cgma
GeometryModifyTool.cpp
Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 // Filename      : GeometryModifyTool.cpp
00003 //
00004 // Purpose       : The tool used to create and modify geometry
00005 //
00006 // Special Notes :
00007 //
00008 // Creator       : Tim Tautges
00009 //
00010 // Creation Date : 2/01
00011 //
00012 //-------------------------------------------------------------------------
00013 
00014 #include <string.h>
00015 #include <assert.h>
00016 #include <stdlib.h>
00017 #include <math.h>
00018 #include <sstream>
00019 //#include <iostream>
00020 
00021 #include "GeometryModifyTool.hpp"
00022 #include "CubitDefines.h"
00023 #include "GeometryDefines.h"
00024 #include "GeometryEntity.hpp"
00025 #include "GeometryQueryTool.hpp"
00026 #include "MergeTool.hpp"
00027 #include "SurfaceOverlapTool.hpp"
00028 #include "GeometryQueryEngine.hpp"
00029 #include "OldUnmergeCode.hpp"
00030 #include "GeometryModifyEngine.hpp"
00031 #include "AnalyticGeometryTool.hpp"
00032 #include "DAG.hpp"
00033 #include "TopologyBridge.hpp"
00034 #include "ModelQueryEngine.hpp"
00035 #include "CADefines.hpp"
00036 #include "GeomMeasureTool.hpp"
00037 #include "LocalToleranceTool.hpp"
00038 
00039 #include "RefEntity.hpp"
00040 #include "RefEntityFactory.hpp"
00041 #include "RefEntityName.hpp"
00042 #include "BasicTopologyEntity.hpp"
00043 #include "RefVertex.hpp"
00044 #include "RefEdge.hpp"
00045 #include "RefFace.hpp"
00046 #include "RefVolume.hpp"
00047 
00048 #include "CoVertex.hpp"
00049 #include "CoEdge.hpp"
00050 #include "CoFace.hpp"
00051 #include "CoVolume.hpp"
00052 
00053 #include "Chain.hpp"
00054 #include "Loop.hpp"
00055 #include "Shell.hpp"
00056 #include "Body.hpp"
00057 
00058 #include "Lump.hpp"
00059 #include "Surface.hpp"
00060 #include "Curve.hpp"
00061 #include "Point.hpp"
00062 #include "BodySM.hpp"
00063 #include "ShellSM.hpp"
00064 #include "LoopSM.hpp"
00065 #include "CoEdgeSM.hpp"
00066 
00067 #include "CubitAttrib.hpp"
00068 #include "CubitVector.hpp"
00069 #include "CubitPlane.hpp"
00070 #include "CubitTransformMatrix.hpp"
00071 #include "GfxPreview.hpp"
00072 #include "AppUtil.hpp"
00073 
00074 #include "DLIList.hpp"
00075 
00076 #include "CubitMessage.hpp"
00077 #include "SettingHandler.hpp"
00078 
00079 #include "CastTo.hpp"
00080 #include "CpuTimer.hpp"
00081 
00082 #include "BridgeManager.hpp"
00083 #include "SplitSurfaceTool.hpp"
00084 #include "OffsetSplitTool.hpp"
00085 #include "AutoMidsurfaceTool.hpp"
00086 #include "TDSurfaceOverlap.hpp"
00087 #include "GfxDebug.hpp"
00088 
00089 #include "CubitUndo.hpp"
00090 
00091 /* Work around stupid #define hz equal to HZ on IBM */
00092 #ifdef hz
00093 #  undef hz
00094 #endif
00095 #ifdef PROE
00096 #include "CompositeTool.hpp"
00097 #endif
00098 
00099 GeometryModifyTool* GeometryModifyTool::instance_ = 0;
00100 CubitBoolean GeometryModifyTool::allEdgesImprint = CUBIT_TRUE;
00101 CubitBoolean GeometryModifyTool::groupImprint = CUBIT_TRUE;
00102 CubitBoolean GeometryModifyTool::newIds = CUBIT_FALSE;
00103 CubitBoolean GeometryModifyTool::sepAfterWebcut = CUBIT_TRUE;
00104 CubitBoolean GeometryModifyTool::booleanRegularize = CUBIT_TRUE;
00105 CubitBoolean GeometryModifyTool::uniteMixedModels = CUBIT_TRUE;
00106 CubitBoolean GeometryModifyTool::oldNames = CUBIT_FALSE;
00107 CubitBoolean GeometryModifyTool::meshAutodelete = CUBIT_TRUE;
00108 CubitBoolean GeometryModifyTool::meshAutodeleteRemesh = CUBIT_FALSE;
00109 RefEntity* GeometryModifyTool::copyingEntity = NULL;
00110 
00111 CubitStatus prepare_surface_sweep(
00112                               DLIList<BodySM*> &blank_bodies,
00113                               DLIList<Surface*> &surfaces,
00114                               const CubitVector& sweep_vector,
00115                               bool sweep_perp,
00116                               bool through_all,
00117                               bool outward,
00118                               bool up_to_next,
00119                               Surface *stop_surf,
00120                               Curve *curve_to_sweep_along,
00121                               BodySM* &cutting_tool_ptr ,
00122                               const CubitVector* point = NULL,
00123                               double *angle = NULL);
00124   // prepare for webcut with swept_surfaces. if point and angle is known,
00125   // do surface sweep rotated; or if curve_to_sweep_along is known, do
00126   // sweep along curve; then if sweep_perp is true, do perpendicular sweep
00127   // of the surfaces; lastly do sweep along vector.
00128 
00129 CubitStatus webcut_w_cylinder( DLIList<BodySM*> &webcut_body_list,
00130                                double radius,
00131                                const CubitVector &axis,
00132                                const CubitVector &center,
00133                                DLIList<BodySM*>& neighbor_imprint_list,
00134                                DLIList<BodySM*>& results_list,
00135                                ImprintType imprint_type = NO_IMPRINT );
00136   //- webcuts a body using a cylinder given the input parameters.
00137 
00138 //-------------------------------------------------------------------------
00139 // Purpose       : Controls access and creation of the sole instance of this
00140 //                 class.
00141 //
00142 // Special Notes :
00143 //
00144 // Creator       : Xuechen Liu
00145 //
00146 // Creation Date : 07/11/96
00147 //-------------------------------------------------------------------------
00148 
00149 GeometryModifyTool* GeometryModifyTool::instance(GeometryModifyEngine *GMEPtr)
00150 {
00151      // Check to see if we have created an instance of the class
00152      // If not, proceed to create one.
00153 
00154    if (instance_ == 0)
00155    {
00156         // When creating the instance, we should always have a valid
00157         // SMEPtr. If not, complain.
00158 
00159      instance_ = new GeometryModifyTool (GMEPtr) ;
00160 
00161         // check to make sure there's a ref entity factory extant
00162      //RefEntityFactory *factory =
00163      RefEntityFactory::instance();
00164    }
00165 
00166      // If there is an existing instance of the class, check if there
00167      // was a request to set default solid modeling engine. If so, be nice
00168      // to the calling routine :) :) and kindly set the default solid
00169      // modeling engine.
00170 
00171    else if ( GMEPtr != NULL && instance_->gmeList.move_to(GMEPtr)) {
00172      delete instance_->gmeList.remove();
00173      instance_->gmeList.insert(GMEPtr);
00174    }
00175 
00176      // Return the a pointer to the instance of the class.
00177 
00178    return instance_ ;
00179 }
00180 
00181 //-------------------------------------------------------------------------
00182 // Purpose       : Destructor.
00183 //
00184 // Special Notes :
00185 //
00186 // Creator       : Xuechen Liu
00187 //
00188 // Creation Date : 07/11/96
00189 //-------------------------------------------------------------------------
00190 GeometryModifyTool::~GeometryModifyTool ()
00191 {
00192    instance_ = NULL;
00193      //Kill the geometry modify engine(s)
00194    int i;
00195    for (i = gmeList.size(); i > 0; i--)
00196      delete gmeList.get_and_step();
00197 
00198    gmeList.clean_out();
00199 }
00200 
00201 //-------------------------------------------------------------------------
00202 // Purpose       : Deletes instance variable
00203 //
00204 // Special Notes :
00205 //
00206 // Creator       : Corey Ernst
00207 //
00208 // Creation Date : 12/31/07
00209 //-------------------------------------------------------------------------
00210 void GeometryModifyTool::delete_instance()
00211 {
00212   if( NULL != instance_ )
00213   {
00214     delete instance_;
00215     instance_ = NULL;
00216   }
00217 }
00218 
00219 //-------------------------------------------------------------------------
00220 // Purpose       : Creates a Body corresponding to a sphere with the
00221 //                 given radius
00222 //
00223 // Special Notes :
00224 //
00225 // Creator       : Jihong Ma
00226 //
00227 // Creation Date : 09/18/96
00228 //-------------------------------------------------------------------------
00229 Body* GeometryModifyTool::sphere(double radius,
00230                                  int x_shift,
00231                                  int y_shift,
00232                                  int z_shift,
00233                                  double inner_radius,
00234                                  bool delete_side )
00235 {
00236    if (0 == gmeList.size())
00237    {
00238       PRINT_WARNING("No active geometry engine.\n");
00239       return NULL;
00240    }
00241 
00242      // First make sure the radius is not zero or less
00243    if ( radius <= 0.0 )
00244    {
00245       PRINT_ERROR("In GeometryModifyTool::sphere\n"
00246                   "       Cannot make a sphere of radius %f\n",
00247                   radius);
00248       return NULL ;
00249    }
00250 
00251   if( CubitUndo::get_undo_enabled() )
00252     CubitUndo::save_state();
00253 
00254   GeometryModifyEngine *gme = gmeList.get();
00255 
00256   BodySM* body_sm = gme->sphere(radius);
00257 
00258   if (x_shift != 0 || y_shift != 0 || z_shift != 0)
00259   {
00260     BodySM *brick = gme->brick( 2.0 * radius,
00261                                 2.0 * radius,
00262                                 2.0 * radius);
00263 
00264     CubitVector delta( x_shift * radius,
00265                        y_shift * radius,
00266                        z_shift * radius );
00267 
00268     gme->get_gqe()->translate( brick, delta );
00269 
00270     DLIList<BodySM*> new_sms;
00271     DLIList<BodySM*> from_bodies(1);
00272     from_bodies.append( body_sm );
00273     bool keep_old = true;
00274     CubitStatus bool_status;
00275     if( delete_side == false )
00276        bool_status = gme->intersect( brick, from_bodies, new_sms, keep_old );
00277     else
00278     {
00279       DLIList<BodySM*> tool_bodies(1);
00280       tool_bodies.append( brick );
00281       bool imprint = false;
00282       bool_status = gme->subtract( tool_bodies, from_bodies, new_sms, imprint, keep_old );
00283     }
00284 
00285     //delete the old bodies
00286     gme->get_gqe()->delete_solid_model_entities( body_sm );
00287     gme->get_gqe()->delete_solid_model_entities( brick );
00288 
00289     if( bool_status == CUBIT_FAILURE || new_sms.size() == 0 )
00290     {
00291       PRINT_ERROR("Problems creating sphere.\n" );
00292       return NULL ;
00293     }
00294 
00295     body_sm = new_sms.get();
00296   }
00297 
00298   Body *new_body = NULL;
00299   BodySM* inner_body_sm = NULL;
00300   if( inner_radius )
00301   {
00302     inner_body_sm = gme->sphere(inner_radius);
00303     DLIList<BodySM*> new_sms;
00304     DLIList<BodySM*> from_bodies(1);
00305     DLIList<BodySM*> tool_bodies(1);
00306     from_bodies.append( body_sm );
00307     tool_bodies.append( inner_body_sm );
00308     bool imprint = false;
00309     bool keep_old = true;
00310     CubitStatus subtract_status =
00311        gme->subtract( tool_bodies, from_bodies, new_sms, imprint, keep_old );
00312 
00313      //delete the old bodies
00314     gme->get_gqe()->delete_solid_model_entities( body_sm );
00315     gme->get_gqe()->delete_solid_model_entities( inner_body_sm );
00316 
00317     if( subtract_status == CUBIT_FAILURE || new_sms.size() == 0 )
00318     {
00319       PRINT_ERROR("Problems creating sphere with inner radius.\n" );
00320       return NULL ;
00321     }
00322 
00323     body_sm = new_sms.get();
00324   }
00325 
00326   if (!body_sm)
00327   {
00328      PRINT_ERROR("In GeometryModifyTool::sphere\n"
00329                  "       Problems building a volume from the sphere.\n");
00330   }
00331   else
00332     new_body = GeometryQueryTool::instance()->make_Body(body_sm);
00333 
00334   if( CubitUndo::get_undo_enabled() )
00335   {
00336     if( new_body )
00337       CubitUndo::note_result_body( new_body );
00338     else
00339       CubitUndo::remove_last_undo();
00340   }
00341 
00342   return new_body;
00343 }
00344 
00345 //-------------------------------------------------------------------------
00346 // Purpose       : Creates a Body corresponding to a brick with given width,
00347 //                 depth, and height.
00348 //
00349 // Special Notes :
00350 //
00351 // Creator       : Jihong Ma
00352 //
00353 // Creation Date : 09/18/96
00354 //-------------------------------------------------------------------------
00355 Body* GeometryModifyTool::brick(double width, double depth, double height)
00356 {
00357    if (0 == gmeList.size())
00358    {
00359       PRINT_WARNING("No active geometry engine.\n");
00360       return NULL;
00361    }
00362 
00363      // First make sure that none of the input values are zero or less
00364    if ( width <= GEOMETRY_RESABS || depth <= GEOMETRY_RESABS || height <= GEOMETRY_RESABS )
00365    {
00366       PRINT_ERROR("In GeometryModifyTool::brick\n"
00367                   "    Cannot make a cuboid of size %f x %f x %f\n"
00368                   "       All dimensions must be > 0.0\n",
00369                   width, depth, height);
00370       return NULL;
00371    }
00372 
00373   if( CubitUndo::get_undo_enabled() )
00374     CubitUndo::save_state();
00375 
00376    Body *new_body = NULL;
00377    BodySM* bodyPtr = gmeList.get()->brick(width, depth, height);
00378 
00379    if (bodyPtr == NULL)
00380    {
00381       PRINT_ERROR("In GeometryModifyTool::brick\n"
00382                   "       Problem creating a brick.\n") ;
00383    }
00384    else
00385      new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
00386 
00387   if( CubitUndo::get_undo_enabled() )
00388   {
00389     if( new_body )
00390       CubitUndo::note_result_body( new_body );
00391     else
00392       CubitUndo::remove_last_undo();
00393   }
00394 
00395    return new_body;
00396 }
00397 
00398 #ifdef KCM_MESH_TO_GEOM
00399 //-------------------------------------------------------------------------
00400 // Purpose       : Create breps from mesh entities.
00401 //
00402 // Special Notes :
00403 //
00404 // Creator       : Brett Clark
00405 //
00406 // Creation Date : 12/21/2010
00407 //-------------------------------------------------------------------------
00408 CubitStatus GeometryModifyTool::mesh2brep(std::vector<double> &xvals,
00409                         std::vector<double> &yvals,
00410                         std::vector<double> &zvals,
00411                         std::vector<unsigned int> &tri_connectivity,
00412                         DLIList<BodySM*> &new_body_sms)
00413 {
00414   if (0 == gmeList.size())
00415   {
00416     PRINT_WARNING("No active geometry engine.\n");
00417     return CUBIT_FAILURE;
00418   }
00419 
00420   return gmeList.get()->mesh2brep(xvals, yvals, zvals, tri_connectivity, new_body_sms);
00421 }
00422 #endif
00423 
00424 //-------------------------------------------------------------------------
00425 // Purpose       : Creates a Body corresponding to a brick at given location,
00426 //                 orientation, and size.
00427 //
00428 // Special Notes : If one of the dimensions is zero, a planar sheet is created.
00429 //
00430 // Creator       : Steve Storm
00431 //
00432 // Creation Date : 10/09/2000
00433 //-------------------------------------------------------------------------
00434 Body* GeometryModifyTool::brick(const CubitVector &center,
00435                                 const CubitVector axes[3],
00436                                 const CubitVector &extension)
00437 {
00438    if (0 == gmeList.size())
00439    {
00440       PRINT_WARNING("No active geometry engine.\n");
00441       return NULL;
00442    }
00443 
00444    double width = 2.0*extension.x();
00445    double height = 2.0*extension.y();
00446    double depth = 2.0*extension.z();
00447      // First make sure that entity creation is possible.  Allow at most
00448      // only one of the dimensions to be zero - in which case a planar
00449      // sheet is created.
00450    if ( width < 0.0 || height < 0.0 || depth < 0.0 )
00451    {
00452       PRINT_ERROR( "Cannot make a brick of size %f x %f x %f\n"
00453                    "     Negative dimensions are not allowed.\n",
00454                    width, height, depth );
00455       return NULL ;
00456    }
00457 
00458    int wz = width < GEOMETRY_RESABS;
00459    int hz = height < GEOMETRY_RESABS;
00460    int dz = depth < GEOMETRY_RESABS;
00461    if( wz || hz || dz )
00462    {
00463       if( (wz + hz + dz) > 1 )
00464       {
00465          PRINT_ERROR( "Cannot make a sheet of size %f x %f x %f\n"
00466             "     At least two dimensions must be nonzero.\n",
00467             width, height, depth );
00468          return NULL ;
00469       }
00470 
00471       // Make a sheet body instead of a cuboid
00472       CubitVector sheet_axes[2];
00473       if( wz )
00474       {
00475          sheet_axes[0] = axes[1];
00476          sheet_axes[1] = axes[2];
00477          return planar_sheet( center, sheet_axes, height, depth );
00478       }
00479       else if( hz )
00480       {
00481          sheet_axes[0] = axes[2];
00482          sheet_axes[1] = axes[0];
00483          return planar_sheet( center, sheet_axes, depth, width );
00484       }
00485       else
00486       {
00487          sheet_axes[0] = axes[0];
00488          sheet_axes[1] = axes[1];
00489          return planar_sheet( center, sheet_axes, width, height );
00490       }
00491    }
00492    else
00493    {
00494       if( CubitUndo::get_undo_enabled() )
00495         CubitUndo::save_state();
00496 
00497       BodySM* bodyPtr = gmeList.get()->brick(center, axes, extension) ;
00498       Body *new_body = NULL;
00499       if (bodyPtr == NULL)
00500       {
00501          PRINT_ERROR("In GeometryTool::brick\n"
00502             "       Problem creating a brick.\n") ;
00503       }
00504       else
00505         new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
00506 
00507       if( CubitUndo::get_undo_enabled() )
00508       {
00509         if( new_body )
00510           CubitUndo::note_result_body( new_body );
00511         else
00512           CubitUndo::remove_last_undo();
00513       }
00514 
00515       return new_body;
00516    }
00517 }
00518 
00519 //-------------------------------------------------------------------------
00520 // Purpose       : Creates a Body corresponding to a prism with height,
00521 //                 sides, major, minor radii
00522 //
00523 //
00524 // Special Notes :
00525 //
00526 // Creator       : Jihong Ma
00527 //
00528 // Creation Date : 09/18/96
00529 //-------------------------------------------------------------------------
00530 Body* GeometryModifyTool::prism( double height, int sides, double major, double minor)
00531 {
00532    if (0 == gmeList.size())
00533    {
00534       PRINT_WARNING("No active geometry engine.\n");
00535       return NULL;
00536    }
00537 
00538      // First make sure that the input values make sense
00539    if ( major < minor ||
00540         major <= GEOMETRY_RESABS || minor <= GEOMETRY_RESABS ||
00541         height <= GEOMETRY_RESABS || sides < 3 )
00542    {
00543       PRINT_ERROR("In GeometryModifyTool::prism\n"
00544                   "   Cannot make a prism of major-radius = %f,"
00545                   " minor-radius = %f, height = %f, and"
00546                   " number of sides = %d\n"
00547                   "   All dimensions must be > 0.0, the major-radius\n"
00548                   " should be greater than or equal to the minor-"
00549                   "radius,\n and the number of sides should be greater"
00550                   " than 2.\n", major, minor, height, sides);
00551 
00552       return NULL;
00553    }
00554 
00555    if( CubitUndo::get_undo_enabled() )
00556      CubitUndo::save_state();
00557 
00558      // Create a Body that represents the prism
00559    BodySM* bodyPtr = gmeList.get()->prism(height,  sides, major, minor) ;
00560    Body *new_body = NULL;
00561    if (bodyPtr == NULL)
00562    {
00563       PRINT_ERROR("In GeometryModifyTool::prism\n"
00564                   "       Problems building a volume from the prism.\n") ;
00565    }
00566    else
00567      new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
00568 
00569   if( CubitUndo::get_undo_enabled() )
00570   {
00571     if( new_body )
00572       CubitUndo::note_result_body( new_body );
00573     else
00574       CubitUndo::remove_last_undo();
00575   }
00576 
00577    return new_body;
00578 }
00579 
00580 //-------------------------------------------------------------------------
00581 // Purpose       : Creates a Body corresponding to a pyramid with given
00582 //                 height, major, minor,top, sides
00583 //
00584 // Special Notes :
00585 //
00586 // Creator       : Jihong Ma
00587 //
00588 // Creation Date : 09/18/96
00589 //-------------------------------------------------------------------------
00590 Body* GeometryModifyTool::pyramid  ( double height, int sides, double major,
00591                              double minor,  double top)
00592 {
00593    if (0 == gmeList.size())
00594    {
00595       PRINT_WARNING("No active geometry engine.\n");
00596       return NULL;
00597    }
00598 
00599      // First make sure that the input values make sense
00600    if ( major < minor ||
00601         major <= GEOMETRY_RESABS || minor <= GEOMETRY_RESABS ||
00602         height <= GEOMETRY_RESABS || top < 0.0 || sides < 3  )
00603    {
00604       PRINT_ERROR("In GeometryModifyTool::pyramid\n"
00605                   "    Cannot make a pyramid of major-radius = %f,"
00606                   " minor-radius = %f, height = %f,"
00607                   " top %f, and number of sides = %d\n"
00608                   "     All dimensions must be > 0.0, the major-radius"
00609                   " should be greater than the minor-radius, the "
00610                   "number of sides should be greater than 2.\n",
00611                   major, minor, height, top, sides);
00612       return NULL;
00613    }
00614 
00615    if( CubitUndo::get_undo_enabled() )
00616      CubitUndo::save_state();
00617 
00618      // Create a Body that represents the prism
00619    BodySM* bodyPtr = gmeList.get()->pyramid ( height, sides, major, minor, top);
00620    Body *new_body = NULL;
00621    if (bodyPtr == NULL)
00622    {
00623       PRINT_ERROR("In GeometryModifyTool::pyramid\n"
00624                   "      Problems building a volume from the pyramid.\n");
00625    }
00626    else
00627      new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
00628 
00629   if( CubitUndo::get_undo_enabled() )
00630   {
00631     if( new_body )
00632       CubitUndo::note_result_body( new_body );
00633     else
00634       CubitUndo::remove_last_undo();
00635   }
00636 
00637    return new_body;
00638 }
00639 
00640 //-------------------------------------------------------------------------
00641 // Purpose       : Creates a Body corresponding to a frustum of a cone with
00642 //                 height,
00643 //                 input radius in x-direction at base
00644 //                 input radius in y-direction at base
00645 //                 input radius in x-direction at top
00646 //
00647 // Special Notes :
00648 //
00649 // Creator       : Jihong Ma
00650 //
00651 // Creation Date : 09/18/96
00652 //-------------------------------------------------------------------------
00653 Body* GeometryModifyTool::cylinder ( double hi, double r1, double r2, double r3 )
00654 {
00655    if (0 == gmeList.size())
00656    {
00657       PRINT_WARNING("No active geometry engine.\n");
00658       return NULL;
00659    }
00660 
00661      // First make sure that the input values make sense
00662    if ( hi <= GEOMETRY_RESABS || r1 <= GEOMETRY_RESABS ||
00663         r2 <= GEOMETRY_RESABS || r3 < 0.0 )
00664    {
00665       PRINT_ERROR("In GeometryModifyTool::cylinder\n"
00666                   " Cannot make a frustum of a cone with height = %f,"
00667                   " lower x-direction radius = %f,"
00668                   " lower y-direction radius = %f, and "
00669                   "top radius = %f\n"
00670                   "       All dimensions must be > 0.0\n",
00671                   hi, r1, r2, r3);
00672       return NULL;
00673    }
00674 
00675    if( CubitUndo::get_undo_enabled() )
00676      CubitUndo::save_state();
00677 
00678      // Create a Body that represents the prism
00679    BodySM* bodyPtr = gmeList.get()->cylinder( hi, r1, r2, r3);
00680    Body *new_body = NULL;
00681 
00682    if (bodyPtr == NULL)
00683    {
00684       PRINT_ERROR("In GeometryModifyTool::cylinder\n"
00685                   "       Problems building a volume from the conical frustum.\n");
00686    }
00687    else
00688      new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
00689 
00690   if( CubitUndo::get_undo_enabled() )
00691   {
00692     if( new_body )
00693       CubitUndo::note_result_body( new_body );
00694     else
00695       CubitUndo::remove_last_undo();
00696   }
00697 
00698    return new_body;
00699 }
00700 
00701 //-------------------------------------------------------------------------
00702 // Purpose       : Creates a Body corresponding to a torus with major_radius
00703 //                 and minor_radius
00704 //
00705 //
00706 // Special Notes :
00707 //
00708 // Creator       : Jihong Ma
00709 //
00710 // Creation Date : 09/18/96
00711 //-------------------------------------------------------------------------
00712 Body* GeometryModifyTool::torus( double r1, double r2 )
00713 {   if (0 == gmeList.size())
00714    {
00715       PRINT_WARNING("No active geometry engine.\n");
00716       return NULL;
00717    }
00718 
00719 
00720      // First make sure that the input values make sense
00721    if ( r1 <= r2 || r1 <= GEOMETRY_RESABS || r2 <= 0.0)
00722    {
00723       PRINT_ERROR("In GeometryModifyTool::torus\n"
00724                   "  Cannot make a torus of major-radius = %f and"
00725                   " minor-radius = %f\n",
00726                   r1, r2);
00727       return NULL;
00728    }
00729 
00730    if( CubitUndo::get_undo_enabled() )
00731      CubitUndo::save_state();
00732 
00733      // Create a Body that represents the torus
00734    BodySM* bodyPtr = gmeList.get()->torus(r1, r2) ;
00735    Body *new_body = NULL;
00736 
00737    if (bodyPtr == NULL)
00738    {
00739       PRINT_ERROR("In GeometryModifyTool::torus\n"
00740                   "       Problems building a volume from the torus.\n") ;
00741    }
00742    else
00743      new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
00744 
00745   if( CubitUndo::get_undo_enabled() )
00746   {
00747     if( new_body )
00748       CubitUndo::note_result_body( new_body );
00749     else
00750       CubitUndo::remove_last_undo();
00751   }
00752 
00753    return new_body;
00754 }
00755 
00756 //-------------------------------------------------------------------------
00757 // Purpose       : Creates a planar sheet with the given corner locations.
00758 //
00759 // Special Notes :
00760 //
00761 // Creator       : Steve Storm
00762 //
00763 // Creation Date : 05/10/05
00764 //-------------------------------------------------------------------------
00765 Body* GeometryModifyTool::planar_sheet( const CubitVector& p1,
00766                                         const CubitVector& p2,
00767                                         const CubitVector& p3,
00768                                         const CubitVector& p4 )
00769 {
00770    if (0 == gmeList.size())
00771    {
00772       PRINT_WARNING("No active geometry engine.\n");
00773       return NULL;
00774    }
00775 
00776    if( CubitUndo::get_undo_enabled() )
00777      CubitUndo::save_state();
00778 
00779   // Create a Body that represents the sheet
00780   BodySM* body_ptr = gmeList.get()->planar_sheet(p1, p2, p3, p4) ;
00781   Body *new_body = NULL;
00782   if( body_ptr == NULL )
00783   {
00784     PRINT_ERROR("In GeometryTool::planar_sheet\n"
00785       "       Problems building a volume from the sheet.\n") ;
00786   }
00787   else
00788     new_body = GeometryQueryTool::instance()->make_Body(body_ptr);
00789 
00790   if( CubitUndo::get_undo_enabled() )
00791   {
00792     if( new_body )
00793       CubitUndo::note_result_body( new_body );
00794     else
00795       CubitUndo::remove_last_undo();
00796   }
00797 
00798   return new_body;
00799 }
00800 
00801 //-------------------------------------------------------------------------
00802 // Purpose       : Creates a planar sheet with the given input location,
00803 //                 orientation and size.
00804 //
00805 // Special Notes :
00806 //
00807 // Creator       : Steve Storm
00808 //
00809 // Creation Date : 10/09/00
00810 //-------------------------------------------------------------------------
00811 Body* GeometryModifyTool::planar_sheet ( const CubitVector &center,
00812                                          const CubitVector axes[2],
00813                                          double width, double height )
00814 {
00815    if (0 == gmeList.size())
00816    {
00817       PRINT_WARNING("No active geometry engine.\n");
00818       return NULL;
00819    }
00820 
00821    CubitVector p1, p2, p3, p4;
00822 
00823    // Get the corners of the sheet
00824    center.next_point( axes[0], width/2.0, p1 );
00825    p1.next_point( axes[1], -height/2.0, p1 );
00826    p1.next_point( axes[1], height, p2 );
00827    p2.next_point( axes[0], -width, p3 );
00828    p3.next_point( axes[1], -height, p4 );
00829 
00830    if( CubitUndo::get_undo_enabled() )
00831      CubitUndo::save_state();
00832 
00833    // Create a Body that represents the sheet
00834    BodySM* body_ptr = gmeList.get()->planar_sheet(p1, p2, p3, p4) ;
00835    Body *new_body = NULL;
00836 
00837    if( body_ptr == NULL )
00838    {
00839       PRINT_ERROR("In GeometryTool::planar_sheet\n"
00840          "       Problems building a volume from the sheet.\n") ;
00841    }
00842    else
00843      new_body = GeometryQueryTool::instance()->make_Body(body_ptr);
00844 
00845   if( CubitUndo::get_undo_enabled() )
00846   {
00847     if( new_body )
00848       CubitUndo::note_result_body( new_body );
00849     else
00850       CubitUndo::remove_last_undo();
00851   }
00852 
00853   return new_body;
00854 }
00855 
00856 //-------------------------------------------------------------------------
00857 // Purpose       : Creates a planar sheet with the minimal amount of area
00858 //                 to cut through the given 3D bounding box.  The sheet
00859 //                 can be extended optionally to make it larger than this
00860 //                 minimal size.
00861 //
00862 // Special Notes : extension_types: 0-none, 1-percentage, 2-absolute
00863 //
00864 // Creator       : Steve Storm
00865 //
00866 // Creation Date : 10/19/98
00867 //-------------------------------------------------------------------------
00868 Body* GeometryModifyTool::planar_sheet ( const CubitPlane& plane,
00869                                          const CubitBox& bounding_box,
00870                                          int extension_type,
00871                                          double extension )
00872 {
00873    if (0 == gmeList.size())
00874    {
00875       PRINT_WARNING("No active geometry engine.\n");
00876       return NULL;
00877    }
00878 
00879    CubitVector p1, p2, p3, p4;
00880 
00881    // Get the corners of the sheet
00882    if( AnalyticGeometryTool::instance()->
00883       min_pln_box_int_corners( plane, bounding_box, extension_type,
00884                                extension, p1, p2, p3, p4 ) == CUBIT_FAILURE )
00885       return NULL;
00886 
00887    if( CubitUndo::get_undo_enabled() )
00888      CubitUndo::save_state();
00889 
00890    // Create a Body that represents the sheet
00891    BodySM* body_ptr = gmeList.get()->planar_sheet(p1, p2, p3, p4) ;
00892    Body *new_body = NULL;
00893 
00894    if( body_ptr == NULL )
00895    {
00896       PRINT_ERROR("In GeometryModifyTool::planar_sheet\n"
00897          "       Problems building a volume from the sheet.\n") ;
00898    }
00899    else
00900      new_body = GeometryQueryTool::instance()->make_Body(body_ptr);
00901 
00902    if( CubitUndo::get_undo_enabled() )
00903    {
00904      if( new_body )
00905        CubitUndo::note_result_body( new_body );
00906      else
00907        CubitUndo::remove_last_undo();
00908    }
00909 
00910    return new_body;
00911 }
00912 
00913 Body* GeometryModifyTool::create_body( VolumeFacets& volume, std::map<FacetShapes*, RefEntity*>& entity_map,
00914                                        const FacetPointSet& points, int interp_order)
00915 {
00916   GeometryModifyEngine* engine = gmeList.get();
00917   if (!engine->supports_facets())
00918     return NULL;
00919 
00920   Body* new_body = NULL;
00921 
00922   if( CubitUndo::get_undo_enabled() )
00923      CubitUndo::save_state();
00924 
00925   std::map<FacetShapes*, GeometryEntity*> geom_entity_map;
00926   BodySM* body_sm = engine->create_body(volume, geom_entity_map, points, interp_order);
00927   if(body_sm)
00928   {
00929     new_body = GeometryQueryTool::instance()->make_Body(body_sm);
00930     // map information back to caller
00931     std::map<FacetShapes*, GeometryEntity*>::iterator geom_iter;
00932     for (geom_iter = geom_entity_map.begin(); geom_iter != geom_entity_map.end(); geom_iter++)
00933       entity_map[geom_iter->first] = dynamic_cast<RefEntity*>(geom_iter->second->topology_entity());
00934   }
00935 
00936   if( CubitUndo::get_undo_enabled() )
00937   {
00938     if( new_body )
00939       CubitUndo::note_result_body( new_body );
00940     else
00941       CubitUndo::remove_last_undo();
00942   }
00943 
00944   return new_body;
00945 }
00946 
00947 RefVertex* GeometryModifyTool::make_RefVertex( RefVertex *vertex ) const
00948 {
00949   if ( vertex == NULL )
00950   {
00951     PRINT_ERROR("Vertex is NULL\n");
00952     return NULL;
00953   }
00954 
00955   TopologyBridge* bridge = 0;
00956   GeometryModifyEngine* engine = get_engine(vertex, &bridge);
00957   if (engine == NULL)
00958   {
00959      PRINT_ERROR( "%s (vertex %d) does not have a modify engine.\n",
00960                   vertex->entity_name().c_str(),
00961                   vertex->id() );
00962      return 0;
00963   }
00964 
00965   CubitVector point = vertex->coordinates();
00966 
00967   // Call the default GeometryModifyEngine to create a new TBPoint
00968   TBPoint* point_ptr = engine->make_Point(point);
00969 
00970   if( CubitUndo::get_undo_enabled() )
00971     CubitUndo::save_state();
00972 
00973   // Use the TBPoint to create a RefVertex
00974   RefVertex* ref_vertex_ptr = RefEntityFactory::instance()->construct_RefVertex(point_ptr) ;
00975 
00976   if( CubitUndo::get_undo_enabled() )
00977   {
00978     if( ref_vertex_ptr )
00979       CubitUndo::note_result_entity( ref_vertex_ptr );
00980     else
00981       CubitUndo::remove_last_undo();
00982   }
00983 
00984   //transfer the names
00985   DLIList<CubitString> names;
00986   vertex->entity_names( names );
00987 
00988   int i;
00989   for( i=names.size(); i--; )
00990   {
00991     CubitString tmp_name = names.get_and_step();
00992     ref_vertex_ptr->entity_name( tmp_name );
00993   }
00994 
00995   // Send a message to the model indicating the vertex was created
00996   AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, ref_vertex_ptr));
00997 
00998   // Return the newly created RefVertex
00999   return ref_vertex_ptr ;
01000 }
01001 
01002 
01003 //-------------------------------------------------------------------------
01004 // Purpose       : This function takes a type information and a location
01005 //                 to create a RefVertex. The underlying representation
01006 //                 of the RefVertex is determined by the default
01007 //                 GeometryModifyEngine.
01008 //
01009 // Special Notes :
01010 //
01011 // Creator       : Raikanta Sahu
01012 //
01013 // Creation Date : 03/27/97
01014 //-------------------------------------------------------------------------
01015 
01016 RefVertex* GeometryModifyTool::make_RefVertex(
01017                                         CubitVector const& point, int color) const
01018 {
01019    if (0 == gmeList.size())
01020    {
01021       PRINT_WARNING("No active geometry engine.\n");
01022       return NULL;
01023    }
01024 
01025      // Call the default GeometryModifyEngine to create a new TBPoint
01026    TBPoint* point_ptr = gmeList.get()->make_Point(point);
01027 
01028      // If we get a NULL pointer, give a warning message and return
01029      // a NULL pointer.
01030    if ( point_ptr == NULL )
01031    {
01032       PRINT_WARNING("In GeometryModifyTool::make_RefVertex\n"
01033                     "         Got a NULL pointer to a TBPoint.\n"
01034                     "         Cannot make a RefVertex.\n") ;
01035       return (RefVertex *)NULL ;
01036    }
01037 
01038    if( CubitUndo::get_undo_enabled() )
01039      CubitUndo::save_state();
01040 
01041      // Use the TBPoint to create a RefVertex
01042    RefVertex* ref_vertex_ptr = RefEntityFactory::instance()->construct_RefVertex(point_ptr) ;
01043 
01044   if( CubitUndo::get_undo_enabled() )
01045   {
01046     if( ref_vertex_ptr )
01047       CubitUndo::note_result_entity( ref_vertex_ptr );
01048     else
01049       CubitUndo::remove_last_undo();
01050   }
01051 
01052    ref_vertex_ptr->color(color);
01053 
01054      // Send a message to the model indicating the vertex was created
01055    AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::FREE_REF_ENTITY_GENERATED, ref_vertex_ptr));
01056 
01057      // Return the newly created RefVertex
01058    return ref_vertex_ptr ;
01059 }
01060 
01061 Body *GeometryModifyTool::make_Body(Surface *surface) const
01062 {
01063   // make a Body from a Surface
01064   BodySM *body_sm = surface->bodysm();
01065 
01066   GeometryModifyEngine* gme = get_engine(surface);
01067 
01068   if (gme && !body_sm)
01069     body_sm = gme->make_BodySM(surface);
01070 
01071   assert(body_sm != 0);
01072 
01073   return GeometryQueryTool::instance()->make_Body(body_sm);
01074 }
01075 
01076 //-------------------------------------------------------------------------
01077 // Purpose       : This function takes RefEdge type information, too
01078 //
01079 // Creator       : David White
01080 //
01081 // Creation Date : 10/9/97
01082 //-------------------------------------------------------------------------
01083 RefEdge* GeometryModifyTool::make_RefEdge(RefEdge *ref_edge_ptr,
01084                                           bool copy_attribs,
01085                                           std::map< RefEntity*, RefEntity* > *old_to_new_map ) const
01086 {
01087   if ( ref_edge_ptr == NULL )
01088   {
01089     PRINT_ERROR("curve is NULL\n");
01090     return (RefEdge*)NULL;
01091   }
01092 
01093   TopologyBridge* bridge = 0;
01094   GeometryModifyEngine* engine = get_engine(ref_edge_ptr, &bridge);
01095   Curve *old_curve = dynamic_cast<Curve*>(bridge);
01096   if (engine == NULL)
01097   {
01098      PRINT_ERROR( "%s (curve %d) does not have a modify engine.\n",
01099                   ref_edge_ptr->entity_name().c_str(),
01100                   ref_edge_ptr->id() );
01101      return 0;
01102   }
01103 
01104   Curve *tmp_curve;
01105   if( copy_attribs )
01106   {
01107     DLIList<RefEntity*> tmp_list;
01108     tmp_list.append( ref_edge_ptr );
01109     TopologyBridge *curve_bridge;
01110     prepare_for_copy( ref_edge_ptr, curve_bridge );
01111     tmp_curve = CAST_TO( curve_bridge, Curve);
01112   }
01113   else
01114     tmp_curve = old_curve;
01115 
01116   std::map<TopologyBridge*, TopologyBridge*> old_tb_to_new_tb;
01117   Curve *new_curve = NULL;
01118   if( old_to_new_map )
01119     new_curve = engine->make_Curve( tmp_curve, &old_tb_to_new_tb );
01120   else 
01121     new_curve = engine->make_Curve( tmp_curve );
01122 
01123   if (!new_curve)
01124   {
01125     if( copy_attribs )
01126       clean_up_from_copy_failure( old_curve );
01127     return (RefEdge *)NULL;
01128   }
01129 
01130   TopologyBridge *new_curve_bridge;
01131   if( copy_attribs )
01132   {
01133     new_curve_bridge = new_curve;
01134     finish_copy( new_curve_bridge, old_curve );
01135     new_curve = CAST_TO( new_curve_bridge, Curve);
01136   }
01137 
01138   if( CubitUndo::get_undo_enabled() )
01139     CubitUndo::save_state();
01140 
01141   // Complete the task of linking this new Curve into the rest of the
01142   // geometry datastructures and return the new RefEdge.
01143   RefEdge *new_ref_edge = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
01144 
01145   if( old_to_new_map )
01146      create_old_to_new_ref_ent_map( old_curve, new_curve, *old_to_new_map, old_tb_to_new_tb );
01147 
01148   if( CubitUndo::get_undo_enabled() )
01149     CubitUndo::note_result_entity( new_ref_edge );
01150 
01151   return new_ref_edge;
01152 }
01153 
01154 CubitStatus GeometryModifyTool::prepare_for_copy( RefEntity *ref_ent,
01155                                                   TopologyBridge *&top_bridge )
01156 {
01157   //save attribute settings
01158   CGMApp::instance()->save_current_attribute_states();
01159 
01160   CGMApp::instance()->attrib_manager()->auto_flag(1);
01161   // Groups are saved directly in the Cubit file, not with attributes
01162   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_GROUP, CUBIT_FALSE);
01163   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_GROUP, CUBIT_FALSE);
01164   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_GROUP, CUBIT_FALSE);
01165   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_GROUP, CUBIT_FALSE);
01166 
01167   // The mesh container is only used for the Exodus save/resore method
01168   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_MESH_CONTAINER, CUBIT_FALSE);
01169   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_MESH_CONTAINER, CUBIT_FALSE);
01170   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_MESH_CONTAINER, CUBIT_FALSE);
01171   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_MESH_CONTAINER, CUBIT_FALSE);
01172 
01173   // Genesis Entities are saved directly in the Cubit file, not with attributes
01174   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_GENESIS_ENTITY, CUBIT_FALSE);
01175   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_GENESIS_ENTITY, CUBIT_FALSE);
01176   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_GENESIS_ENTITY, CUBIT_FALSE);
01177   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_GENESIS_ENTITY, CUBIT_FALSE);
01178 
01179   //Don't save out entity ids
01180   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ENTITY_ID, CUBIT_FALSE);
01181   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_ENTITY_ID, CUBIT_FALSE);
01182   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_ENTITY_ID, CUBIT_FALSE);
01183   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_ENTITY_ID, CUBIT_FALSE);
01184 
01185   //Don't save out graphics
01186   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_GRAPHICS_OPTS, CUBIT_FALSE);
01187   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_GRAPHICS_OPTS, CUBIT_FALSE);
01188   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_GRAPHICS_OPTS, CUBIT_FALSE);
01189   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_GRAPHICS_OPTS, CUBIT_FALSE);
01190 
01191   //Flag to say "we're copying" attributes
01192   copyingEntity = ref_ent;
01193 
01194   //Get all children
01195   DLIList<RefEntity*> child_list;
01196   ref_ent->get_all_child_ref_entities( child_list );
01197 
01198   //Puts attributes on all the entities
01199   child_list.append( ref_ent );
01200   CubitAttribUser::auto_update_cubit_attrib( child_list );
01201 
01202   //Prepare virtual
01203   TopologyEntity *topo_ptr = dynamic_cast<TopologyEntity*>( ref_ent );
01204   top_bridge = topo_ptr->bridge_manager()->topology_bridge();
01205   DLIList<TopologyBridge*> bridge_list;
01206   bridge_list.append( top_bridge );
01207   GeometryQueryTool::instance()->ige_export_geom( bridge_list );
01208 
01209   //Should only have 1 bridge in the list
01210   assert( bridge_list.size() == 1 );
01211   TopologyBridge *tmp_bridge_after = bridge_list.get();
01212   if( top_bridge != tmp_bridge_after)
01213     top_bridge = tmp_bridge_after;
01214 
01215   //Done copying attributes
01216   copyingEntity = NULL;
01217 
01218   return CUBIT_SUCCESS;
01219 
01220 }
01221 
01222 CubitStatus GeometryModifyTool::clean_up_from_copy_failure( TopologyBridge *old_bridge )
01223 {
01224   //Remove attributes on underlying entities of virtual geometry
01225   //entities which do not have corresponding RefEntities.
01226   DLIList<TopologyBridge*> bridge_list;
01227   bridge_list.append( old_bridge );
01228   GeometryQueryTool::instance()->ige_remove_attributes( bridge_list );
01229 
01230   //Remove attributes on original entity and children
01231   DLIList<RefEntity*> child_list;
01232   RefEntity *ref_ent = CAST_TO( old_bridge->topology_entity(), RefEntity );
01233   ref_ent->get_all_child_ref_entities( child_list );
01234   //child_list.append( ref_ent );
01235   CubitAttribUser::clear_all_simple_attrib( child_list );
01236   child_list.clean_out();
01237   child_list.append( ref_ent );
01238   CubitAttribUser::clear_all_simple_attrib( child_list );
01239 
01240   CGMApp::instance()->restore_previous_attribute_states();
01241 
01242 return CUBIT_SUCCESS;
01243 }
01244 
01245 CubitStatus GeometryModifyTool::finish_copy( TopologyBridge *&new_bridge,
01246                                              TopologyBridge *old_bridge )
01247 {
01248   //Remove attributes on underlying entities of virtual geometry
01249   //entities which do not have corresponding RefEntities.
01250   DLIList<TopologyBridge*> bridge_list;
01251   bridge_list.append( old_bridge );
01252   GeometryQueryTool::instance()->ige_remove_attributes( bridge_list );
01253 
01254   //Remove attributes on original entity and children
01255   DLIList<RefEntity*> child_list;
01256   RefEntity *ref_ent = CAST_TO( old_bridge->topology_entity(), RefEntity );
01257   ref_ent->get_all_child_ref_entities( child_list );
01258   //child_list.append( ref_ent );
01259   CubitAttribUser::clear_all_simple_attrib( child_list );
01260   child_list.clean_out();
01261   child_list.append( ref_ent );
01262   CubitAttribUser::clear_all_simple_attrib( child_list );
01263 
01264 
01265   //Restore virtual
01266   //Could create virtual geometry here so the Topology Bridge can change
01267   bridge_list.clean_out();
01268   bridge_list.append( new_bridge );
01269   TopologyBridge *tmp_bridge_before = new_bridge;
01270   GeometryQueryTool::instance()->ige_import_geom( bridge_list );
01271   assert( bridge_list.size() == 1 );
01272   if( tmp_bridge_before != bridge_list.get() )
01273     new_bridge = bridge_list.get();
01274 
01275   //make the RefEntities
01276   Curve *curve = NULL;
01277   Surface *surface = NULL;
01278   Lump *lump = NULL;
01279   BodySM *body = NULL;
01280 
01281   RefEntity *new_ref_ent = NULL;
01282   if( (curve = CAST_TO( new_bridge, Curve ) ) != NULL )
01283     new_ref_ent = GeometryQueryTool::instance()->make_RefEdge( curve );
01284   else if( (surface = CAST_TO( new_bridge, Surface) ) != NULL )
01285     new_ref_ent = GeometryQueryTool::instance()->make_RefFace( surface );
01286   else if( (lump = CAST_TO( new_bridge, Lump) ) != NULL )
01287     new_ref_ent = GeometryQueryTool::instance()->make_Body( lump->bodysm() );
01288   else if( (body = CAST_TO( new_bridge, BodySM) ) != NULL )
01289     new_ref_ent = GeometryQueryTool::instance()->make_Body( body );
01290 
01291   //actuate the attributes on everything
01292   child_list.clean_out();
01293   new_ref_ent->get_all_child_ref_entities( child_list );
01294   child_list.append( new_ref_ent );
01295   GeometryQueryTool::import_actuate( child_list );
01296 
01297   //Remove attributes on new entity and children
01298   child_list.clean_out();
01299   new_ref_ent->get_all_child_ref_entities( child_list );
01300   CubitAttribUser::clear_all_simple_attrib( child_list );
01301   child_list.clean_out();
01302   child_list.append( new_ref_ent );
01303   CubitAttribUser::clear_all_simple_attrib( child_list );
01304 
01305   CGMApp::instance()->restore_previous_attribute_states();
01306   return CUBIT_SUCCESS;
01307 }
01308 #ifdef PROE
01309 CubitStatus GeometryModifyTool::prepare_for_topology_update( BodySM* old_bodysm )
01310 {
01311   DLIList<BodySM*> old_bodysms;
01312   old_bodysms.append(old_bodysm);
01313 
01314   do_attribute_setup();
01315   push_attributes_before_modify( old_bodysms );
01316 
01317   return CUBIT_SUCCESS;
01318 }
01319 CubitStatus GeometryModifyTool::finish_topology_update( BodySM* new_bodysm,
01320                                                         Body* old_body )
01321 {
01322   DLIList<Body*> input_bodies,result_bodies;
01323   DLIList<BodySM*> new_bodysms, old_bodysms;
01324   input_bodies.append(old_body);
01325   new_bodysms.append(new_bodysm);
01326   old_bodysms.clean_out();
01327 
01328   DLIList<int> merged_surface_ids;
01329   DLIList<int> merged_curve_ids;
01330 
01331 
01332   get_merged_curve_and_surface_ids( input_bodies, merged_surface_ids, merged_curve_ids );
01334   //Store information about what surfaces were originally merged
01335   //
01336   //This fixes a problem caused by the lack of support
01337   //for automatically remerging surfaces that contain any
01338   //virtual geometry.
01339   //This should be removed if this issue is ever fixed - AHH
01340   std::map< int , DLIList<Surface*> > merged_map;
01341   for(int i=0; i< merged_surface_ids.size(); i++ )
01342     {
01343     int refface_id = merged_surface_ids.get_and_step();
01344     RefFace* old_merged_refface = RefEntityFactory::instance()->get_ref_face( refface_id );
01345     if( old_merged_refface && old_merged_refface->bridge_manager()->number_of_bridges() > 1 )
01346       {
01347       DLIList<Surface*> merged_surfsms;
01348       DLIList<TopologyBridge*> bridge_list;
01349       old_merged_refface->bridge_manager()->get_bridge_list( bridge_list );
01350       for(int j=0; j< bridge_list.size(); j++ )
01351         {
01352         Surface* merging_surf = CAST_TO(bridge_list.get_and_step(),Surface);
01353         if( merging_surf )
01354           merged_surfsms.append_unique( merging_surf );
01355         }
01356       merged_map[ refface_id ] = merged_surfsms;
01357       }
01358     }
01359   //*/
01360   /*
01361   //check to see if any curves have been orphaned inside virtual geometry
01362   DLIList<TBPoint*> point_list;
01363   new_bodysm->points( point_list );
01364   CubitBoolean loop = CUBIT_TRUE;
01365   while( loop )
01366     {
01367     for(i=0; i< point_list.size(); i++)
01368       {
01369       //loop all the points and see if any will be on only one live curve
01370       TBPoint* curr_point = point_list.get_and_step();
01371       DLIList<Curve*> curves_on_point;
01372       DLIList<Curve*> curves_to_keep;
01373       curr_point->curves( curves_on_point );
01374       for(int j=0; j< curves_on_point.size(); j++)
01375         {
01376         Curve* curr_curve = curves_on_point.get_and_step();
01377         DLIList<CubitSimpleAttrib*> attrib_list;
01378         CubitSimpleAttrib* attrib = CompositeEngine::find_attribute_by_name( curr_curve, "COMPOSITE_GEOM" );
01379         if( attrib )
01380           {
01381           attrib_list.append(attrib);
01382           }
01383         else
01384           curves_to_keep.append_unique( curr_curve );
01385         //curr_curve->get_simple_attribute( "COMPOSITE_GEOM", attrib_list );
01386         //if ( !attrib_list.size() )
01387           //curves_to_keep.append_unique( curr_curve );
01388         }
01389       //if all but one curve on this point will be removed we need to remove the other one too
01390       if( curves_to_keep.size() == 1 )
01391         {
01392         CubitString name("COMPOSITE_GEOM");
01393         DLIList<CubitString*> string_list;
01394         string_list.append( &name );
01395         CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
01396         curves_to_keep.get()->append_simple_attribute_virt( &geom_attrib );
01397         curr_point->append_simple_attribute_virt( &geom_attrib );
01398         loop = CUBIT_FALSE;
01399         }
01400       else if( curves_to_keep.size() == 0 )
01401         {
01402         DLIList<CubitSimpleAttrib*> attrib_list;
01403         curr_point->get_simple_attribute( "COMPOSIT_GEOM", attrib_list );
01404         if( !attrib_list.size() )
01405           {
01406           CubitString name("COMPOSITE_GEOM");
01407           DLIList<CubitString*> string_list;
01408           string_list.append( &name );
01409           CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
01410           curr_point->append_simple_attribute_virt( &geom_attrib );
01411           loop = CUBIT_TRUE;
01412           }
01413         }
01414       }
01415     if( loop )
01416       loop = CUBIT_FALSE;
01417     else
01418       loop = CUBIT_TRUE;
01419     }
01420   */
01421   GeometryModifyEngine* gme = GeometryModifyTool::instance()->get_engine(old_body);
01422 
01423   restore_vg_after_modify(new_bodysms, input_bodies, gme);
01424 
01425 
01426   DLIList<RefVolume*> volume_list;
01427 
01428   int i;
01429   for(i=new_bodysms.size(); i--;)
01430   {
01431     BodySM *bsm = new_bodysms.get_and_step();
01432     Body *body = dynamic_cast<Body*>(bsm->topology_entity());
01433     if(body)
01434     {
01435       // Append to the total list of volumes.
01436       body->ref_volumes(volume_list);
01437     }
01438   }
01439   // get all child entities (only get entities below volumes)
01440   DLIList<RefEntity*> child_list, ref_ent_list;
01441   CAST_LIST_TO_PARENT(volume_list, ref_ent_list);
01442   RefEntity::get_all_child_ref_entities( ref_ent_list, child_list );
01443 
01444   // Only push the id attributes if we are doing persistent ids.
01445   for(i=child_list.size(); i--;)
01446   {
01447   child_list.get_and_step()->auto_actuate_cubit_attrib(CUBIT_FALSE,CUBIT_TRUE);
01448   }
01449 
01450   remove_pushed_attributes(new_bodysms, input_bodies);
01451 
01452   finish_sm_op( input_bodies, new_bodysms , result_bodies);
01453 
01454   fixup_merged_entities( merged_surface_ids, merged_curve_ids);
01455 
01456   //Look for RefEdges that are orphaned inside of virtual surfaces
01457   CubitBoolean loop = CUBIT_TRUE;
01458   DLIList<RefVertex*> vertex_list;
01459   while(loop)
01460     {
01461     loop = CUBIT_FALSE;
01462     vertex_list.clean_out();
01463     for(i=0; i< volume_list.size(); i++)
01464       {
01465       RefVolume* curr_volume = volume_list.get_and_step();
01466       curr_volume->ref_vertices( vertex_list );
01467       }
01468     for(i=0; i< vertex_list.size(); i++)
01469       {
01470       RefVertex* curr_vertex = vertex_list.get_and_step();
01471       DLIList<RefEdge*> edges_on_vertex;
01472       curr_vertex->ref_edges( edges_on_vertex );
01473       edges_on_vertex.uniquify_unordered();
01474       if( edges_on_vertex.size() == 1 )
01475         {
01476         RefEdge* edge_to_remove = edges_on_vertex.get();
01477         CompositeTool::instance()->remove_edge(edge_to_remove);
01478         loop = CUBIT_TRUE;
01479         break;
01480         }
01481       }
01482     }
01484   //Force merge faces that were missed by finish_sm_op
01485   //
01486   //This fixes a problem caused by the lack of support
01487   //for automatically remerging surfaces that contain any
01488   //virtual geometry.
01489   //This should be removed if this issue is ever fixed - AHH
01490   for(i=0; i< merged_surface_ids.size(); i++)
01491     {
01492     int refface_id = merged_surface_ids.get_and_step();
01493     DLIList<RefFace*> ref_faces_to_remerge;
01494     if(merged_map.find( refface_id ) != merged_map.end())
01495       {
01496       DLIList<Surface*> merged_surfsms = merged_map[ refface_id ];
01497       for(int k=0; k< merged_surfsms.size(); k++)
01498         {
01499         Surface* merging_surf = merged_surfsms.get_and_step();
01500         RefFace* merging_refface = CAST_TO(merging_surf->topology_entity(),RefFace);
01501         if(merging_refface)
01502           ref_faces_to_remerge.append_unique(merging_refface);
01503         }
01504       }
01505     if( ref_faces_to_remerge.size() == 2 )
01506       {
01507       RefFace* first_remerge_face = ref_faces_to_remerge.get_and_step();
01508       RefFace* second_remerge_face = ref_faces_to_remerge.get_and_step();
01509       int first_id = first_remerge_face->id();
01510       int second_id = second_remerge_face->id();
01511       MergeTool::instance()->force_merge( first_remerge_face , second_remerge_face );
01512       PRINT_WARNING("Remerging Surfaces %i and %i\n",first_id,second_id);
01513       }
01514     }
01515   //*/
01516   //do_attribute_cleanup();
01517 
01518   return CUBIT_SUCCESS;
01519 }
01520 
01521 #endif
01522 GeometryModifyEngine*
01523 GeometryModifyTool::make_RefEdge_common( RefVertex* start_vertex,
01524                                          RefVertex* end_vertex,
01525                                          TBPoint*& start_point,
01526                                          TBPoint*& end_point,
01527                                          RefFace* ref_face,
01528                                          Surface** surface ) const
01529 {
01530   DLIList<TopologyEntity*> entity_list(3);
01531   DLIList<TopologyBridge*> bridge_list(3);
01532   TopologyBridge* bridge = 0;
01533   GeometryModifyEngine* gme = 0;
01534   start_point = end_point = 0;
01535 
01536   bool new_start_point = start_vertex->get_parents() > 0;
01537   bool new_end_point = end_vertex->get_parents() > 0;
01538 
01539   if (ref_face)
01540     entity_list.append( ref_face );
01541   if (!new_start_point)
01542     entity_list.append( start_vertex );
01543   if (!new_end_point)
01544     entity_list.append( end_vertex );
01545 
01546   if (entity_list.size())
01547     gme = common_modify_engine( entity_list, bridge_list );
01548 
01549   if (gme)
01550   {
01551     bridge_list.reset();
01552     if (ref_face)
01553       *surface = dynamic_cast<Surface*>(bridge_list.get_and_step());
01554     if (!new_start_point)
01555       start_point = dynamic_cast<TBPoint*>(bridge_list.get_and_step());
01556     if (!new_end_point)
01557       end_point = dynamic_cast<TBPoint*>(bridge_list.get_and_step());
01558   }
01559   else if (ref_face)
01560   {
01561     gme = get_engine( ref_face, &bridge );
01562     if (!gme)
01563     {
01564       PRINT_ERROR("No modify engine for surface %d\n", ref_face->id()) ;
01565       return 0;
01566     }
01567     *surface = dynamic_cast<Surface*>(bridge);
01568     GeometryQueryEngine* gqe = bridge->get_geometry_query_engine();
01569     if (!new_start_point)
01570       start_point = dynamic_cast<TBPoint*>( start_vertex->
01571                                   bridge_manager()->topology_bridge( gqe ) );
01572     if (!new_end_point)
01573       end_point = dynamic_cast<TBPoint*>( end_vertex->
01574                                   bridge_manager()->topology_bridge( gqe ) );
01575   }
01576   else if (!new_start_point && (gme = get_engine( start_vertex, &bridge )))
01577   {
01578     start_point = dynamic_cast<TBPoint*>(bridge);
01579     if (!new_end_point)
01580       end_point = dynamic_cast<TBPoint*>( end_vertex->bridge_manager()->
01581                     topology_bridge( bridge->get_geometry_query_engine() ) );
01582   }
01583   else if (!new_end_point && (gme = get_engine( end_vertex, &bridge )))
01584   {
01585     end_point = dynamic_cast<TBPoint*>(bridge);
01586   }
01587   else
01588   {
01589     gme = get_gme();
01590   }
01591 
01592 
01593   if (!start_point)
01594     start_point = gme->make_Point( start_vertex->coordinates() );
01595   if (!end_point)
01596     end_point = gme->make_Point( end_vertex->coordinates());
01597 
01598   return gme;
01599 }
01600 
01601 //-------------------------------------------------------------------------
01602 // Purpose       : This function uses the vertices and surface to create
01603 //                 a curve along this surface.  The solid modeler will actually
01604 //                 do most of the work.
01605 // Note          : The optional third vertex will not be part of the curve,
01606 //                 it is used for interpolation purposes.
01607 //
01608 // Creator       : David White
01609 //
01610 // Creation Date : 10/9/97
01611 //
01612 // Rewriting for new GeometryQueryTool interface - J.Kraftcheck 9/03
01613 //-------------------------------------------------------------------------
01614 RefEdge* GeometryModifyTool::make_RefEdge(RefVertex *ref_vertex_1,
01615                                     RefVertex *ref_vertex_2,
01616                                     RefFace* ref_face_ptr,
01617                                     RefVertex const* ref_vertex_3 ) const
01618 {
01619       //make sure that the vertices are on the ref-face.
01620    CubitVector vert_1 = ref_vertex_1->coordinates();
01621    CubitVector vert_2 = ref_vertex_2->coordinates();
01622 
01623    ref_face_ptr->move_to_surface(vert_1);
01624    ref_face_ptr->move_to_surface(vert_2);
01625 
01626    GeometryQueryEngine *gqe = ref_face_ptr->get_geometry_query_engine();
01627 
01628    if (!ref_vertex_1->coordinates().within_tolerance(vert_1, gqe->get_sme_resabs_tolerance()))
01629    {
01630       PRINT_ERROR("vertices must lie within tolerance to the given"
01631                   " surface.\n"
01632                   "%s (Vertex %d) does not lie on %s (Surface %d).\n",
01633                   ref_vertex_1->entity_name().c_str(),
01634                   ref_vertex_1->id(),
01635                   ref_face_ptr->entity_name().c_str(),
01636                   ref_face_ptr->id() );
01637       return (RefEdge*)NULL;
01638    }
01639    else if (!ref_vertex_2->coordinates().within_tolerance(vert_2, gqe->get_sme_resabs_tolerance() ))
01640    {
01641       PRINT_ERROR("vertices must lie within tolerance to the given"
01642                   " surface.\n"
01643                   "%s (Vertex %d) does not lie on %s (Surface %d).\n",
01644                   ref_vertex_2->entity_name().c_str(),
01645                   ref_vertex_2->id(),
01646                   ref_face_ptr->entity_name().c_str(),
01647                   ref_face_ptr->id() );
01648       return (RefEdge*)NULL;
01649    }
01650      //Now let us find the points on the surface.  We want to
01651      //create them as we go for accuracy.
01652 
01653       // Get the GME of the first RefVertex.
01654    GeometryModifyEngine* GMEPtr = 0;
01655 
01656      // Extract the end Points to be used to make the RefEdge
01657    TBPoint* point_ptr1 = NULL;
01658    TBPoint* point_ptr2 = NULL;
01659    Surface* surface_ptr = NULL;
01660 
01661    // Look for a common GeometryModifyEngine
01662   GMEPtr = make_RefEdge_common( ref_vertex_1, ref_vertex_2,
01663                                 point_ptr1, point_ptr2,
01664                                 ref_face_ptr, &surface_ptr );
01665 
01666   //If we did not find a common GeometryModifyEngine, fail
01667   if( ! GMEPtr )
01668   {
01669     PRINT_ERROR("Surface %d, vertex %d and vertex %d do not "
01670       "belong to the same geometric modeling engine.\n", ref_face_ptr->id(),
01671       ref_vertex_1->id(), ref_vertex_2->id() );
01672 
01673     return 0;
01674   }
01675 
01676    CubitVector *third_vector_ptr = NULL;
01677    CubitVector third_vector;
01678    if ( ref_vertex_3 != NULL )
01679    {
01680       third_vector = ref_vertex_3->coordinates();
01681       third_vector_ptr = &third_vector;
01682       ref_face_ptr->move_to_surface( third_vector );
01683    }
01684 
01685      // Make sure that we get back valid Points
01686    assert ( point_ptr1 != NULL && point_ptr2 != NULL );
01687    
01688    if( CubitUndo::get_undo_enabled() )
01689    {
01690      //if endpoints are free vertices, need to save them out
01691      DLIList<RefVertex*> verts_to_save;
01692      verts_to_save.append( ref_vertex_1 );
01693      verts_to_save.append( ref_vertex_2 );
01694      bool save_only_if_free = true;
01695      CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
01696    }
01697 
01698      // Request the GME to create a Curve using the Points
01699    Curve *curve_ptr;
01700    curve_ptr = GMEPtr->make_Curve( point_ptr1,
01701                           point_ptr2,
01702                           surface_ptr,
01703                           third_vector_ptr);
01704 
01705 
01706      // If we get a NULL pointer, give a warning message and return
01707      // a NULL pointer.
01708    if ( curve_ptr == NULL )
01709    {
01710       PRINT_WARNING("In GeometryModifyTool::make_RefEdge\n"
01711                     "\tProblems making a spline curve from Vertex %d and %d\n"
01712                     "\tand the input list of positions.\n",
01713                     ref_vertex_1->id(), ref_vertex_2->id());
01714       return (RefEdge *)NULL ;
01715    }
01716   
01717 
01718      // Complete the task of linking this new Curve into the rest of the
01719      // geometry datastructures and return the new RefEdge.
01720    RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
01721    if( CubitUndo::get_undo_enabled() )
01722    {
01723      if( new_edge )
01724        CubitUndo::note_result_entity( new_edge );
01725    }
01726    return new_edge;
01727 }
01728 
01729 RefEdge* GeometryModifyTool::make_elliptical_RefEdge( RefVertex *vert1,
01730                                                       RefVertex *vert2,
01731                                                       CubitVector center_point,
01732                                                       double start_angle,
01733                                                       double end_angle,
01734                                                       CubitSense sense) const
01735 {
01736   GeometryModifyEngine* GMEPtr = 0;
01737 
01738   // Extract the Points to be used to make the RefEdge
01739   TBPoint* point_ptr1 = NULL;
01740   TBPoint* point_ptr2 = NULL;
01741 
01742   // Look for a common geometric modeling engine to use
01743   GMEPtr = make_RefEdge_common( vert1, vert2,
01744                                 point_ptr1, point_ptr2 );
01745   if (!GMEPtr)
01746     return 0;
01747 
01748   // Make sure that we get back valid Points
01749   assert ( point_ptr1 != NULL && point_ptr2 != NULL ) ;
01750 
01751   if( CubitUndo::get_undo_enabled() )
01752   {
01753     //if endpoints are free vertices, need to save them out
01754     DLIList<RefVertex*> verts_to_save;
01755     verts_to_save.append( vert1 );
01756     verts_to_save.append( vert2 );
01757     bool save_only_if_free = true;
01758     CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
01759   }
01760 
01761   // Request the GME to create a Curve using the Points
01762   Curve* curve_ptr = GMEPtr->make_elliptical_Curve(point_ptr1,
01763                                                    point_ptr2,
01764                                                    center_point,
01765                                                    start_angle,
01766                                                    end_angle,
01767                                                    sense);
01768 
01769   // If we get a NULL pointer, give a warning message and return
01770   // a NULL pointer.
01771   if ( curve_ptr == NULL )
01772   {
01773     PRINT_WARNING("In GeometryModifyTool::make_elliptical_RefEdge\n"
01774                   "         Got a NULL pointer to a Curve.\n"
01775                   "         Problems making RefEdge from RefVertex %d and %d\n",
01776                   vert1->id(), vert2->id());
01777     return (RefEdge *)NULL ;
01778   }
01779 
01780   // Complete the task of linking this new Curve into the rest of the
01781   // geometry datastructures and return the new RefEdge.
01782   RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge( curve_ptr );
01783   if( CubitUndo::get_undo_enabled() )
01784   {
01785     if( new_edge )
01786       CubitUndo::note_result_entity( new_edge );
01787   }
01788 
01789   return new_edge;
01790 }
01791 
01792 
01793 
01794 
01795 
01796 
01797 //-------------------------------------------------------------------------
01798 // Purpose       : This function takes RefEdge type information, two
01799 //                 RefVertices, and a list of positions in space (represented
01800 //                 by CubitVectors) to create a RefEdge. The RefVertices must
01801 //                 be associated with the same GeometryModifyEngine.
01802 //                 The return value can be a NULL pointer, if the RefEdge
01803 //                 cannot be succesfully made for some reason.
01804 //
01805 // Special Notes : The interpolated curve is a spline curve.
01806 //                 If the input refface_ptr is not NULL, the points are first
01807 //                 moved to the surface before interpolation.
01808 //
01809 // Creator       : Malcolm Panthaki
01810 //
01811 // Creation Date : 05/15/97
01812 //
01813 // Rewriting for new GeometryQueryTool interface - J.Kraftcheck 9/03
01814 //-------------------------------------------------------------------------
01815 RefEdge* GeometryModifyTool::make_RefEdge(GeometryType ref_edge_type,
01816                                     RefVertex *ref_vertex_1,
01817                                     RefVertex *ref_vertex_2,
01818                                     DLIList<CubitVector*>& vector_list,
01819                                     RefFace* refface_ptr) const
01820 {
01821    GeometryModifyEngine* GMEPtr = 0;
01822 
01823      // Extract the end Points to be used to make the RefEdge
01824    TBPoint* point_ptr1 = NULL;
01825    TBPoint* point_ptr2 = NULL;
01826    Surface* surface_ptr = NULL;
01827 
01828    // Look for a common GeometryModifyEngine
01829   GMEPtr = make_RefEdge_common( ref_vertex_1, ref_vertex_2,
01830                                 point_ptr1, point_ptr2,
01831                                 refface_ptr, &surface_ptr );
01832   if (!GMEPtr)
01833     return 0;
01834 
01835      // Make sure that we get back valid Points
01836    assert ( point_ptr1 != NULL && point_ptr2 != NULL );
01837 
01838    if( CubitUndo::get_undo_enabled() )
01839    {
01840      //if endpoints are free vertices, need to save them out
01841      DLIList<RefVertex*> verts_to_save;
01842      verts_to_save.append( ref_vertex_1 );
01843      verts_to_save.append( ref_vertex_2 );
01844      bool save_only_if_free = true;
01845      CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
01846    }
01847 
01848      // Request the GME to create a Curve using the Points
01849    Curve* curve_ptr = GMEPtr->make_Curve(ref_edge_type,
01850                                          point_ptr1,
01851                                          point_ptr2,
01852                                          vector_list,
01853                                          refface_ptr ? refface_ptr->get_surface_ptr() : 0);
01854 
01855      // If we get a NULL pointer, give a warning message and return
01856      // a NULL pointer.
01857    if ( curve_ptr == NULL )
01858    {
01859       PRINT_WARNING("In GeometryModifyTool::make_RefEdge\n"
01860                     "         Got a NULL pointer to a Curve.\n"
01861                     "         Problems making a spline RefEdge from RefVertex %d and %d\n"
01862                     "         and the input list of positions.\n",
01863                     ref_vertex_1->id(), ref_vertex_2->id());
01864       return (RefEdge *)NULL ;
01865    }
01866 
01867      // Complete the task of linking this new Curve into the rest of the
01868      // geometry datastructures and return the new RefEdge.
01869    RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
01870    if( CubitUndo::get_undo_enabled() )
01871    {
01872      if( new_edge )
01873        CubitUndo::note_result_entity( new_edge );
01874    }
01875    return new_edge;
01876 }
01877 
01878 //-------------------------------------------------------------------------
01879 // Purpose       : This function takes a type information, two
01880 //                 RefVertices, an intermediate position, and a sense
01881 //                 information to create a RefEdge. The RefVertices must
01882 //                 be associated with the same GeometryModifyEngine.
01883 //                 The return value can be a NULL pointer, if the RefEdge
01884 //                 cannot be succesfully made for some reason.
01885 //
01886 // Special Notes :
01887 //
01888 // Creator       : Raikanta Sahu
01889 //
01890 // Creation Date : 03/27/97
01891 //-------------------------------------------------------------------------
01892 RefEdge* GeometryModifyTool::make_RefEdge(GeometryType ref_edge_type,
01893                                     RefVertex *ref_vertex_1,
01894                                     RefVertex *ref_vertex_2,
01895                                     CubitVector const* intermediate_point ) const
01896 {
01897    GeometryModifyEngine* GMEPtr = 0;
01898 
01899      // Extract the Points to be used to make the RefEdge
01900    TBPoint* point_ptr1 = NULL;
01901    TBPoint* point_ptr2 = NULL;
01902 
01903     // Look for a common geometric modeling engine to use
01904   GMEPtr = make_RefEdge_common( ref_vertex_1, ref_vertex_2,
01905                                 point_ptr1, point_ptr2 );
01906   if (!GMEPtr)
01907     return 0;
01908 
01909      // Make sure that we get back valid Points
01910    assert ( point_ptr1 != NULL && point_ptr2 != NULL ) ;
01911 
01912    if( CubitUndo::get_undo_enabled() )
01913    {
01914      //if endpoints are free vertices, need to save them out
01915      DLIList<RefVertex*> verts_to_save;
01916      verts_to_save.append( ref_vertex_1 );
01917      verts_to_save.append( ref_vertex_2 );
01918      bool save_only_if_free = true;
01919      CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
01920    }
01921 
01922      // Request the GME to create a Curve using the Points
01923    Curve* curve_ptr = GMEPtr->make_Curve(ref_edge_type,
01924                                          point_ptr1,
01925                                          point_ptr2,
01926                                          intermediate_point );
01927 
01928      // If we get a NULL pointer, give a warning message and return
01929      // a NULL pointer.
01930    if ( curve_ptr == NULL )
01931    {
01932       PRINT_WARNING("In GeometryModifyTool::make_RefEdge\n"
01933                     "         Got a NULL pointer to a Curve.\n"
01934                     "         Problems making RefEdge from RefVertex %d and %d\n",
01935                     ref_vertex_1->id(), ref_vertex_2->id());
01936       return (RefEdge *)NULL ;
01937    }
01938 
01939      // Complete the task of linking this new Curve into the rest of the
01940      // geometry datastructures and return the new RefEdge.
01941    RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge( curve_ptr );
01942    if( CubitUndo::get_undo_enabled() )
01943    {
01944      if( new_edge )
01945        CubitUndo::note_result_entity( new_edge );
01946    }
01947    return new_edge;
01948 }
01949 
01950 //-------------------------------------------------------------------------
01951 // Purpose       : This function creates a RefFace from an existing RefFace.
01952 //                 The new face is a sheet body, double sided face with no
01953 //                 volume to the body.
01954 //
01955 // Special Notes :
01956 //
01957 // Creator       : Raikanta Sahu
01958 //
01959 // Creation Date : 03/27/97
01960 //-------------------------------------------------------------------------
01961 
01962 RefFace* GeometryModifyTool::make_RefFace(RefFace *from_ref_face,                                    
01963                                     std::map< RefEntity*, RefEntity* > *old_to_new_map ) const
01964 {
01965    GeometryModifyEngine* GME_ptr = get_engine(from_ref_face);
01966 
01967    if (!GME_ptr)
01968    {
01969       PRINT_ERROR("Cannot create surface from another virtual surface.\n");
01970       return NULL;
01971    }
01972      //From the surface create a new surface.
01973    TopologyBridge* bridge = 0;
01974    GeometryModifyEngine* engine = get_engine(from_ref_face, &bridge);
01975    Surface* old_surface_ptr = dynamic_cast<Surface*>(bridge);
01976    if ( engine == NULL )
01977    {
01978       PRINT_ERROR("%s (surface %d) does not have a modify engine.\n",
01979                   from_ref_face->entity_name().c_str(),
01980                   from_ref_face->id() );
01981       return (RefFace*)NULL;
01982    }
01983 
01984   if( CubitUndo::get_undo_enabled() )
01985     CubitUndo::save_state();
01986 
01987   //this list will get all the TB's what we'll be copying
01988   TopologyBridge *top_bridge = old_surface_ptr;
01989 
01990   
01991   //if( !extended_from )
01992   {
01993     prepare_for_copy( from_ref_face, top_bridge );
01994   }
01995 
01996   Surface *tmp_surface = CAST_TO( top_bridge, Surface );
01997   std::map< TopologyBridge*, TopologyBridge* > old_tb_to_new_tb;
01998   Surface* new_surface_ptr = engine->make_Surface( tmp_surface, &old_tb_to_new_tb );
01999 
02000   if (!new_surface_ptr)
02001   {
02002     PRINT_ERROR("Surface copy failed.\n");
02003     //if( !extended_from )
02004       clean_up_from_copy_failure( old_surface_ptr );
02005 
02006    if( CubitUndo::get_undo_enabled() )
02007         CubitUndo::remove_last_undo();
02008 
02009     return 0;
02010   }
02011   
02012   //if( !extended_from  )
02013   {
02014     TopologyBridge *top_bridge_new = new_surface_ptr;
02015     finish_copy( top_bridge_new, old_surface_ptr );
02016     new_surface_ptr = CAST_TO( top_bridge_new, Surface );
02017   }
02018 
02019   Body *new_Body = make_Body(new_surface_ptr);
02020   DLIList<RefFace*> ref_faces;
02021   new_Body->ref_faces(ref_faces);
02022   assert(ref_faces.size() > 0);
02023   
02024   if( old_to_new_map )
02025     create_old_to_new_ref_ent_map( tmp_surface, new_surface_ptr, *old_to_new_map, old_tb_to_new_tb );
02026 
02027   if( CubitUndo::get_undo_enabled() )
02028   {
02029     if( new_Body )
02030       CubitUndo::note_result_body( new_Body );
02031     else
02032       CubitUndo::remove_last_undo();
02033   }
02034 
02035   return ref_faces.get();
02036 }
02037 
02038 //-------------------------------------------------------------------------
02039 // Purpose       : This function creates a sheet body by extending out a
02040 //                 set of surfaces.  The sheet body is a double sided face
02041 //                 with no volume.
02042 //
02043 // Special Notes :
02044 //
02045 // Creator       : Steve Storm
02046 //
02047 // Creation Date : 02/28/08
02048 //-------------------------------------------------------------------------
02049 Body*
02050 GeometryModifyTool::make_extended_sheet( DLIList<RefFace*> &ref_face_list,
02051                                          CubitBox *clip_box_ptr,
02052                                          bool preview ) const
02053 {
02054   if( !ref_face_list.size() )
02055     return 0;
02056 
02057   GfxPreview::clear();
02058 
02059   // Check for virtual geometry
02060   DLIList<RefEntity*> ref_ent_list;
02061   CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
02062   if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
02063   {
02064     PRINT_ERROR("EXTENDING surfaces containing virtual geometry is not\n"
02065       "       allowed. Delete virtual geometry on these surfaces\n"
02066       "       before operation.\n" );
02067     return 0;
02068   }
02069 
02070   // Look for a common GeometryModifyEngine for all of the RefFaces
02071   int count = ref_face_list.size();
02072   DLIList<TopologyBridge*> bridge_list(count);
02073   DLIList<TopologyEntity*> entity_list(count);
02074   CAST_LIST_TO_PARENT( ref_face_list, entity_list );
02075 
02076   GeometryModifyEngine* GME_ptr =
02077     common_modify_engine( entity_list, bridge_list );
02078   if(! GME_ptr )
02079   {
02080      PRINT_ERROR("Cannot construct an extended sheet using surfaces that\n"
02081                  "       do not share a common geometry engine.\n");
02082      return 0;
02083   }
02084 
02085   DLIList<Surface*> surface_list(count);
02086   CAST_LIST( bridge_list, surface_list, Surface );
02087   
02088   if( CubitUndo::get_undo_enabled() )
02089     CubitUndo::save_state();
02090 
02091   BodySM *bodySM_ptr = GME_ptr->make_extended_sheet( surface_list,
02092     clip_box_ptr, preview );
02093 
02094   if( !bodySM_ptr )
02095     CubitUndo::remove_last_undo();
02096 
02097   if( bodySM_ptr )
02098   {
02099     Body *tmp_body = GeometryQueryTool::instance()->make_Body(bodySM_ptr);
02100 
02101     if( CubitUndo::get_undo_enabled() )
02102     {
02103       if( tmp_body )
02104         CubitUndo::note_result_entity( tmp_body );
02105       else 
02106         CubitUndo::remove_last_undo();
02107     }
02108 
02109     return tmp_body;
02110   }
02111   else
02112     return 0;
02113 }
02114 
02115 //-------------------------------------------------------------------------
02116 // Purpose       : This function takes a type information and a list of
02117 //                 RefEdges to create a Body with just one RefFace. The
02118 //                 underlying representation of the RefFace is determined
02119 //                 by the GeometryModifyEngine of the RefEdges. All the
02120 //                 RefEdges in the list must be associated with the same
02121 //                 GeometryModifyEngine. The return value can be a
02122 //                 NULL pointer, if the RefFace cannot be succesfully
02123 //                 made for some reason.
02124 //
02125 // Special Notes :
02126 //
02127 // Creator       : David White
02128 //
02129 // Creation Date : 10/23/97
02130 //-------------------------------------------------------------------------
02131 
02132 RefFace* GeometryModifyTool::make_RefFace(GeometryType ref_face_type,
02133                                     DLIList<RefEdge*>& ref_edge_list,
02134                                     bool is_free_face,
02135                                     RefFace *ref_face_ptr,
02136                                     bool check_edges ) const
02137 {
02138     //Look for a common GeometryModifyEngine for all of
02139     //the RefEdges.
02140 
02141   const int count = ref_edge_list.size() + (ref_face_ptr ? 1 : 0);
02142   DLIList<TopologyBridge*> bridge_list(count);
02143   DLIList<TopologyEntity*> entity_list(count);
02144   CAST_LIST_TO_PARENT( ref_edge_list, entity_list );
02145   if( ref_face_ptr ) entity_list.append( ref_face_ptr );
02146 
02147   GeometryModifyEngine* GME_ptr =
02148     common_modify_engine( entity_list, bridge_list );
02149   if(! GME_ptr )
02150   {
02151      PRINT_ERROR("Cannot construct a Surface using entities that do "
02152                  "not share a common geometry engine.\n");
02153      return 0;
02154   }
02155 
02156    Surface* old_surface_ptr = 0;
02157    if (ref_face_ptr)
02158     old_surface_ptr = dynamic_cast<Surface*>(bridge_list.pop());
02159 
02160    //Collect all the names on vertices to propagate after you create
02161    //the surface
02162    DLIList<CubitVector> vertex_coordinates;
02163    DLIList<CubitString> vertex_names;
02164    DLIList<RefEdge*> free_ref_edges;
02165    int kk;
02166    for( kk=ref_edge_list.size(); kk--; )
02167    {
02168      DLIList<CubitString> tmp_names;
02169      RefEdge *tmp_edge = ref_edge_list.get_and_step();
02170 
02171      if( tmp_edge->num_parent_ref_entities() == 0 )
02172        free_ref_edges.append( tmp_edge );
02173 
02174      RefVertex *s_vertex = tmp_edge->start_vertex();
02175      RefVertex *e_vertex = tmp_edge->end_vertex();
02176      int jj;
02177 
02178      s_vertex->entity_names( tmp_names );
02179      for( jj=tmp_names.size(); jj--; )
02180      {
02181        CubitVector tmp_vec = tmp_edge->start_vertex()->coordinates();
02182        CubitString name = tmp_names.get_and_step();
02183        vertex_coordinates.append( tmp_vec );
02184        vertex_names.append( name );
02185      }
02186 
02187      tmp_names.clean_out();
02188      e_vertex->entity_names( tmp_names );
02189      for( jj=tmp_names.size(); jj--; )
02190      {
02191        CubitVector tmp_vec = tmp_edge->end_vertex()->coordinates();
02192        CubitString name = tmp_names.get_and_step();
02193        vertex_coordinates.append( tmp_vec );
02194        vertex_names.append( name );
02195      }
02196    }
02197 
02198    DLIList<Curve*> curve_list(ref_edge_list.size());
02199    CAST_LIST( bridge_list, curve_list, Curve );
02200 
02201      // Use the Curves to create a Surface
02202    Surface* surface_ptr = GME_ptr->make_Surface(ref_face_type, curve_list,
02203                                                 old_surface_ptr, check_edges) ;
02204 
02205    if (surface_ptr == NULL) {
02206      PRINT_ERROR("Couldn't make new RefFace.\n");
02207      return NULL;
02208    }
02209 
02210    GeometryQueryTool* const gqt = GeometryQueryTool::instance();
02211 
02212    RefFace* result_face = gqt->make_free_RefFace(surface_ptr, is_free_face);
02213    gqt->cleanout_deactivated_geometry();
02214 
02215    //send out events for free curves saying that their 'free' status has
02216    //be changed
02217 
02218   for( kk=0; kk<free_ref_edges.size(); kk++ )
02219   {
02220     RefEdge *free_edge = free_ref_edges.get_and_step();
02221     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOP_LEVEL_ENTITY_DESTRUCTED, free_edge));
02222     CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, free_edge );
02223     GeometryQueryTool::instance()->history().add_event(evt);
02224   }
02225 
02226 
02227    //look for a vertex at the same location of the original
02228    //vertex(s).  Add the name to this new vertex.
02229    DLIList<RefVertex*> tmp_verts;
02230    result_face->ref_vertices( tmp_verts);
02231    for( kk=vertex_coordinates.size(); kk--; )
02232    {
02233      CubitVector tmp_coord = vertex_coordinates.get_and_step();
02234      CubitString tmp_name = vertex_names.get_and_step();
02235 
02236      int jj;
02237      for( jj=tmp_verts.size(); jj--; )
02238      {
02239        RefVertex *tmp_vert = tmp_verts.get_and_step();
02240        if( tmp_coord.distance_between( tmp_vert->coordinates() ) < GEOMETRY_RESABS )
02241        {
02242          //add the name if it doesn't already exist
02243          RefEntityName::instance()->add_refentity_name( tmp_vert, tmp_name );
02244        }
02245      }
02246    }
02247 
02248    return result_face;
02249 }
02250 
02251 //-------------------------------------------------------------------------
02252 // Purpose       : This function takes a list of RefVolumes to create a
02253 //                 Body. The underlying representation of the Body is
02254 //                 determined by the GeometryModifyEngine of the
02255 //                 RefVolumes. All the RefVolumes in the list must be
02256 //                 associated with the same GeometryModifyEngine. The
02257 //                 return value can be a NULL pointer, if the RefFace
02258 //                 cannot be succesfully made for some reason.
02259 //
02260 // Special Notes :
02261 //
02262 // Creator       : Raikanta Sahu
02263 //
02264 // Creation Date : 03/29/97
02265 //-------------------------------------------------------------------------
02266 
02267 Body* GeometryModifyTool::make_Body(DLIList<RefVolume*>& ref_volume_list) const
02268 {
02269   DLIList<TopologyEntity*> topo_list;
02270   DLIList<Lump*> lump_list;
02271   DLIList<TopologyBridge*> bridge_list;
02272   CAST_LIST_TO_PARENT( ref_volume_list, topo_list );
02273   GeometryModifyEngine* GME_ptr =
02274     common_modify_engine( topo_list, bridge_list, CUBIT_FALSE );
02275   if( ! GME_ptr )
02276   {
02277     PRINT_ERROR("The specified volumes do not belong to the same "
02278       "geometry engine, and therefore cannot be used to form a "
02279       "single body.");
02280     return 0;
02281   }
02282   CAST_LIST( bridge_list, lump_list, Lump );
02283   assert( ref_volume_list.size() == lump_list.size() );
02284 
02285 
02286      // Use the Lumps to create a BodySM
02287    BodySM* bodySM_ptr = GME_ptr->make_BodySM(lump_list) ;
02288 
02289      // If we get a NULL pointer, give a warning message and return
02290      // a NULL pointer.
02291    if ( bodySM_ptr == NULL )
02292    {
02293       PRINT_WARNING("In GeometryModifyTool::make_Body\n"
02294                     "         Got a NULL pointer to a BodySM.\n"
02295                     "         Cannot make a Body.\n") ;
02296       return (Body *)NULL;
02297    }
02298 
02299    return GeometryQueryTool::instance()->make_Body(bodySM_ptr);
02300 }
02301 
02302 //-------------------------------------------------------------------------
02303 // Purpose       : This function creates a sheet body from an existing
02304 //                 RefFace.
02305 //
02306 // Special Notes :
02307 //
02308 // Creator       : Raikanta Sahu
02309 //
02310 // Creation Date : 03/29/97
02311 //-------------------------------------------------------------------------
02312 
02313 Body* GeometryModifyTool::make_Body(RefFace *from_ref_face,                              
02314                               std::map< RefEntity*, RefEntity* > *old_to_new_map ) const
02315 {
02316      // Given the arguments, make a RefFace.
02317    RefFace* new_ref_face = this->make_RefFace(from_ref_face,
02318                                               old_to_new_map );
02319    if (!new_ref_face)
02320    {
02321       return (Body *)NULL;
02322    }
02323 
02324    DLIList<Body*> bodies;
02325    new_ref_face->bodies(bodies);
02326 
02327    if (!bodies.size()) {
02328      GeometryEntity *ge_ptr = new_ref_face->get_geometry_entity_ptr();
02329      Surface *surf_ptr = CAST_TO(ge_ptr, Surface);
02330      assert(surf_ptr != 0);
02331 
02332      BodySM *body_sm = gmeList.get()->make_BodySM(surf_ptr);
02333      return GeometryQueryTool::instance()->make_Body(body_sm);
02334    }
02335 
02336    else return bodies.get();
02337 }
02338 //-------------------------------------------------------------------------
02339 // Purpose       : This function takes a type information and a list of
02340 //                 RefEdges to create a Body that has just one RefFace.
02341 //                 The underlying representation of the Body is
02342 //                 determined by the GeometryModifyEngine of the
02343 //                 RefEdges. All the RefEdges in the list must be
02344 //                 associated with the same GeometryModifyEngine. The
02345 //                 return value can be a NULL pointer, if the Body cannot
02346 //                 be succesfully made for some reason.
02347 //
02348 // Special Notes :
02349 //
02350 // Creator       : Raikanta Sahu
02351 //
02352 // Creation Date : 03/29/97
02353 //-------------------------------------------------------------------------
02354 
02355 Body* GeometryModifyTool::make_Body(GeometryType ref_face_type,
02356                               DLIList<RefEdge*>& ref_edge_list,
02357                               RefFace *ref_face_ptr) const
02358 {
02359    if( CubitUndo::get_undo_enabled() )
02360      CubitUndo::save_state_with_cubit_file( ref_edge_list );
02361 
02362    bool is_free_face = false;
02363 
02364      // Given the arguments, make a RefFace.
02365    RefFace* new_ref_face = this->make_RefFace(ref_face_type,
02366                                               ref_edge_list,
02367                                               is_free_face,
02368                                               ref_face_ptr);
02369 
02370    if( new_ref_face == NULL )
02371       return NULL;
02372 
02373       // If new_ref_face doesn't have a body, create one.
02374    DLIList<Body*> bodies;
02375    new_ref_face->bodies(bodies);
02376 
02377    if (!bodies.size()) {
02378      Surface *surf_ptr = new_ref_face->get_surface_ptr();
02379      assert(surf_ptr != 0);
02380      GeometryModifyEngine* engine = get_engine(surf_ptr);
02381      assert(engine != 0);
02382 
02383      BodySM *body_sm = engine->make_BodySM(surf_ptr);
02384      Body* body = GeometryQueryTool::instance()->make_Body(body_sm);
02385      bodies.append( body );
02386    }
02387 
02388    if( CubitUndo::get_undo_enabled() )
02389    {
02390      if( bodies.size() )
02391        CubitUndo::note_result_entity( bodies.get() );
02392      else
02393       CubitUndo::remove_last_undo();
02394    }
02395 
02396      // Return the body containing the new RefFace.
02397    return bodies.get();
02398 }
02399 
02400 //-------------------------------------------------------------------------
02401 // Purpose       : The following functions copy the input Body to create
02402 //                 a new one.  Some transformations may be applied to the
02403 //                 newly copied Body before returning it:
02404 //                    copy
02405 //                    copy_and_move
02406 //                    copy_and_rotate
02407 //
02408 // Special Notes :
02409 //
02410 // Creator       : Malcolm J. Panthaki
02411 //
02412 // Creation Date : 10/1/96
02413 //-------------------------------------------------------------------------
02414 Body* GeometryModifyTool::copy_body ( Body* bodyPtr, 
02415   std::map< RefEntity*, RefEntity* > *old_to_new_map )
02416 {
02417    BodySM* body_sm = bodyPtr->get_body_sm_ptr();
02418    if (!body_sm)
02419    {
02420      PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n", bodyPtr->id());
02421      return 0;
02422    }
02423 
02424    //this list will get all the TB's what we'll be copying
02425    DLIList<RefEntity*> tmp_list;
02426    tmp_list.append( bodyPtr );
02427    TopologyBridge *top_bridge;
02428    prepare_for_copy( bodyPtr, top_bridge );
02429 
02430    BodySM *tmp_body_sm = CAST_TO( top_bridge, BodySM );
02431 
02432    GeometryModifyEngine* GMEPtr = get_engine(tmp_body_sm);
02433    if ( GMEPtr == NULL )
02434    {
02435      clean_up_from_copy_failure( top_bridge );
02436      PRINT_ERROR("Cannot copy volume %d\n"
02437                  "     Copy is supported for bodies based on solid "
02438                  "models only\n", bodyPtr->ref_volume()->id() );
02439      return NULL ;
02440    }
02441    std::map<TopologyBridge*, TopologyBridge*> old_tb_to_new_tb;  
02442 
02443    BodySM *new_bodysm = GMEPtr->copy_body(tmp_body_sm, &old_tb_to_new_tb );
02444 
02445    if (!new_bodysm)
02446    {
02447      clean_up_from_copy_failure( top_bridge );
02448      PRINT_ERROR("Failed to copy volume %d\n", bodyPtr->ref_volume()->id());
02449      return 0;
02450    }
02451 
02452    TopologyBridge *top_bridge_new = new_bodysm;
02453    finish_copy( top_bridge_new, body_sm );
02454 
02455    new_bodysm = CAST_TO( top_bridge_new, BodySM );
02456    Body *body_new = GeometryQueryTool::instance()->make_Body(new_bodysm);
02457 
02458    if( old_to_new_map )
02459      create_old_to_new_ref_ent_map( body_sm, new_bodysm, *old_to_new_map, old_tb_to_new_tb );
02460 
02461    return body_new;
02462 }
02463 
02464 //-------------------------------------------------------------------------
02465 // Purpose       : Check if bodies can be webcut
02466 //
02467 // Special Notes :
02468 //
02469 // Creator       : Jason Kraftcheck
02470 //
02471 // Creation Date : 10/10/03
02472 //-------------------------------------------------------------------------
02473 CubitStatus GeometryModifyTool::okay_to_modify(
02474                                  DLIList<Body*>& webcut_body_list,
02475                                  const char* op ) const
02476 {
02477   CubitStatus ret = CUBIT_SUCCESS;
02478 
02479   Body *b = webcut_body_list.get();
02480   if(b)
02481   {
02482     GeometryModifyEngine *gme = get_engine(b);
02483     if(gme)
02484     {
02485       if(!gme->supports_interoperability() &&
02486           contains_intermediate_geom(webcut_body_list))
02487       {
02488         PRINT_ERROR("Intermixing real and virtual geometry operations using the current solid modeling kernel is not allowed.\n");
02489         ret = CUBIT_FAILURE;
02490       }
02491     }
02492   }
02493 
02494   if(ret == CUBIT_SUCCESS)
02495   {
02496     // If the operation is not one of the ones below...
02497     if(strcmp(op, "WEBCUT") &&
02498       strcmp(op, "CHOP") &&
02499       strcmp(op, "UNITE") &&
02500       strcmp(op, "TWEAK") &&
02501       strcmp(op, "IMPRINT") &&
02502       strcmp(op, "REGULARIZE") &&
02503       strcmp(op, "SPLIT_SURFACE") &&
02504       strcmp(op, "REMOVE_TOPOLOGY") &&
02505       strcmp(op, "SPLIT") &&
02506       strcmp(op, "NON_UNIFORM_SCALE"))
02507     {
02508       if (contains_intermediate_geom(webcut_body_list))
02509       {
02510         PRINT_ERROR("Performing %s on volumes containing virtual geometry is not allowed.\n", op);
02511         ret = CUBIT_FAILURE;
02512       }
02513     }
02514     else
02515     {
02516       if(contains_partitions(webcut_body_list))
02517       {
02518         PRINT_ERROR("Performing %s on volumes containing virtual partitions is not allowed.\n", op);
02519         ret = CUBIT_FAILURE;
02520       }
02521     }
02522   }
02523 
02524   return ret;
02525 }
02526 
02527 
02528 //-------------------------------------------------------------------------
02529 // Purpose       : Common code for finishing webcut operations.
02530 //
02531 // Special Notes :
02532 //
02533 // Creator       : Jason Kraftcheck
02534 //
02535 // Creation Date : 09/25/03
02536 //-------------------------------------------------------------------------
02537 CubitStatus GeometryModifyTool::finish_webcut( DLIList<Body*>& webcut_body_list,
02538                                                DLIList<BodySM*>& result_body_sms,
02539                                                CubitBoolean merge,
02540                                                CubitStatus status,
02541                                                DLIList<Body*>& result_list,
02542                                                DLIList<int> *merged_surface_ids,
02543                                                DLIList<int> *merged_curve_ids,
02544                                                CubitBoolean print_info) const
02545 {
02546    if (!finish_sm_op(webcut_body_list, result_body_sms, result_list,(bool)print_info))
02547      status = CUBIT_FAILURE;
02548 
02549    DLIList<Body*> temp_result_list;
02550    if (status)
02551    {
02552      status = separate_body_after_webcut( result_list, temp_result_list);
02553      result_list = temp_result_list;
02554    }
02555 
02556    if( merged_surface_ids && merged_curve_ids )
02557      fixup_merged_entities( *merged_surface_ids, *merged_curve_ids );
02558 
02559    if (merge && status)
02560    {
02561      DLIList<Body*> temp_results(result_list);
02562      status = MergeTool::instance()->merge_bodies( temp_results );
02563    }
02564    return status;
02565 }
02566 
02567 
02568 //-------------------------------------------------------------------------
02569 // Purpose       : Complete solid modeling operation on bodies
02570 //
02571 // Special Notes :
02572 //
02573 // Creator       : Jason Kraftcheck
02574 //
02575 // Creation Date : 09/25/03
02576 //-------------------------------------------------------------------------
02577 CubitStatus GeometryModifyTool::finish_sm_op( DLIList<Body*>& input_bodies,
02578                                               DLIList<BodySM*>& new_bodies,
02579                                               DLIList<Body*>& result_bodies,
02580                                               bool print_info ) const
02581 {
02582   int i;
02583   GeometryQueryTool* gqt = GeometryQueryTool::instance();
02584 
02585   DLIList<int> updated_ids, created_ids, destroyed_ids;
02586   DLIList<int> updated_vol_ids, created_vol_ids, destroyed_vol_ids;
02587 
02588   // traverse the body object and remove any meshes from modified objects
02589   int b;
02590   for (b = 0; b < input_bodies.size(); b++) {
02591       Body* body = input_bodies.get_and_step();
02592     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_ENTITY_MODIFIED, body));
02593   }
02594 
02595     // Remove dead bodies
02596   input_bodies.reset();
02597   for (i = input_bodies.size(); i--;)
02598   {
02599     Body* body = input_bodies.step_and_get();
02600 
02601     BodySM* bodysm = body->get_body_sm_ptr();
02602     if (!bodysm)
02603     {
02604         // If the body was destroyed, update the list
02605       destroyed_ids.append( body->id() );
02606 
02607       DLIList<RefVolume*> temp_vols;
02608       body->ref_volumes( temp_vols );
02609       for( int nv = temp_vols.size(); nv > 0; nv-- )
02610       {
02611         if( !temp_vols.get()->get_lump_ptr() )
02612           destroyed_vol_ids.append( temp_vols.get_and_step()->id() );
02613       }
02614 
02615       input_bodies.change_to(0);
02616       gqt->destroy_dead_entity(body);
02617     }
02618     else
02619     {
02620       remove_dead_entity_names( body );
02621     }
02622   }
02623   gqt->cleanout_deactivated_geometry();
02624 
02625     // Create new bodies
02626   new_bodies.last();
02627   for (i = new_bodies.size(); i--; )
02628   {
02629     BodySM* bodysm = new_bodies.step_and_get();
02630     bool newbody = bodysm->owner() == 0;
02631     Body* body = gqt->make_Body(bodysm);
02632     result_bodies.append(body);
02633 
02634     if (newbody)
02635     {
02636       created_ids.append(body->id());
02637 
02638       DLIList<RefVolume*> temp_vols;
02639       body->ref_volumes( temp_vols );
02640       for( int nv = temp_vols.size(); nv > 0; nv-- )
02641       {
02642         created_vol_ids.append( temp_vols.get_and_step()->id() );
02643       }
02644     }
02645     else
02646     {
02647       updated_ids.append(body->id());
02648 
02649       DLIList<RefVolume*> temp_vols;
02650       body->ref_volumes( temp_vols );
02651       for( int nv = temp_vols.size(); nv > 0; nv-- )
02652       {
02653         updated_vol_ids.append( temp_vols.get_and_step()->id() );
02654       }
02655     }
02656   }
02657   gqt->cleanout_deactivated_geometry();
02658 
02659   if (print_info)
02660   {
02661     if( DEBUG_FLAG( 153 ) )
02662     {
02663       if (created_ids.size())
02664          CubitUtil::list_entity_ids( "Created body(s): ", created_ids );
02665       if (updated_ids.size())
02666          CubitUtil::list_entity_ids( "Updated body(s): ", updated_ids );
02667       if (destroyed_ids.size())
02668          CubitUtil::list_entity_ids( "Destroyed body(s): ", destroyed_ids );
02669     }
02670 
02671     if (created_vol_ids.size())
02672        CubitUtil::list_entity_ids( "Created volume(s): ", created_vol_ids );
02673     if (updated_vol_ids.size())
02674        CubitUtil::list_entity_ids( "Updated volume(s): ", updated_vol_ids );
02675     if (destroyed_vol_ids.size())
02676        CubitUtil::list_entity_ids( "Destroyed volume(s): ", destroyed_vol_ids );
02677   }
02678 
02679   return CUBIT_SUCCESS;
02680 }
02681 
02682 
02683 
02684 //-------------------------------------------------------------------------
02685 // Purpose       : Webcut a body with a cylinder given the input parameters.
02686 // Special Notes :
02687 //
02688 // Creator       : David White
02689 //
02690 // Creation Date : 10/28/97
02691 //-------------------------------------------------------------------------
02692 CubitStatus GeometryModifyTool::webcut_with_cylinder(
02693                                        DLIList<Body*>& webcut_body_list,
02694                                        double radius,
02695                                        const CubitVector &axis,
02696                                        const CubitVector &center,
02697                                        DLIList<Body*>& results_list,
02698                                        DLIList<Body*> &neighboring_bodies,
02699                                        ImprintType imprint_type,
02700                                        CubitBoolean merge,
02701                                        CubitBoolean preview)
02702 {
02703   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
02704     return CUBIT_FAILURE;
02705 
02706   GfxPreview::clear();
02707 
02708   CubitStatus rval = CUBIT_SUCCESS;
02709 
02710   if (preview)
02711   {
02712     // find the bounding box for the cylinder
02713     CubitBox bounding_box;
02714     Body* body_ptr = webcut_body_list.get_and_step();
02715     bounding_box = body_ptr->bounding_box();
02716 
02717     int i;
02718     for( i=1; i<webcut_body_list.size(); i++ )
02719     {
02720        body_ptr = webcut_body_list.get_and_step();
02721        bounding_box |= body_ptr->bounding_box();
02722     }
02723 
02724     int color = CUBIT_BLUE_INDEX;
02725     GfxPreview::draw_cylinder(axis, center, bounding_box, (float) radius, color);
02726     GfxPreview::flush();
02727     return rval;
02728   }
02729 
02730   if( CubitUndo::get_undo_enabled() )
02731   {
02732     DLIList<Body*> bodies_to_save;
02733     bodies_to_save += webcut_body_list;
02734     bodies_to_save += neighboring_bodies;
02735     CubitUndo::save_state_with_cubit_file( bodies_to_save );
02736   }
02737 
02738   const int count = webcut_body_list.size();
02739   DLIList<BodySM*> result_sm_list;
02740   DLIList<Body*> body_list(webcut_body_list);
02741   DLIList<BodySM*> engine_body_sms(count);
02742   DLIList<Body*> engine_bodies(count);
02743   GeometryModifyEngine* gme = 0;
02744 
02745   if(!preview)
02746     do_attribute_setup();
02747 
02748   while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
02749   {
02750     //get all bodysms that we might modify in this operation
02751     DLIList<BodySM*> neighbor_imprint_list;
02752     DLIList<BodySM*> bodies_sm_to_modify;
02753     DLIList<Body*> bodies_to_modify;
02754     bodies_to_modify += engine_bodies;
02755     int i;
02756     for( i=neighboring_bodies.size(); i--; )
02757     {
02758       Body *tmp_body = neighboring_bodies.get_and_step();
02759       BodySM *tmp_body_sm = tmp_body->get_body_sm_ptr();
02760       if( gme == get_engine(tmp_body_sm ) )
02761       {
02762         neighbor_imprint_list.append( tmp_body_sm );
02763         bodies_to_modify.append( tmp_body );
02764       }
02765     }
02766 
02767     DLIList<int> merged_surface_ids;
02768     DLIList<int> merged_curve_ids;
02769 
02770     if(!preview)
02771     {
02772       bodies_sm_to_modify += neighbor_imprint_list;
02773 
02774       push_attributes_before_modify( bodies_sm_to_modify );
02775       //get all the child entities that have been merged
02776       get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
02777     }
02778 
02779     // note that preview actually gets handled before this point
02780     CubitStatus status = webcut_w_cylinder(engine_body_sms, radius, axis,
02781               center, neighbor_imprint_list, result_sm_list, imprint_type );
02782 
02783     if ( status != CUBIT_FAILURE )
02784     {
02785       if(!preview)
02786       {
02787         restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
02788         remove_pushed_attributes(result_sm_list, bodies_to_modify);
02789       }
02790       status = finish_webcut( engine_bodies, result_sm_list, merge, status,
02791                               results_list, &merged_surface_ids, &merged_curve_ids );
02792     }
02793     else
02794     {
02795       if(!preview)
02796         remove_pushed_attributes(result_sm_list, engine_bodies);
02797     }
02798 
02799 
02800     engine_bodies.clean_out();
02801     engine_body_sms.clean_out();
02802     result_sm_list.clean_out();
02803 
02804     if ( status == CUBIT_FAILURE )
02805     {
02806       rval = CUBIT_FAILURE;
02807       break;
02808     }
02809   }
02810 
02811   if(!preview)
02812     do_attribute_cleanup();
02813 
02814   if( CubitUndo::get_undo_enabled() )
02815   {
02816     if( rval == CUBIT_SUCCESS )
02817       CubitUndo::note_result_bodies( results_list );
02818     else
02819       CubitUndo::remove_last_undo();
02820   }
02821 
02822   return rval;
02823 }
02824 //*************************************************************************************************************************************
02825 //-------------------------------------------------------------------------
02826 // Purpose       : Webcut a body with a cone given the input parameters.
02827 // Special Notes :
02828 //
02829 // Creator       : Ajoy
02830 //
02831 // Creation Date : 04/23/2012
02832 //-------------------------------------------------------------------------
02833 CubitStatus GeometryModifyTool::webcut_with_Cone(
02834                                        DLIList<Body*>& webcut_body_list,
02835                                        DLIList<BodySM*> &webcut_bodySM_list,
02836                                        double outer_radius,double inner_radius,
02837                                        CubitVector& AxisPt1,
02838                                        CubitVector& AxisPt2,
02839                                        DLIList<Body*>& results_list,
02840                                        DLIList<Body*> &neighboring_bodies,
02841                                        ImprintType imprint_type,
02842                                        CubitBoolean merge,
02843                                        CubitBoolean preview)
02844 {
02845     if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
02846         return CUBIT_FAILURE;
02847 
02848     CubitStatus rval = CUBIT_SUCCESS;
02849 
02850 
02851     GfxPreview::clear();
02852 
02853 
02854     // find the height
02855     double dHeight  =  sqrt( (AxisPt2.x()-AxisPt1.x()) * (AxisPt2.x()-AxisPt1.x())+
02856                             (AxisPt2.y()-AxisPt1.y()) * (AxisPt2.y()-AxisPt1.y())+
02857                             (AxisPt2.z()-AxisPt1.z()) * (AxisPt2.z()-AxisPt1.z()) );
02858 
02859     // Find the Tan Angle
02860     double Diff        = fabs(outer_radius - inner_radius);
02861            Diff       /= dHeight;
02862     double dTanAngle   = atan ( Diff ) ;
02863 
02864     if (preview)
02865     {
02866         // find the bounding box for the cylinder
02867         CubitBox bounding_box;
02868         Body* body_ptr = webcut_body_list.get_and_step();
02869         bounding_box = body_ptr->bounding_box();
02870 
02871         int i;
02872         for( i=1; i<webcut_body_list.size(); i++ )
02873         {
02874             body_ptr = webcut_body_list.get_and_step();
02875             bounding_box |= body_ptr->bounding_box();
02876         }
02877 
02878         CubitVector axis;
02879         axis.x( AxisPt2.x()-AxisPt1.x() ); axis.y( AxisPt2.y()-AxisPt1.y() );
02880         axis.z( AxisPt2.z()-AxisPt1.z() );
02881 
02882 
02883         CubitVector start;
02884         CubitVector end;
02885         double dExtendedOuterRadius;
02886         double dExtendedInnerRadius;
02887 
02888 
02889         // Now extend the 2 end points to extend beyond the BBox limits. In case it converges, stop at the Apex.
02890 
02891          FindExtendedPoints( AxisPt1 , AxisPt2 , outer_radius , inner_radius , axis, dHeight , bounding_box ,
02892                              dTanAngle, start , end, dExtendedOuterRadius , dExtendedInnerRadius );
02893 
02894         int color = CUBIT_BLUE_INDEX;
02895         GfxPreview::draw_frustum(axis, start, end, dExtendedOuterRadius, dExtendedInnerRadius ,bounding_box , color);
02896         GfxPreview::flush();
02897         return rval;
02898     }
02899 
02900     if( CubitUndo::get_undo_enabled() )
02901     {
02902         DLIList<Body*> bodies_to_save;
02903         bodies_to_save += webcut_body_list;
02904         bodies_to_save += neighboring_bodies;
02905         CubitUndo::save_state_with_cubit_file( bodies_to_save );
02906     }
02907 
02908     const int count = webcut_body_list.size();
02909     DLIList<BodySM*> result_sm_list;
02910     DLIList<Body*> body_list(webcut_body_list);
02911     DLIList<BodySM*> engine_body_sms(count);
02912     DLIList<Body*> engine_bodies(count);
02913     GeometryModifyEngine* gme = 0;
02914 
02915     if(!preview)
02916         do_attribute_setup();
02917 
02918     while ( (gme = group_bodies_by_engine(webcut_body_list, engine_bodies, engine_body_sms)) )
02919     {
02920         //get all bodysms that we might modify in this operation
02921         DLIList<BodySM*> neighbor_imprint_list;
02922         DLIList<BodySM*> bodies_sm_to_modify;
02923         DLIList<Body*> bodies_to_modify;
02924         bodies_to_modify += engine_bodies;
02925         int i;
02926         for( i=neighboring_bodies.size(); i--; )
02927         {
02928             Body *tmp_body = neighboring_bodies.get_and_step();
02929             BodySM *tmp_body_sm = tmp_body->get_body_sm_ptr();
02930             if( gme == get_engine(tmp_body_sm ) )
02931             {
02932                 neighbor_imprint_list.append( tmp_body_sm );
02933                 bodies_to_modify.append( tmp_body );
02934             }
02935         }
02936 
02937 
02938         DLIList<BodySM*> Body_to_Cut_SM;
02939 
02940         for( i = 0 ;i<webcut_body_list.size(); i++  )
02941         {
02942             Body* body           = webcut_body_list.get_and_step();
02943             BodySM *Body_To_Cut  = body->get_body_sm_ptr();
02944 
02945             Body_to_Cut_SM.append( Body_To_Cut ) ;
02946         }
02947 
02948 
02949 
02950         DLIList<int> merged_surface_ids;
02951         DLIList<int> merged_curve_ids;
02952 
02953         if(!preview)
02954         {
02955             bodies_sm_to_modify += neighbor_imprint_list;
02956 
02957             push_attributes_before_modify( bodies_sm_to_modify );
02958             //get all the child entities that have been merged
02959             get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
02960         }
02961 
02962 
02963         // Get the overall bounding box of the bodies list
02964         Body* body_ptr = NULL;
02965         CubitBox bounding_box;
02966         if(body_list.size())
02967         {
02968             body_ptr  = body_list.get_and_step();
02969             bounding_box = body_ptr->bounding_box();
02970             for( i=1; i<webcut_body_list.size(); i++ )
02971             {
02972                 body_ptr = body_list.get_and_step();
02973                 bounding_box |= body_ptr->bounding_box();
02974             }
02975         }
02976 
02977 
02978 
02979         // Get the Geometry engine
02980         GeometryModifyEngine* gme =
02981             GeometryModifyTool::instance()->get_engine( body_ptr );
02982 
02983 
02985         //CubitStatus status = CreateCircularBody(webcut_body_list );
02986 
02987         CubitStatus status = CUBIT_SUCCESS;
02988 
02989 
02990         CubitVector axis;
02991         axis.x( AxisPt2.x()-AxisPt1.x() ); axis.y( AxisPt2.y()-AxisPt1.y() );
02992         axis.z( AxisPt2.z()-AxisPt1.z() );
02993 
02994 
02995 
02996 
02997         // Set The important deciders.
02998 
02999         bool bIfReverseAxis = false;
03000         if( outer_radius < inner_radius )
03001         {
03002             bIfReverseAxis = true;
03003         }
03004 
03005 
03006         //**************************************//
03007         // find the extension of the narrow end.
03008         //**************************************//
03009 
03010         // For this find the extended end point, at the smaller end
03011         // and assign zero radius, setting that point to be the AxisPt2.
03012 
03013         // Will be done only if outerRad is bigger than innerRad
03014         // Else set a bool to remember that, the inner_radius is set as the outer.
03015 
03016         CubitVector endpt ;
03017         if( outer_radius > inner_radius )
03018         {
03019             //EndPt  = FindExtendedEndPt( outer_radius , inner_radius , AxisPt2 , axis,  dHeight );
03020 
03021 
03022             double Diff     = (outer_radius - inner_radius);
03023             Diff    /= dHeight;
03024             double dAngle   = atan ( Diff ) ;
03025             axis.normalize();
03026 
03027             double dTan         = tan( dAngle );
03028             double dExtendvalue = inner_radius / dTan;
03029 
03030             endpt.x( ( axis.x() * dExtendvalue )  + AxisPt2.x() );
03031             endpt.y( ( axis.y() * dExtendvalue )  + AxisPt2.y() );
03032             endpt.z( ( axis.z() * dExtendvalue )  + AxisPt2.z() );
03033 
03034 
03035 
03036             dHeight = sqrt( (endpt.x() - AxisPt1.x()) * (endpt.x() - AxisPt1.x())+
03037                 (endpt.y() - AxisPt1.y()) * (endpt.y() - AxisPt1.y())+
03038                 (endpt.z() - AxisPt1.z()) * (endpt.z() - AxisPt1.z()) );
03039 
03040             AxisPt2.x( endpt.x() );
03041             AxisPt2.y( endpt.y() );
03042             AxisPt2.z( endpt.z() );
03043         }
03044         else
03045         {
03046             // reverse the axis.
03047 
03048             axis.x( -axis.x());
03049             axis.y( -axis.y());
03050             axis.z( -axis.z());
03051 
03052             //endpt  = FindExtendedendpt( inner_radius , outer_radius , AxisPt1 , axis,  dHeight );
03053 
03054 
03055             double Diff     = (inner_radius - outer_radius);
03056             Diff    /= dHeight;
03057             double dAngle   = atan ( Diff ) ;
03058             axis.normalize();
03059 
03060             double dTan        = tan( dAngle );
03061             double dExtendvalue = outer_radius / dTan;
03062 
03063             endpt.x( ( axis.x() * dExtendvalue )  + AxisPt1.x() );
03064             endpt.y( ( axis.y() * dExtendvalue )  + AxisPt1.y() );
03065             endpt.z( ( axis.z() * dExtendvalue )  + AxisPt1.z() );
03066 
03067 
03068 
03069 
03070             dHeight = sqrt( (endpt.x() - AxisPt2.x()) * (endpt.x() - AxisPt2.x())+
03071                 (endpt.y() - AxisPt2.y()) * (endpt.y() - AxisPt2.y())+
03072                 (endpt.z() - AxisPt2.z()) * (endpt.z() - AxisPt2.z()) );
03073 
03074             AxisPt1.x( endpt.x() );
03075             AxisPt1.y( endpt.y() );
03076             AxisPt1.z( endpt.z() );
03077 
03078              // reset the axis.
03079 
03080             axis.x( -axis.x());
03081             axis.y( -axis.y());
03082             axis.z( -axis.z());
03083 
03084         }
03085 
03086 
03087 
03088         //*****************************************//
03089         // Now find the extension of the bigger end.
03090         //*****************************************//
03091 
03092         //CubitVector EndPt ;
03093         double dExtendedRadius;
03094         if( outer_radius > inner_radius )
03095         {
03096             // reverse the axis.
03097             axis.x( -axis.x());
03098             axis.y( -axis.y());
03099             axis.z( -axis.z());
03100 
03101 
03102             //EndPt  = FindExtendedStartPt( bounding_box , outer_radius , inner_radius , AxisPt1 , axis,  dHeight , dTanAngle , dExtendedRadius );
03103 
03104 
03105 
03106             CubitVector Extended_Start_Pt;
03107 
03108             // Find the Difference between the Max and thre min values in all 3 directions.
03109             // Incase the point is within the box limits, then add the difference values
03110             // in all 3 directions , witht he " Axis " as the direction vector and extend the point.
03111 
03112             // After that find the Radius of this bigger end.
03113 
03114             CubitVector DiffVec;
03115 
03116             axis.normalize();
03117 
03118             DiffVec.x( fabs( bounding_box.max_x() - bounding_box.min_x() ));
03119             DiffVec.y( fabs( bounding_box.max_y() - bounding_box.min_y() ));
03120             DiffVec.z( fabs( bounding_box.max_z() - bounding_box.min_z() ));
03121 
03122             // Extend the start Pt
03123 
03124             Extended_Start_Pt.x( AxisPt1.x() + ( axis.x() * DiffVec.x() ) );
03125             Extended_Start_Pt.y( AxisPt1.y() + ( axis.y() * DiffVec.y() ) );
03126             Extended_Start_Pt.z( AxisPt1.z() + ( axis.z() * DiffVec.z() ) );
03127 
03128 
03129             // Find the length
03130 
03131             double dLength = sqrt( (( AxisPt1.x() - Extended_Start_Pt.x()) *  (AxisPt1.x() - Extended_Start_Pt.x()) ) +
03132                 (( AxisPt1.y() - Extended_Start_Pt.y()) *  (AxisPt1.y() - Extended_Start_Pt.y()) ) +
03133                 (( AxisPt1.z() - Extended_Start_Pt.z()) *  (AxisPt1.z() - Extended_Start_Pt.z()) ) );
03134 
03135 
03136 
03137             // Find the Extended Radius
03138 
03139             dExtendedRadius = outer_radius + ( tan( dTanAngle ) * dLength ) ;
03140 
03141 
03142             dHeight = sqrt( (Extended_Start_Pt.x() - AxisPt2.x()) * (Extended_Start_Pt.x() - AxisPt2.x())+
03143                 (Extended_Start_Pt.y() - AxisPt2.y()) * (Extended_Start_Pt.y() - AxisPt2.y())+
03144                 (Extended_Start_Pt.z() - AxisPt2.z()) * (Extended_Start_Pt.z() - AxisPt2.z()) );
03145 
03146             if( dExtendedRadius == 0 )
03147                 dExtendedRadius = outer_radius;
03148 
03149             AxisPt1.x( Extended_Start_Pt.x() );
03150             AxisPt1.y( Extended_Start_Pt.y() );
03151             AxisPt1.z( Extended_Start_Pt.z() );
03152 
03153             // reverse the axis.
03154             axis.x( -axis.x());
03155             axis.y( -axis.y());
03156             axis.z( -axis.z());
03157 
03158         }
03159         else
03160         {
03161             //EndPt  = FindExtendedStartPt( bounding_box ,  inner_radius , outer_radius , AxisPt2 , axis,  dHeight , dTanAngle , dExtendedRadius );
03162 
03163 
03164 
03165 
03166             CubitVector Extended_Start_Pt;
03167 
03168             // Find the Difference between the Max and thre min values in all 3 directions.
03169             // Incase the point is within the box limits, then add the difference values
03170             // in all 3 directions , witht he " Axis " as the direction vector and extend the point.
03171 
03172             // After that find the Radius of this bigger end.
03173 
03174             CubitVector DiffVec;
03175 
03176             axis.normalize();
03177 
03178             DiffVec.x( fabs( bounding_box.max_x() - bounding_box.min_x() ));
03179             DiffVec.y( fabs( bounding_box.max_y() - bounding_box.min_y() ));
03180             DiffVec.z( fabs( bounding_box.max_z() - bounding_box.min_z() ));
03181 
03182             // Extend the start Pt
03183 
03184             Extended_Start_Pt.x( AxisPt2.x() + ( axis.x() * DiffVec.x() ) );
03185             Extended_Start_Pt.y( AxisPt2.y() + ( axis.y() * DiffVec.y() ) );
03186             Extended_Start_Pt.z( AxisPt2.z() + ( axis.z() * DiffVec.z() ) );
03187 
03188 
03189             // Find the length
03190 
03191             double dLength = sqrt( (( AxisPt2.x() - Extended_Start_Pt.x()) *  (AxisPt2.x() - Extended_Start_Pt.x()) ) +
03192                 (( AxisPt2.y() - Extended_Start_Pt.y()) *  (AxisPt2.y() - Extended_Start_Pt.y()) ) +
03193                 (( AxisPt2.z() - Extended_Start_Pt.z()) *  (AxisPt2.z() - Extended_Start_Pt.z()) ) );
03194 
03195 
03196 
03197             // Find the Extended Radius
03198 
03199             dExtendedRadius = inner_radius + ( tan( dTanAngle ) * dLength ) ;
03200 
03201 
03202             dHeight = sqrt( (Extended_Start_Pt.x() - AxisPt1.x()) * (Extended_Start_Pt.x() - AxisPt1.x())+
03203                 (Extended_Start_Pt.y() - AxisPt1.y()) * (Extended_Start_Pt.y() - AxisPt1.y())+
03204                 (Extended_Start_Pt.z() - AxisPt1.z()) * (Extended_Start_Pt.z() - AxisPt1.z()) );
03205 
03206             AxisPt2.x( Extended_Start_Pt.x() );
03207             AxisPt2.y( Extended_Start_Pt.y() );
03208             AxisPt2.z( Extended_Start_Pt.z() );
03209 
03210             if( dExtendedRadius == 0 )
03211                 dExtendedRadius = outer_radius;
03212 
03213         }
03214 
03215 
03216 
03217         //Create the cylinder
03218 
03219         BodySM* bodySM_Ptr = NULL;
03220         outer_radius       = dExtendedRadius;
03221         inner_radius       = 0;
03222         bodySM_Ptr         = gmeList.get()->cylinder( dHeight, outer_radius, outer_radius, inner_radius );
03223 
03224 
03225         if( !bodySM_Ptr )
03226         {
03227             return CUBIT_FAILURE;
03228         }
03229 
03230 
03231         DLIList<Curve*> curve_list;
03232 
03233         bodySM_Ptr->curves(curve_list);
03234 
03235         // infor for the Frustum Axis
03236 
03237         CubitVector Frustum_Axis;
03238 
03239         Frustum_Axis.x(0);
03240         Frustum_Axis.y(0);
03241         Frustum_Axis.z(dHeight);
03242 
03243 
03244 
03245 
03246         if( bIfReverseAxis )
03247             axis.z( -axis.z() );
03248 
03249 
03250         // Get Cross product for the resultant vector, which will be the axis for rotation
03251         CubitVector cross;
03252         cross = Frustum_Axis * axis;
03253 
03254 
03255         // 2. Find the Angle Between them
03256         CubitVector Angle;
03257         double dAngle  = Angle.vector_angle( Frustum_Axis , axis );
03258 
03259 
03260 
03261         //Now find the angle and the axis to rotate about...
03262 
03263         dAngle = 180.0*dAngle/CUBIT_PI;
03264 
03265         if( bIfReverseAxis )
03266             dAngle = 360 - dAngle ;
03267 
03268 
03269 
03270         // 3. Rotate the body for the received cross product axis ( cross ) as the axis
03271         // and for the angle, dAngle
03272         //GeometryQueryTool::instance()->rotate( cutting_tool_ptr , cross , dAngle );
03273 
03274         GeometryQueryEngine* engine = bodySM_Ptr->get_geometry_query_engine();
03275         CubitStatus result = engine->rotate( bodySM_Ptr, cross, dAngle );
03276 
03277 
03278         // 4. Now find the mid-point of the specified 2 vertices, and assign that as the
03279         //    2'nd parameter, for the Pt at which the center of the, created frustum should lie.
03280 
03281         CubitVector Pt;
03282         Pt.x( (AxisPt1.x() + AxisPt2.x() )/2  );
03283         Pt.y( (AxisPt1.y() + AxisPt2.y() )/2  );
03284         Pt.z( (AxisPt1.z() + AxisPt2.z() )/2  );
03285 
03286 
03287 
03288         // 5 . Now move the body to the location of the target_center.
03289 
03290         CubitTransformMatrix xform;
03291         xform.translate( Pt );
03292         result = engine->translate( bodySM_Ptr, Pt );
03293 
03294 
03295 
03296 
03297         if (!result )
03298         {
03299             if(!preview)
03300             {
03301                 restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
03302                 remove_pushed_attributes(result_sm_list, bodies_to_modify);
03303             }
03304             status = finish_webcut( engine_bodies, result_sm_list, merge, status,
03305                 results_list, &merged_surface_ids, &merged_curve_ids );
03306         }
03307         else
03308         {
03309             if(!preview)
03310                 remove_pushed_attributes(result_sm_list, engine_bodies);
03311         }
03312 
03313         if ( !result )
03314         {
03315             rval = CUBIT_FAILURE;
03316             engine_bodies.clean_out();
03317             engine_body_sms.clean_out();
03318             result_sm_list.clean_out();
03319             return rval;
03320         }
03321 
03322         DLIList<BodySM*> results_list_SM;
03323         DLIList<BodySM*> neighboring_bodies_SM;
03324         // Use the BODY to perform webcut
03325         rval = gme->webcut(engine_body_sms, bodySM_Ptr,
03326             neighboring_bodies_SM, results_list_SM, imprint_type, preview );
03327 
03328         if( GeometryQueryTool::instance()->history().is_tracking() )
03329         {
03330             if( rval == CUBIT_SUCCESS )
03331             {
03332                 gme->get_gqe()->delete_solid_model_entities(bodySM_Ptr);
03333             }
03334         }
03335 
03336         // if we're doing the real thing (not preview) finish the process
03337         if (!preview)
03338         {
03339             restore_vg_after_modify(results_list_SM, body_list, gme);
03340             remove_pushed_attributes(results_list_SM, body_list);
03341             rval = finish_webcut( bodies_to_modify, results_list_SM, merge,
03342                 rval, results_list);
03343             do_attribute_cleanup();
03344 
03345             //GeometryQueryTool::instance()->delete_Body( cutting_tool_ptr );
03346             GeometryQueryEngine* gqe = bodySM_Ptr->get_geometry_query_engine();
03347             gqe->delete_solid_model_entities(bodySM_Ptr);
03348         }
03349 
03350         if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
03351         {
03352             if( rval == CUBIT_SUCCESS )
03353                 CubitUndo::note_result_bodies( results_list );
03354             else
03355                 CubitUndo::remove_last_undo();
03356         }
03357 
03358         engine_bodies.clean_out();
03359         engine_body_sms.clean_out();
03360         result_sm_list.clean_out();
03361     }
03362     return rval;
03363 }
03364 //************************************************************************************************************************************************************
03365 void GeometryModifyTool::do_attribute_setup(void)
03366 {
03367   //save attribute settings
03368   CGMApp::instance()->save_current_attribute_states();
03369 
03370   //Turn off all attributes
03371   CubitAttribManager *attrib_manager = CGMApp::instance()->attrib_manager();
03372   attrib_manager->set_all_auto_update_flags( CUBIT_FALSE );
03373   attrib_manager->set_all_auto_actuate_flags( CUBIT_FALSE );
03374   attrib_manager->set_all_auto_write_flags( CUBIT_FALSE );
03375   attrib_manager->set_all_auto_read_flags( CUBIT_FALSE );
03376 
03377   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ENTITY_NAME, CUBIT_TRUE);
03378   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_ENTITY_NAME, CUBIT_TRUE);
03379   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_ENTITY_NAME, CUBIT_TRUE);
03380   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_ENTITY_NAME, CUBIT_TRUE);
03381 
03382   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_MESH_OUTPUT_GROUP, CUBIT_TRUE);
03383   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_MESH_OUTPUT_GROUP, CUBIT_TRUE);
03384   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_MESH_OUTPUT_GROUP, CUBIT_TRUE);
03385   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_MESH_OUTPUT_GROUP, CUBIT_TRUE);
03386 
03387 
03388   // enable update, actuate, write, read for composite attributes
03389   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_COMPOSITE_VG, CUBIT_TRUE);
03390   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_COMPOSITE_VG, CUBIT_TRUE);
03391   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_COMPOSITE_VG, CUBIT_TRUE);
03392   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_COMPOSITE_VG, CUBIT_TRUE);
03393   // enable update, actuate, write, read for partition attributes
03394   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_PARTITION_VG, CUBIT_TRUE);
03395   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_PARTITION_VG, CUBIT_TRUE);
03396   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_PARTITION_VG, CUBIT_TRUE);
03397   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_PARTITION_VG, CUBIT_TRUE);
03398   // enable update, actuate, write, read for entity ids
03399   // We will use these ID atts to make sure the ref entities associated with unmodified
03400   // virtual bridges will maintain the same ids after real operations.
03401   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ENTITY_ID, CUBIT_TRUE);
03402   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_ENTITY_ID, CUBIT_TRUE);
03403   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_ENTITY_ID, CUBIT_TRUE);
03404   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_ENTITY_ID, CUBIT_TRUE);
03405   // enable metadata attributes
03406   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ASSEMBLY_DATA, CUBIT_TRUE);
03407   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_ASSEMBLY_DATA, CUBIT_TRUE);
03408   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_ASSEMBLY_DATA, CUBIT_TRUE);
03409   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_ASSEMBLY_DATA, CUBIT_TRUE);
03410 }
03411 
03412 void GeometryModifyTool::do_attribute_cleanup(void)
03413 {
03414 
03415   CGMApp::instance()->restore_previous_attribute_states();
03416 }
03417 
03418 // Pushes virtual geometry and boundary condition
03419 //attributes down to the underlying solid model topology
03420 void GeometryModifyTool::push_attributes_before_modify(DLIList<BodySM*> &old_sms)
03421 {
03422   // Get all of the ref entities involved and push CA_ENTITY_ID attributes
03423   // on to them.  This will help us maintain ids on virtual that doesn't
03424   // get modified by the real operation.
03425   int i;
03426   DLIList<RefVolume*> volume_list;
03427 
03428   for(i=old_sms.size(); i--;)
03429   {
03430     BodySM *bsm = old_sms.get_and_step();
03431     Body *body = dynamic_cast<Body*>(bsm->topology_entity());
03432     if(body)
03433     {
03434       // Append to the total list of volumes.
03435       body->ref_volumes(volume_list);
03436     }
03437   }
03438   // get all child entities (only get entities below volumes)
03439   DLIList<RefEntity*> child_list, ref_ent_list;
03440   CAST_LIST_TO_PARENT(volume_list, ref_ent_list);
03441   RefEntity::get_all_child_ref_entities( ref_ent_list, child_list );
03442 
03443   //by including the volumes we can propagate the bcs on them
03444   //across webcuts
03445   child_list+=ref_ent_list;
03446 
03447 
03448   // Only push the id attributes if we are doing persistent ids.
03449   if(!get_new_ids())
03450     CubitAttribUser::auto_update_cubit_attrib(child_list);
03451 
03452   DLIList<TopologyBridge*> top_bridges;
03453   CAST_LIST_TO_PARENT(old_sms, top_bridges);
03454   GeometryQueryTool::instance()->ige_export_geom(top_bridges);
03455 }
03456 
03457 // Push imprint specific attributes down to the underlying solid model
03458 // topology prior to imprinting.
03459 void GeometryModifyTool::push_imprint_attributes_before_modify(DLIList<BodySM*> &body_sms)
03460 {
03461   GeometryQueryTool::instance()->ige_push_imprint_attributes_before_modify(body_sms);
03462 }
03463 
03464 void GeometryModifyTool::push_named_attributes_to_curves_and_points(DLIList<TopologyBridge*> &tb_list,
03465                                                              const char *name_in)
03466 {
03467   GeometryQueryTool::instance()->ige_push_named_attributes_to_curves_and_points(tb_list, name_in);
03468 }
03469 
03470 // Cleanup imprint attributes that were pushed onto the underlying solid
03471 // model topology.
03472 void GeometryModifyTool::remove_imprint_attributes_after_modify(DLIList<BodySM*> &old_sms,
03473                                                                 DLIList<BodySM*> &new_sms)
03474 {
03475   GeometryQueryTool::instance()->ige_remove_imprint_attributes_after_modify(old_sms, new_sms);
03476 }
03477 
03478 #ifdef CAT
03479 CubitStatus GeometryModifyTool::webcut_across_translate(
03480                                           DLIList<Body*> &webcut_body_list,
03481                                           RefFace *ref_face_top,
03482                                           RefFace *ref_face_bottom,
03483                                           DLIList<Body*> &results_list,
03484                                           ImprintType imprint_type,
03485                                           CubitBoolean merge,
03486                                           CubitBoolean preview)
03487 {
03488   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
03489     return CUBIT_FAILURE;
03490 
03491   DLIList<Body*> original_body_list = webcut_body_list;
03492   const int count = webcut_body_list.size() + 2;
03493   DLIList<TopologyEntity*> entity_list(count);
03494   DLIList<TopologyBridge*> bridge_list(count);
03495   CAST_LIST_TO_PARENT(webcut_body_list, entity_list);
03496   entity_list.append( ref_face_top );
03497   entity_list.append( ref_face_bottom );
03498   GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
03499 
03500   if ( !gme )
03501   {
03502      PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from\n"
03503                  "different modeling engines is not allowed.\n"
03504                  "Delete uncommon geometry on these volumes before operation.\n\n");
03505      return CUBIT_FAILURE;
03506   }
03507 
03508   Surface* surface_bottom = dynamic_cast<Surface*>(bridge_list.pop());
03509   Surface* surface_top    = dynamic_cast<Surface*>(bridge_list.pop());
03510   DLIList<BodySM*> result_sm_list, webcut_sm_list(bridge_list.size());
03511   CAST_LIST(bridge_list, webcut_sm_list, BodySM);
03512 
03513   if (!preview)
03514   {
03515     do_attribute_setup();
03516     push_attributes_before_modify(webcut_sm_list);
03517   }
03518 
03519   DLIList<BodySM*> neighbor_list;
03520   CubitStatus result_val = gme->webcut_across_translate (
03521     webcut_sm_list, surface_top, surface_bottom, result_sm_list, neighbor_list, imprint_type, preview );
03522 
03523   // if we're doing the real thing (not preview) finish the process
03524   if (!preview)
03525   {
03526     restore_vg_after_modify(result_sm_list, original_body_list, gme);
03527     remove_pushed_attributes(result_sm_list, original_body_list);
03528     result_val = finish_webcut( webcut_body_list, result_sm_list, merge,
03529                                 result_val, results_list);
03530     do_attribute_cleanup();
03531   }
03532 
03533   return result_val;
03534 }
03535 #endif
03536 
03537 //-------------------------------------------------------------------------
03538 // Purpose       : This functions webcuts a list of bodies using a loop
03539 //                 of curves
03540 //
03541 // Special Notes :
03542 //
03543 // Creator       : Eric W. Nielsen
03544 //
03545 // Creation Date : 12/20/99
03546 //-------------------------------------------------------------------------
03547 CubitStatus GeometryModifyTool::webcut_with_curve_loop(
03548                                          DLIList<Body*>& webcut_body_list,
03549                                          DLIList<RefEdge*>& refedge_list,
03550                                          DLIList<Body*>& results_list,
03551                                          DLIList<Body*> &neighboring_bodies,
03552                                          ImprintType imprint_type,
03553                                          CubitBoolean merge,
03554                                          CubitBoolean preview)
03555 
03556 {
03557   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
03558     return CUBIT_FAILURE;
03559 
03560   GfxPreview::clear();
03561 
03562    int i;
03563    const int count = webcut_body_list.size() + refedge_list.size();
03564    DLIList<TopologyEntity*> entity_list(count);
03565    DLIList<TopologyBridge*> bridge_list(count);
03566    CAST_LIST_TO_PARENT(webcut_body_list, entity_list);
03567    refedge_list.reset();
03568    for (i = refedge_list.size(); i--; )
03569      entity_list.append(refedge_list.get_and_step());
03570    GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
03571 
03572    if ( !gme )
03573    {
03574       PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from\n"
03575                   "different modeling engines is not allowed.\n"
03576                   "Delete uncommon geometry on these volumes before operation.\n\n");
03577       return CUBIT_FAILURE;
03578    }
03579 
03580    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
03581    {
03582      DLIList<Body*> bodies_to_save;
03583      bodies_to_save += webcut_body_list;
03584      bodies_to_save += neighboring_bodies;
03585      CubitUndo::save_state_with_cubit_file( bodies_to_save );
03586    }
03587 
03588    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), result_sm_list;
03589    DLIList<Curve*> curve_list(refedge_list.size());
03590    CAST_LIST(bridge_list, body_sm_list, BodySM);
03591    CAST_LIST(bridge_list, curve_list, Curve);
03592    assert(body_sm_list.size() == webcut_body_list.size());
03593    assert(curve_list.size() == refedge_list.size());
03594 
03595    DLIList<int> merged_surface_ids;
03596    DLIList<int> merged_curve_ids;
03597    DLIList<BodySM*> neighbor_imprint_list;
03598    DLIList<Body*> bodies_to_modify;
03599 
03600    //make copies of the curves.
03601    DLIList<Curve*> copied_curves;
03602    Curve* temp_curve = NULL;
03603    for (int i = curve_list.size(); i--;)
03604      {
03605        temp_curve = gme->make_Curve(curve_list.get_and_step());
03606        if(temp_curve != NULL)
03607          copied_curves.append(temp_curve);
03608      }
03609 
03610    //make a face out of the curves
03611    Surface * surf = gme->make_Surface(PLANE_SURFACE_TYPE, copied_curves, NULL, false );
03612    if (surf == NULL)
03613      {
03614        PRINT_ERROR("webcut tool surface is not created from occ.\n");
03615        return CUBIT_FAILURE;
03616      }
03617 
03618 
03619    //get cutting tool BodySM.
03620    BodySM* cutting_tool_ptr = gme->make_BodySM(surf);
03621    assert(cutting_tool_ptr );
03622 
03623    if (!preview)
03624    {
03625      int i;
03626      for( i=neighboring_bodies.size(); i--; )
03627      {
03628        Body *neighbor_body = neighboring_bodies.get_and_step();
03629        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
03630        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
03631 
03632        if( gme == neighbor_gme )
03633          neighbor_imprint_list.append( tmp_body );
03634      }
03635 
03636      do_attribute_setup();
03637      DLIList<BodySM*> bodies_sm_to_modify;
03638      bodies_sm_to_modify += body_sm_list;
03639      bodies_sm_to_modify += neighbor_imprint_list;
03640      push_attributes_before_modify( bodies_sm_to_modify );
03641      bodies_to_modify += webcut_body_list;
03642      bodies_to_modify += neighboring_bodies;
03643      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
03644    }
03645 
03646 
03647    CubitStatus result_val = gme->webcut(
03648                      body_sm_list, cutting_tool_ptr,
03649                      neighbor_imprint_list,
03650                      result_sm_list,
03651                      imprint_type, preview) ;
03652 
03653    // Delete the BodySM that was created to be used as a tool
03654    gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
03655 
03656    // finish up if we're doing the real thing
03657    if (!preview)
03658    {
03659      restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
03660      remove_pushed_attributes(result_sm_list, bodies_to_modify);
03661 
03662      result_val = finish_webcut( webcut_body_list, result_sm_list, merge,
03663                                  result_val, results_list,
03664                                  &merged_surface_ids, &merged_curve_ids );
03665      do_attribute_cleanup();
03666    }
03667 
03668   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
03669   {
03670     if( result_val == CUBIT_SUCCESS )
03671       CubitUndo::note_result_bodies( results_list );
03672     else
03673       CubitUndo::remove_last_undo();
03674   }
03675 
03676    return result_val;
03677 }
03678 
03679 //-------------------------------------------------------------------------
03680 // Purpose       : This functions webcuts a list of bodies through a plane
03681 //                 defined by a refFace. The newly created bodies are
03682 //                 merged and imprinted depeding on the respective flags.
03683 //
03684 // Special Notes :
03685 //
03686 // Creator       : Raikanta Sahu
03687 //
03688 // Creation Date : 12/16/96
03689 //-------------------------------------------------------------------------
03690 
03691 CubitStatus GeometryModifyTool::webcut_with_surface(
03692                                       DLIList<Body*>& webcut_body_list,
03693                                       RefFace* refFace,
03694                                       DLIList<Body*>& results_list,
03695                                       DLIList<Body*> &neighboring_bodies,
03696                                       ImprintType imprint_type,
03697                                       CubitBoolean merge,
03698                                       CubitBoolean preview)
03699 {
03700   //make sure that this refface is planar, or you'll get unexpected results
03701   if( refFace->geometry_type() != PLANE_SURFACE_TYPE )
03702   {
03703     PRINT_ERROR("Surface %d is not planar.\n", refFace->id() );
03704     return CUBIT_FAILURE;
03705   }
03706 
03707      // Using the face, get three positions (CubitVectors :) :) )
03708      // The positions can be used by a GeometryModifyEngine to generate its
03709      // own webcutting tool and perform the webcut.
03710    CubitVector vector1 = refFace->position_from_u_v(0, 1) ;
03711    CubitVector vector3 = refFace->position_from_u_v(1, 0) ;
03712    CubitVector vector2 = refFace->position_from_u_v(0, 0) ;
03713 
03714    CubitStatus result_val = this->webcut_with_plane(webcut_body_list, vector1,
03715                                   vector2, vector3, results_list, neighboring_bodies,
03716                                   imprint_type, merge, preview) ;
03717 
03718    return result_val;
03719 }
03720 
03721 //-------------------------------------------------------------------------
03722 // Purpose       : This functions webcuts a list of bodies using a plane
03723 //                 defined by a refFace. The newly created bodies are
03724 //                 merged and imprinted depending on the respective flags.
03725 //
03726 // Special Notes :
03727 //
03728 // Creator       : Raikanta Sahu
03729 //
03730 // Creation Date : 12/16/96
03731 //-------------------------------------------------------------------------
03732 
03733 CubitStatus GeometryModifyTool::webcut_with_body(
03734                                    DLIList<Body*>& webcut_body_list,
03735                                    Body* tool_body,
03736                                    DLIList<Body*>& results_list,
03737                                    DLIList<Body*> &neighboring_bodies,
03738                                    ImprintType imprint_type,
03739                                    CubitBoolean merge,
03740                                    CubitBoolean preview)
03741 {
03742 
03743   CubitStatus ret;
03744 
03745   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
03746     return CUBIT_FAILURE;
03747 
03748   CubitBox tool_bounding_box = tool_body->bounding_box();
03749   remove_bodies_outside_bounding_box( webcut_body_list, tool_bounding_box );
03750 
03751   if( webcut_body_list.size() == 0 )
03752   {
03753     PRINT_INFO("Tool does not intersect any bodies/volumes.\n");
03754     return CUBIT_FAILURE;
03755   }
03756 
03757   DLIList<BodySM*> body_sm_list(webcut_body_list.size()), result_sm_list;
03758   BodySM* tool_sm = tool_body->get_body_sm_ptr();
03759   GeometryModifyEngine* gme = 0;
03760   if (!tool_sm || !(gme = get_engine(tool_sm)))
03761   {
03762     PRINT_DEBUG_153("No modify engine available for body %d.\n", tool_body->id());
03763     PRINT_ERROR("No modify engine available for volume %d.\n", tool_body->ref_volume()->id());
03764     return CUBIT_FAILURE;
03765   }
03766 
03767   webcut_body_list.reset();
03768   int i;
03769   for (i = webcut_body_list.size(); i--; )
03770   {
03771     Body* body_ptr = webcut_body_list.get_and_step();
03772     BodySM* sm_ptr = body_ptr->get_body_sm_ptr();
03773     if (!sm_ptr || get_engine(sm_ptr) != gme)
03774     {
03775       PRINT_DEBUG_153("ERROR: Body %d does not belong to the same geometric engine "
03776                   "as body %d\n", body_ptr->id(), tool_body->id());
03777       PRINT_ERROR("Volume %d does not belong to the same geometric engine "
03778                   "as volume %d\n", body_ptr->ref_volume()->id(), tool_body->ref_volume()->id());
03779       return CUBIT_FAILURE;
03780     }
03781 
03782     body_sm_list.append(sm_ptr);
03783   }
03784 
03785   DLIList<int> merged_surface_ids;
03786   DLIList<int> merged_curve_ids;
03787   DLIList<BodySM*> neighbor_imprint_list;
03788   DLIList<Body*> bodies_to_modify;
03789 
03790   if (!preview)
03791   {
03792     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
03793     {
03794       DLIList<Body*> bodies_to_save;
03795       bodies_to_save += webcut_body_list;
03796       bodies_to_save += neighboring_bodies;
03797       CubitUndo::save_state_with_cubit_file( bodies_to_save );
03798     }
03799 
03800     int i;
03801     for( i=neighboring_bodies.size(); i--; )
03802     {
03803       Body *neighbor_body = neighboring_bodies.get_and_step();
03804       BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
03805       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
03806 
03807       if( gme == neighbor_gme )
03808         neighbor_imprint_list.append( tmp_body );
03809     }
03810 
03811     do_attribute_setup();
03812     DLIList<BodySM*> bodies_sm_to_modify;
03813     bodies_sm_to_modify += body_sm_list;
03814     bodies_sm_to_modify += neighbor_imprint_list;
03815     push_attributes_before_modify( bodies_sm_to_modify );
03816     bodies_to_modify += webcut_body_list;
03817     bodies_to_modify += neighboring_bodies;
03818     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
03819   }
03820 
03821 
03822   int count = gme->webcut(body_sm_list, tool_sm,
03823                           neighbor_imprint_list,
03824                           result_sm_list, imprint_type, preview);
03825 
03826   // finish up if we're doing the real thing
03827   if (!preview)
03828   {
03829     restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
03830     remove_pushed_attributes(result_sm_list, bodies_to_modify );
03831 
03832     ret = finish_webcut(webcut_body_list, result_sm_list, merge,
03833                           count > 0 ? CUBIT_SUCCESS : CUBIT_FAILURE,
03834                           results_list, &merged_surface_ids, &merged_curve_ids );
03835 
03836     do_attribute_cleanup();
03837   }
03838   else
03839     ret = count > 0 ? CUBIT_SUCCESS : CUBIT_FAILURE;
03840 
03841   if( preview == CUBIT_FALSE && CubitUndo::get_undo_enabled() )
03842   {
03843     if( ret == CUBIT_SUCCESS )
03844       CubitUndo::note_result_bodies( results_list );
03845     else
03846       CubitUndo::remove_last_undo();
03847   }
03848 
03849   return ret;
03850 }
03851 
03852 CubitStatus GeometryModifyTool::section(
03853                                    DLIList<Body*> &section_body_list,
03854                                    const CubitVector &point_1,
03855                                    const CubitVector &point_2,
03856                                    const CubitVector &point_3,
03857                                    DLIList<Body*> &new_body_list,
03858                                    CubitBoolean keep_normal_side,
03859                                    CubitBoolean keep_old )
03860 {
03861   if( section_body_list.size() == 0 )
03862     return CUBIT_FAILURE;
03863 
03864   if (!okay_to_modify( section_body_list, "SECTION" ))
03865     return CUBIT_FAILURE;
03866    CubitStatus rval = CUBIT_SUCCESS;
03867 
03868    const int count = section_body_list.size();
03869    DLIList<BodySM*> result_sm_list;
03870    DLIList<Body*> body_list(section_body_list);
03871    DLIList<BodySM*> engine_body_sms(count);
03872    DLIList<Body*> engine_bodies(count);
03873    GeometryModifyEngine* gme = 0;
03874 
03875    if( CubitUndo::get_undo_enabled() )
03876    {
03877      if( keep_old )
03878        CubitUndo::save_state();
03879      else
03880        CubitUndo::save_state_with_cubit_file( section_body_list );
03881    }
03882 
03883    while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
03884    {
03885       //get all the child entities that have been merged
03886       DLIList<int> merged_surface_ids;
03887       DLIList<int> merged_curve_ids;
03888       get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
03889 
03890       CubitStatus result = gme->section( engine_body_sms,
03891                                          point_1, point_2, point_3,
03892                                          result_sm_list,
03893                                          keep_normal_side, keep_old );
03894 
03895       if (!finish_sm_op( engine_bodies, result_sm_list, new_body_list ))
03896         result = CUBIT_FAILURE;
03897       if (!result)
03898         rval = CUBIT_FAILURE;
03899 
03900       if( merged_surface_ids.size() || merged_curve_ids.size() )
03901         fixup_merged_entities( merged_surface_ids, merged_curve_ids);
03902 
03903       engine_body_sms.clean_out();
03904       engine_bodies.clean_out();
03905       result_sm_list.clean_out();
03906    }
03907 
03908   if( CubitUndo::get_undo_enabled() )
03909   {
03910     if( new_body_list.size() ) //if there are new bodies...something succeeded
03911       CubitUndo::note_result_bodies( new_body_list );
03912     else
03913       CubitUndo::remove_last_undo();
03914   }
03915 
03916    return rval;
03917 }
03918 
03919 CubitStatus
03920 GeometryModifyTool::offset_curves( DLIList<RefEdge*>& ref_edge_list,
03921                                    DLIList<RefEdge*>& output_edge_list,
03922                                    double offset_distance,
03923                                    const CubitVector& offset_direction,
03924                                    int gap_type )
03925 {
03926   // Make sure all curves are from same geometry engine
03927   DLIList<TopologyEntity*> entity_list(ref_edge_list.size());
03928   DLIList<TopologyBridge*> bridge_list(ref_edge_list.size());
03929   CAST_LIST_TO_PARENT(ref_edge_list, entity_list);
03930   GeometryModifyEngine* gme_ptr = common_modify_engine(entity_list, bridge_list);
03931   if ( !gme_ptr )
03932   {
03933     PRINT_ERROR("Can't create offset curves that don't all originate from same\n"
03934       "       modeling engine.\n");
03935     return CUBIT_FAILURE;
03936   }
03937 
03938   if( CubitUndo::get_undo_enabled() )
03939     CubitUndo::save_state();
03940 
03941   DLIList<Curve*> curve_list(bridge_list.size()), result_list;
03942   CAST_LIST(bridge_list, curve_list, Curve);
03943   assert(curve_list.size() == ref_edge_list.size());
03944 
03945   CubitStatus rval = gme_ptr->offset_curves( curve_list, result_list,
03946                         offset_distance, offset_direction, gap_type );
03947   assert( rval || !result_list.size() );
03948   result_list.reset();
03949 
03950   DLIList<RefEntity*> created_edges;
03951   output_edge_list.clean_out();
03952   for (int i = result_list.size(); i--; )
03953   {
03954     RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge(result_list.get_and_step());
03955     created_edges.append( new_edge );
03956     output_edge_list.append( new_edge );
03957   }
03958 
03959   if( CubitUndo::get_undo_enabled() )
03960   {
03961     if( created_edges.size() )
03962       CubitUndo::note_result_entities( created_edges );
03963     else
03964       CubitUndo::remove_last_undo();
03965   }
03966 
03967   return rval;
03968 }
03969 
03970 // Compute the transformation requried to align my_face with target_face
03971 // with respecct to reference_body_ptr.  Then perform the transformation
03972 // on all entities in entities_to_move
03973 CubitStatus GeometryModifyTool::align_entities( RefFace *source_face,  
03974   RefFace *target_face,
03975   DLIList<RefEntity*> &entities_to_move,
03976   bool reverse,
03977   CubitVector &my_center,
03978   CubitVector &axis_of_rot,
03979   CubitVector &target_center,
03980   double &angle,
03981   bool preview)
03982 {
03983   // Initialize angle to zero, so we are passing back a valid
03984   // value if we never need to rotate the body
03985   angle = 0.0;
03986 
03987   //Align the body, which contains my_face, with the target_face.
03988 
03989   //Essentially we want to align the body at my_face with the target_face.
03990   my_center = source_face->center_point();
03991   target_center = target_face->center_point();
03992   
03993   CubitVector my_vector = source_face->normal_at( my_center );
03994   CubitVector target_vector = target_face->normal_at( target_center );
03995 
03996   if( CubitUndo::get_undo_enabled() && !preview )
03997   {
03998     DLIList<RefEntity*> free_ents_to_save;
03999     DLIList<Body*> align_list(entities_to_move.size());
04000     for ( int k=0; k<entities_to_move.size(); k++ )
04001     {
04002       RefEntity *ref_ent = entities_to_move[k];      
04003       Body *tmp_body = dynamic_cast<Body*>(ref_ent);
04004       if( tmp_body )       
04005         align_list.append( tmp_body );              
04006       else
04007         free_ents_to_save.append( ref_ent );       
04008     }     
04009     CubitUndo::save_state_with_cubit_file( align_list, &free_ents_to_save );
04010   }
04011 
04012   axis_of_rot = my_vector * target_vector;
04013 
04014   if( axis_of_rot.length() < CUBIT_RESABS )  
04015   {
04016     CubitVector v1,v2;
04017     my_vector.orthogonal_vectors(v1, v2 );
04018     axis_of_rot = v1;    
04019   }
04020 
04021   if( axis_of_rot.length() > CUBIT_RESABS )
04022   {
04023     angle = axis_of_rot.vector_angle( my_vector, target_vector );
04024 
04025     //Now we have the angle and the axis to rotate about...
04026     angle = 180.0*angle/CUBIT_PI;
04027     
04028     if( angle > 90 )
04029       angle = angle - 180;
04030 
04031     if( reverse )
04032       angle += 180;
04033   }
04034   CubitVector origin(0.,0.,0.);
04035 
04036   if (preview)
04037   {    
04038     preview_align( -my_center, target_center, angle, axis_of_rot, entities_to_move );     
04039   }
04040   else 
04041   {   
04042     //Move the body so that the center of my_face
04043     //is at the origin.   
04044     DLIList<RefEntity*> entities_transformed;
04045     GeometryQueryTool::instance()->translate( entities_to_move,
04046       -my_center.x(),
04047       -my_center.y(),
04048       -my_center.z(),
04049       false,
04050       entities_transformed);
04051 
04052     //If the axis length is zero we dont want to do a rotation,
04053     //they are already parallel..  
04054     if (axis_of_rot.length() > CUBIT_RESABS )
04055     {    
04056       //Now rotate the body about the axis.
04057       GeometryQueryTool::instance()->rotate(entities_to_move, origin, 
04058         axis_of_rot, angle, false, entities_transformed,
04059         false);
04060     }
04061     //Now move the body to the location of the target_center.    
04062     GeometryQueryTool::instance()->translate( entities_to_move,
04063       target_center.x(),
04064       target_center.y(),
04065       target_center.z(),
04066       false,
04067       entities_transformed,
04068       preview);
04069   }
04070 
04071   //That should do it.
04072   return CUBIT_SUCCESS;
04073 }
04074 
04075 CubitStatus GeometryModifyTool::align_entities( DLIList<RefEntity*> &entities_to_align,
04076                                            CubitVector &pos_to_align,
04077                                            CubitVector &pos_to_align_to,
04078                                            CubitVector &axis_origin,
04079                                            CubitVector &axis_of_rot,
04080                                            double &angle_of_rotation,
04081                                            bool preview)
04082 {
04083   //project pos_to_align to axis
04084   axis_of_rot.normalize();
04085   CubitVector tmp_vec = pos_to_align - axis_origin;  
04086   double dot_prod = tmp_vec%axis_of_rot;
04087   CubitVector int_pt1 = axis_origin + (dot_prod*axis_of_rot);
04088 
04089   //project pos_to_align_to to axis
04090   tmp_vec = pos_to_align_to - axis_origin;  
04091   dot_prod = tmp_vec%axis_of_rot;
04092   CubitVector int_pt2 = axis_origin + (dot_prod*axis_of_rot);
04093 
04094   //determine angle of rotation
04095   tmp_vec = pos_to_align - int_pt1;
04096   CubitVector tmp_vec2 = pos_to_align_to - int_pt2;
04097   angle_of_rotation = axis_of_rot.vector_angle( tmp_vec, tmp_vec2 );
04098   angle_of_rotation *= 180.0/CUBIT_PI;
04099   
04100   if( angle_of_rotation < CUBIT_RESABS )
04101   {
04102     PRINT_WARNING("Points already aligned.\n");
04103     return CUBIT_SUCCESS;
04104   }
04105 
04106   if( CubitUndo::get_undo_enabled() && !preview )
04107   {
04108     DLIList<RefEntity*> free_ents_to_save;
04109     DLIList<Body*> align_list(entities_to_align.size());
04110     for ( int k=0; k<entities_to_align.size(); k++ )
04111     {
04112       RefEntity *ref_ent = entities_to_align[k];      
04113       Body *tmp_body = dynamic_cast<Body*>(ref_ent);
04114       if( tmp_body )       
04115         align_list.append( tmp_body );              
04116       else
04117         free_ents_to_save.append( ref_ent );       
04118     }     
04119     CubitUndo::save_state_with_cubit_file( align_list, &free_ents_to_save );
04120   }
04121 
04122   CubitVector translation_vector( int_pt1 );
04123 
04124   if( preview )
04125   {    
04126     preview_align( -translation_vector, translation_vector, 
04127       angle_of_rotation, axis_of_rot, entities_to_align );     
04128   }
04129   else
04130   {
04131     //translate to origin
04132     DLIList<RefEntity*> entities_transformed;
04133     GeometryQueryTool::instance()->translate( entities_to_align,
04134       -translation_vector.x(),
04135       -translation_vector.y(),
04136       -translation_vector.z(),
04137       false,
04138       entities_transformed);
04139 
04140     //rotate to align
04141     CubitVector origin(0,0,0);
04142     GeometryQueryTool::instance()->rotate( entities_to_align, origin, axis_of_rot, angle_of_rotation, false, 
04143       entities_transformed, false );
04144 
04145     //translate back
04146     GeometryQueryTool::instance()->translate( entities_to_align,
04147       translation_vector.x(),
04148       translation_vector.y(),
04149       translation_vector.z(),
04150       false,
04151       entities_transformed);      
04152   }
04153 
04154   //That should do it.
04155   return CUBIT_SUCCESS;  
04156 }
04157 
04158 CubitStatus GeometryModifyTool::align_entities( DLIList<RefEntity*>& reference_entities,
04159                                                 DLIList<RefEntity*> &entities_to_move,
04160                                                 CubitVector align_to_vec,                                                 
04161                                                 CubitVector &my_center,                                           
04162                                                 CubitVector &axis_of_rot,
04163                                                 double &angle,                                           
04164                                                 bool preview)
04165 {
04166    DLIList<RefFace*> ref_face_list;
04167    DLIList<RefVertex*> ref_vertex_list;
04168 
04169    CAST_LIST(reference_entities, ref_face_list, RefFace);
04170    CAST_LIST(reference_entities, ref_vertex_list, RefVertex);
04171 
04172    angle = 0.0;   
04173 
04174    CubitVector translation_vector;
04175    CubitVector axis_of_rotation;
04176    CubitVector vector_to_rotate;
04177 
04178    if( ref_face_list.size() == 1 &&
04179        ref_vertex_list.size() == 0 )
04180    {   
04181      //now form the axis of rotation
04182      RefFace *my_face = ref_face_list.get_and_step();
04183      translation_vector = my_face->center_point();     
04184      my_center = translation_vector;
04185      vector_to_rotate = my_face->normal_at( translation_vector );     
04186      axis_of_rot = align_to_vec * vector_to_rotate;
04187    }
04188    else if( ref_face_list.size() == 0 &&
04189             ref_vertex_list.size() == 2 )
04190    {
04191      RefVertex *vertex_1 = ref_vertex_list.get_and_step();
04192      RefVertex *vertex_2 = ref_vertex_list.get_and_step();     
04193 
04194      //now form the axis of rotation
04195      translation_vector = vertex_1->coordinates();
04196      my_center = vertex_1->coordinates();     
04197      vector_to_rotate = vertex_2->coordinates() - vertex_1->coordinates();     
04198      axis_of_rot = align_to_vec * vector_to_rotate;
04199    }   
04200 
04201    if( axis_of_rot.length() < CUBIT_RESABS )  
04202    {
04203     double dot_prod = align_to_vec%vector_to_rotate;
04204     //normals could be 180 degrees from one another
04205     if( dot_prod < 0 ) 
04206     {
04207       CubitVector v1,v2;
04208       align_to_vec.orthogonal_vectors(v1, v2 );
04209       axis_of_rot = v1;
04210     }
04211   }
04212 
04213    if( CubitUndo::get_undo_enabled() && !preview )
04214    {
04215      DLIList<RefEntity*> free_ents_to_save;
04216      DLIList<Body*> align_list(entities_to_move.size());
04217      for ( int k=0; k<entities_to_move.size(); k++ )
04218      {
04219        RefEntity *ref_ent = entities_to_move[k];      
04220        Body *tmp_body = dynamic_cast<Body*>(ref_ent);
04221        if( tmp_body )       
04222          align_list.append( tmp_body );              
04223        else
04224          free_ents_to_save.append( ref_ent );       
04225      }     
04226      CubitUndo::save_state_with_cubit_file( align_list, &free_ents_to_save );
04227    }
04228 
04229    //determine the angle of rotation   
04230    angle = axis_of_rot.vector_angle( vector_to_rotate, align_to_vec );
04231    angle = 180.0*angle/CUBIT_PI;
04232 
04233    if( preview )
04234    {
04235      preview_align( -translation_vector, translation_vector, 
04236                   angle, axis_of_rot, entities_to_move );     
04237    }
04238    else
04239    {
04240      //translate to origin
04241      DLIList<RefEntity*> entities_transformed;
04242      GeometryQueryTool::instance()->translate( entities_to_move,
04243        -translation_vector.x(),
04244        -translation_vector.y(),
04245        -translation_vector.z(),
04246        false,
04247        entities_transformed);
04248 
04249      //rotate to align
04250      CubitVector origin(0,0,0);
04251      GeometryQueryTool::instance()->rotate( entities_to_move, origin, axis_of_rot, angle, false, 
04252        entities_transformed, false );
04253 
04254      //translate back
04255      GeometryQueryTool::instance()->translate( entities_to_move,
04256        translation_vector.x(),
04257        translation_vector.y(),
04258        translation_vector.z(),
04259        false,
04260        entities_transformed);      
04261    }
04262 
04263    //That should do it.
04264    return CUBIT_SUCCESS;  
04265 }
04266 
04267 void GeometryModifyTool::preview_align( CubitVector translation_to_origin,
04268                                         CubitVector origin_to_target,
04269                                         double angle_of_rotation,
04270                                         CubitVector axis_of_rotation,
04271                                         DLIList<RefEntity*> &entities )
04272 {
04273   CubitTransformMatrix prev_xform;
04274   prev_xform.translate(translation_to_origin);
04275 
04276   CubitTransformMatrix rot_mat;
04277   rot_mat.rotate( angle_of_rotation, axis_of_rotation );
04278 
04279   CubitTransformMatrix mov_mat;
04280   mov_mat.translate( origin_to_target );
04281 
04282   for( int k=0; k<entities.size(); k++ )
04283   {
04284     RefEntity *tmp_ent = entities[k];           
04285     TopologyEntity *te = dynamic_cast<TopologyEntity*>(tmp_ent);
04286     if( NULL == te )
04287       continue;
04288 
04289     DLIList<RefEdge*> edges;
04290     te->ref_edges(edges);      
04291     for (int i = 0; i < edges.size(); i++)
04292     {
04293       GMem poly;
04294       if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
04295       {
04296         poly.transform(prev_xform);
04297         poly.transform(rot_mat);
04298         poly.transform(mov_mat);
04299         GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
04300       }
04301       else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
04302       {
04303         CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
04304         tmp_pt = prev_xform*tmp_pt;
04305         tmp_pt = rot_mat*tmp_pt;
04306         tmp_pt = mov_mat*tmp_pt;       
04307         GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
04308       }
04309     }
04310   }
04311 }
04312 
04313 
04314 
04315 CubitStatus GeometryModifyTool::sweep_setup(
04316                          const char* name,
04317                          DLIList<RefEntity*>& input_entity_list,
04318                          DLIList<Body*>& output_body_list,
04319                          GeometryModifyEngine*& output_engine,
04320                          CubitBoolean& changed_new_ids,
04321                          DLIList<GeometryEntity*>& output_geom_list,
04322                          bool keep_old,
04323                          DLIList<RefEdge*>* input_edge_list,
04324                          DLIList<Curve*>* output_curve_list )
04325 {
04326   int i;
04327 
04328   if (input_entity_list.size() == 0)
04329     return CUBIT_FAILURE;
04330 
04331   DLIList<RefFace*> ref_face_list;
04332   DLIList<RefEdge*> ref_edge_list;
04333   CAST_LIST( input_entity_list, ref_face_list, RefFace );
04334   CAST_LIST( input_entity_list, ref_edge_list, RefEdge );
04335   if( ref_face_list.size() && ref_edge_list.size() )
04336   {
04337     PRINT_ERROR( "Currently cannot sweep curves and surfaces at the same time\n" );
04338     return CUBIT_FAILURE;
04339   }
04340 
04341   if( (ref_face_list.size()+ref_edge_list.size()) != input_entity_list.size() )
04342   {
04343     PRINT_ERROR( "Can only sweep surfaces or curves\n" );
04344     return CUBIT_FAILURE;
04345   }
04346 
04347   // Currently faces to be swept have to belong to different bodies.  It
04348   // doesn't work well to sweep multiple faces from the same body (also
04349   // current implementation in AGE crashes).
04350   if( ref_face_list.size() && false == keep_old )
04351   {
04352     int free_surf_cnt = 0; // Number of free surfaces being swept
04353     DLIList<Body*> body_list;
04354     RefFace *ref_face_ptr;
04355     for( i=ref_face_list.size(); i--; )
04356     {
04357       ref_face_ptr = ref_face_list.get_and_step();
04358       DLIList<Body*> tmp_body_list;
04359       ref_face_ptr->bodies( tmp_body_list );
04360       if( tmp_body_list.size() > 1 )
04361       {
04362         PRINT_ERROR( "Surface %d belongs to more than one volume; cannot sweep.\n",
04363           ref_face_ptr->id() );
04364         return CUBIT_FAILURE;
04365       }
04366 
04367       if( tmp_body_list.size() > 0 )
04368         body_list.append_unique( tmp_body_list.get() );
04369       else
04370         free_surf_cnt++;
04371     }
04372 
04373     if( body_list.size()+free_surf_cnt != ref_face_list.size() )
04374     {
04375       //if each is a sheet body, and every surface is in the list,
04376       //it is ok to sweep it
04377 
04378       //PRINT_ERROR("The surfaces to be swept cannot belong to the same volume\n");
04379       //return CUBIT_FAILURE;
04380 
04381       for( int k=body_list.size(); k--; )
04382       {
04383         Body *tmp_body = body_list.get_and_step();
04384         DLIList<RefFace*> tmp_ref_faces;
04385         tmp_body->ref_faces( tmp_ref_faces );
04386 
04387         //all surfaces must be swept
04388         if( tmp_body->is_sheet_body() )
04389         {
04390           tmp_ref_faces -= ref_face_list;
04391           if( tmp_ref_faces.size() )
04392           {
04393             PRINT_ERROR( "When sweeping a sheet body, all surfaces must be specified\n");
04394             return CUBIT_FAILURE;
04395           }
04396         }
04397         else // only 1 surface can be swept
04398         {
04399           int num_surfaces_before = tmp_ref_faces.size();
04400           tmp_ref_faces -= ref_face_list;
04401 
04402           if( (num_surfaces_before - tmp_ref_faces.size() ) > 1 )
04403           {
04404             PRINT_ERROR( "The surfaces to be swept cannot belong to the same volume\n" );
04405             return CUBIT_FAILURE;
04406           }
04407         }
04408       }
04409     }
04410 
04411     output_body_list = body_list;
04412   }
04413 
04414   // Make sure all entities are from same modify engine
04415   DLIList<TopologyEntity*> te_list;
04416   CAST_LIST(input_entity_list, te_list, TopologyEntity);
04417 
04418   // This is for sweeping along a curve list
04419   if (input_edge_list)
04420   {
04421     input_edge_list->reset();
04422     for( i=input_edge_list->size(); i--; )
04423       te_list.append( input_edge_list->get_and_step() );
04424   }
04425 
04426   DLIList<TopologyBridge*> bridge_list( te_list.size() );
04427   output_engine = common_modify_engine( te_list, bridge_list );
04428   if( output_engine == NULL )
04429   {
04430      PRINT_ERROR("Can't sweep with entities from different modeling engines.\n");
04431      return CUBIT_FAILURE;
04432   }
04433 
04434   // Check for virtual anywhere in participating bodies.  This will catch cases where
04435   // the result from sweeping would interact with some virtual somewhere. bwc 12/22/05.
04436   for(i=output_body_list.size(); i--;)
04437   {
04438      if(GeometryQueryTool::instance()->contains_intermediate_geometry(
04439         output_body_list.get_and_step()))
04440      {
04441         PRINT_ERROR("Can't sweep faces of bodies containing virtual geometry.\n");
04442         return CUBIT_FAILURE;
04443      }
04444   }
04445 
04446   changed_new_ids = CUBIT_FALSE;
04447 
04448   TopologyBridge* bridge_ptr;
04449   bridge_list.reset();
04450   for( i=input_entity_list.size(); i--; )
04451   {
04452     bridge_ptr = bridge_list.get_and_step();
04453     GeometryEntity* geom_ptr = dynamic_cast<GeometryEntity*>(bridge_ptr);
04454     output_geom_list.append(geom_ptr);
04455   }
04456 
04457   if( input_edge_list )
04458   {
04459     for( i=input_edge_list->size(); i--; )
04460     {
04461       bridge_ptr = bridge_list.get_and_step();
04462       Curve* curve_ptr = dynamic_cast<Curve*>(bridge_ptr);
04463       output_curve_list->append(curve_ptr);
04464     }
04465   }
04466 
04467   return CUBIT_SUCCESS;
04468 }
04469 
04470 CubitStatus GeometryModifyTool::sweep_finish(
04471                                      const char* const,
04472                                      DLIList<Body*>& input_body_list,
04473                                      DLIList<BodySM*>& new_body_list,
04474                                      DLIList<Body*>& output_body_list,
04475                                      CubitBoolean changed_new_ids )
04476 {
04477   int i;
04478   DLIList<BodySM*> regen_list( new_body_list );
04479   GeometryQueryTool *gqt = GeometryQueryTool::instance();
04480 
04481   input_body_list.reset();
04482   for (i = input_body_list.size(); i--; )
04483   {
04484     Body* body = input_body_list.get_and_step();
04485     BodySM* bodysm = body->get_body_sm_ptr();
04486     if (bodysm)
04487     {
04488       regen_list.append_unique(bodysm);
04489       remove_dead_entity_names(body);
04490       output_body_list.append( body );
04491     }
04492     else
04493     {
04494       gqt->destroy_dead_entity(body);
04495     }
04496   }
04497   gqt->cleanout_deactivated_geometry();
04498 
04499   regen_list.reset();
04500   for (i = regen_list.size(); i--; )
04501   {
04502     BodySM* bodysm = regen_list.get_and_step();
04503     Body* body = gqt->make_Body(bodysm);
04504     output_body_list.append_unique( body );
04505     PRINT_INFO("%s volume %d\n",
04506       new_body_list.is_in_list(bodysm) ? "Created swept" : "Updated",
04507       body->ref_volume()->id());
04508   }
04509 
04510   if (changed_new_ids) set_new_ids(CUBIT_FALSE);
04511   gqt->cleanout_deactivated_geometry();
04512 
04513   return CUBIT_SUCCESS;
04514 }
04515 
04516 
04517 
04518 
04519 
04520 CubitStatus GeometryModifyTool::sweep_rotational(
04521                                         DLIList<RefEntity*>& ref_ent_list,
04522                                         const CubitVector& point,
04523                                         const CubitVector& sweep_axis,
04524                                         double angle,
04525                                         DLIList<Body*>& output_body_list,
04526                                         CubitBoolean anchor_entity,
04527                                         CubitBoolean keep_old,
04528                                         int steps,
04529                                         double draft_angle,
04530                                         int draft_type,
04531                                         CubitBoolean switchside,
04532                                         CubitBoolean make_solid,
04533                                         CubitBoolean rigid)
04534 {
04535   DLIList<Body*> body_list;
04536   DLIList<GeometryEntity*> geom_list;
04537   GeometryModifyEngine* gePtr1 = 0;
04538   CubitBoolean change_newids;
04539   if (!sweep_setup("rotational", ref_ent_list, body_list, gePtr1,
04540                    change_newids, geom_list, keep_old))
04541     return CUBIT_FAILURE;
04542 
04543   if( CubitUndo::get_undo_enabled())
04544   {
04545     DLIList<RefEdge*> edge_list;
04546     DLIList<RefFace*> face_list;
04547 
04548     CAST_LIST( ref_ent_list, edge_list, RefEdge );
04549     CAST_LIST( ref_ent_list, face_list, RefFace );
04550 
04551     DLIList<RefEdge*> free_edges;
04552     for(int i=0;i<edge_list.size();i++)
04553     {
04554       RefEdge* edge= edge_list[i];
04555       if(edge->num_parent_ref_entities()==0)
04556       {
04557         free_edges.append(edge);
04558       }
04559     }
04560 
04561     if(free_edges.size())
04562       CubitUndo::save_state_with_cubit_file( free_edges );
04563     else if( edge_list.size() || keep_old )
04564       CubitUndo::save_state();
04565     else
04566      //Faces will get consumed so you have to save out original entities
04567       CubitUndo::save_state_with_cubit_file( face_list );
04568   }
04569 
04570   DLIList<BodySM*> result_list;
04571   CubitStatus status = gePtr1->sweep_rotational( geom_list,
04572                                                  result_list,
04573                                                  point,
04574                                                  sweep_axis,
04575                                                  angle,
04576                                                  steps,
04577                                                  draft_angle,
04578                                                  draft_type,
04579                                                  switchside,
04580                                                  make_solid,
04581                                                  rigid,
04582                                                  anchor_entity,
04583                                                  keep_old );
04584 
04585   if( keep_old )
04586     body_list.clean_out();
04587 
04588   if (!sweep_finish("rotational", body_list, result_list, output_body_list, change_newids))
04589     status = CUBIT_FAILURE;
04590 
04591   if( CubitUndo::get_undo_enabled())
04592   {
04593     if( status == CUBIT_FAILURE )
04594       CubitUndo::remove_last_undo();
04595     else
04596       CubitUndo::note_result_bodies( output_body_list );
04597   }
04598 
04599   return status;
04600 }
04601 
04602 
04603 CubitStatus GeometryModifyTool::sweep_helical( DLIList<RefEntity*>& ref_ent_list,
04604                                                CubitVector &location,
04605                                                CubitVector &direction,
04606                                                double &thread_distance,
04607                                                double &angle,
04608                                                bool right_handed,
04609                                                CubitBoolean anchor_entity,
04610                                                CubitBoolean keep_old,
04611                                                DLIList<Body*>& output_body_list)
04612 {
04613   DLIList<Body*> body_list;
04614   DLIList<GeometryEntity*> geom_list;
04615   GeometryModifyEngine* gePtr1 = 0;
04616   CubitBoolean change_newids;
04617   if (!sweep_setup("translational", ref_ent_list, body_list, gePtr1,
04618                    change_newids, geom_list, keep_old))
04619     return CUBIT_FAILURE;
04620 
04621   if( CubitUndo::get_undo_enabled())
04622   {
04623     DLIList<RefEdge*> edge_list;
04624     DLIList<RefFace*> face_list;
04625 
04626     CAST_LIST( ref_ent_list, edge_list, RefEdge );
04627     CAST_LIST( ref_ent_list, face_list, RefFace );
04628 
04629     //Edges aren't consumed, so there's nothing to save out
04630     if( edge_list.size() || keep_old )
04631       CubitUndo::save_state();
04632     else
04633      //Faces will get consumed so you have to save out original entities
04634       CubitUndo::save_state_with_cubit_file( face_list );
04635   }
04636 
04637   DLIList<BodySM*> result_list;
04638   CubitStatus status = gePtr1->
04639     sweep_helical( geom_list, result_list, location,
04640                    direction, thread_distance, angle, right_handed, anchor_entity, keep_old );
04641 
04642   if( keep_old )
04643     body_list.clean_out();
04644 
04645   if (!sweep_finish("translational", body_list, result_list, output_body_list, change_newids))
04646     status = CUBIT_FAILURE;
04647 
04648   if( CubitUndo::get_undo_enabled())
04649   {
04650     if( status == CUBIT_FAILURE )
04651       CubitUndo::remove_last_undo();
04652     else
04653       CubitUndo::note_result_bodies( output_body_list );
04654   }
04655 
04656   return status;
04657 
04658 
04659 
04660 
04661 
04662 }
04663 
04664 CubitStatus GeometryModifyTool::sweep_translational(
04665                                          DLIList<RefEntity*>& ref_ent_list,
04666                                          const CubitVector& sweep_vector,
04667                                          double draft_angle,
04668                                          int draft_type,
04669                                          CubitBoolean switchside,
04670                                          CubitBoolean rigid,
04671                                          CubitBoolean anchor_entity,
04672                                          CubitBoolean keep_old,
04673                                          DLIList<Body*>& output_body_list)
04674 {
04675   DLIList<Body*> body_list;
04676   DLIList<GeometryEntity*> geom_list;
04677   GeometryModifyEngine* gePtr1 = 0;
04678   CubitBoolean change_newids;
04679   if (!sweep_setup("translational", ref_ent_list, body_list, gePtr1,
04680                    change_newids, geom_list, keep_old))
04681     return CUBIT_FAILURE;
04682 
04683   if( CubitUndo::get_undo_enabled())
04684   {
04685     DLIList<RefEdge*> edge_list;
04686     DLIList<RefFace*> face_list;
04687 
04688     CAST_LIST( ref_ent_list, edge_list, RefEdge );
04689     CAST_LIST( ref_ent_list, face_list, RefFace );
04690 
04691     //find any free edges
04692     DLIList<RefEdge*> free_edges;
04693     for( int k=edge_list.size(); k--; )
04694     {
04695       RefEdge *tmp_edge = edge_list.get_and_step();
04696       if( tmp_edge->num_parent_ref_entities() == 0 )
04697         free_edges.append( tmp_edge );
04698     }    
04699 
04700     if( free_edges.size() ) 
04701       //Free edges will get consumed..save them out 
04702       CubitUndo::save_state_with_cubit_file( free_edges );
04703     else if( edge_list.size() || keep_old )
04704       CubitUndo::save_state();
04705     else
04706      //Faces will get consumed so you have to save out original entities
04707       CubitUndo::save_state_with_cubit_file( face_list );
04708   }
04709 
04710   DLIList<BodySM*> result_list;
04711   CubitStatus status = gePtr1->
04712     sweep_translational( geom_list,
04713                          result_list,
04714                          sweep_vector,
04715                          draft_angle,
04716                          draft_type,
04717                          switchside,
04718                          rigid,
04719                          anchor_entity,
04720                          keep_old);
04721 
04722   if( keep_old )
04723     body_list.clean_out();
04724 
04725   if (!sweep_finish("translational", body_list, result_list, output_body_list, change_newids))
04726     status = CUBIT_FAILURE;
04727 
04728   if( CubitUndo::get_undo_enabled())
04729   {
04730     if( status == CUBIT_FAILURE )
04731       CubitUndo::remove_last_undo();
04732     else
04733       CubitUndo::note_result_bodies( output_body_list );
04734   }
04735 
04736   return status;
04737 }
04738 
04739 //Author:: Jonathan Bugman
04740 //Sept 10, 2006
04741 CubitStatus GeometryModifyTool::sweep_curve_target(CubitPlane ref_plane,
04742                                              DLIList<RefEntity*>& ref_ent_list)
04743 {
04744     double distance1;
04745     double distance2;
04746     double distance3;
04747     double temp_counter=0;
04748     CubitVector begin_point;
04749     CubitVector target_begin_point;
04750     CubitVector get_mid_point;
04751     CubitVector target_mid_point;
04752     CubitVector end_point;
04753     CubitVector target_end_point;
04754     DLIList<RefEdge*> edge_list;
04755     CAST_LIST(ref_ent_list, edge_list, RefEdge);
04756     CubitVector result;
04757     double max_distance_for_edge=0;
04758     CubitVector max_result;
04759     //make sure that there are actually edges in list
04760     if(edge_list.size() > 0)
04761     {
04762         //this part of the code steps through all edges that could be
04763         //selected by user and finds the largest distance of all edges from three
04764         //points: midpoint, endpoint, and beginpoint
04765         for (int i=0;i<edge_list.size();i++)
04766         {
04767             //find the midpoint vector of the edge
04768             edge_list[i]->mid_point(get_mid_point);
04769 
04770             //Project the midpoint onto the specified plane
04771             target_mid_point = ref_plane.project(get_mid_point);
04772 
04773             //Calculate the distance between the mid_point, and target_point
04774             distance1 = target_mid_point.distance_between(get_mid_point);
04775 
04776             //the next two blocks are just copies of the above three steps
04777             double fraction_along_curve = 1;
04778             edge_list[i]->position_from_fraction(fraction_along_curve, end_point);
04779             target_end_point = ref_plane.project(end_point);
04780             distance2 = target_end_point.distance_between(end_point);
04781 
04782             fraction_along_curve = 0;
04783             edge_list[i]->position_from_fraction(fraction_along_curve, begin_point);
04784             target_begin_point = ref_plane.project(begin_point);
04785             distance3 = target_begin_point.distance_between(begin_point);
04786 
04787             //see which of the three distances is greater for that edge
04788             //and compare its distance to the other edges that have already been calculated
04789             //saving the vector of the largest distance
04790             if (distance1>distance2 && distance1>distance3)
04791             {
04792                 result = 2*(target_mid_point - get_mid_point);
04793                 max_distance_for_edge=distance1;
04794                 if (max_distance_for_edge>temp_counter)
04795                 {
04796                     temp_counter=max_distance_for_edge;
04797                     max_result=result;
04798                 }
04799             }
04800             else if (distance2>distance3)
04801             {
04802                 result = 2*(target_end_point - end_point);
04803                 max_distance_for_edge=distance2;
04804                 if (max_distance_for_edge>temp_counter)
04805                 {
04806                     temp_counter=max_distance_for_edge;
04807                     max_result=result;
04808                 }
04809             }
04810             else
04811             {
04812                 result = 2*(target_begin_point - begin_point);
04813                 max_distance_for_edge=distance3;
04814                 if (max_distance_for_edge>temp_counter)
04815                 {
04816                     temp_counter=max_distance_for_edge;
04817                     max_result=result;
04818                 }
04819             }
04820         }
04821 
04822         //using the 'facet edges' defined by the drawing geometry take the leading
04823         //and trailing edge projection vectors of this small edge.  With that,
04824         //calc the dot product and if negative, the vectors are opposite of each
04825         //other meaning the curve travels through the plane and the sweep function will fail
04826         for (int ii=0;ii<edge_list.size();ii++)
04827         {
04828             Curve *facet_curve;
04829             facet_curve=edge_list[ii]->get_curve_ptr();
04830             CubitStatus response;
04831             GMem g_mem;
04832 
04833             //get number of points and their locations
04834             //on the curve as defined by the drawing geometry algorithm
04835             response = facet_curve->get_geometry_query_engine()->
04836                 get_graphics( facet_curve, &g_mem );
04837             int num_points = g_mem.pointListCount;
04838 
04839             if (response==CUBIT_FAILURE || num_points == 0)
04840             {
04841                 PRINT_WARNING("Facet Curve calling function failed\n" );
04842             }
04843 
04844             GPoint *point_data = g_mem.point_list();
04845 
04846             for (int jj=0; jj < (num_points-1); jj++)
04847             {
04848                 //get first points vectors
04849                 CubitVector point_1;
04850                 point_1.x(point_data[jj].x);
04851                 point_1.y(point_data[jj].y);
04852                 point_1.z(point_data[jj].z);
04853                 //get second points vectors
04854                 CubitVector point_2;
04855                 point_2.x(point_data[jj+1].x);
04856                 point_2.y(point_data[jj+1].y);
04857                 point_2.z(point_data[jj+1].z);
04858                 //project the two points onto target plane
04859                 CubitVector target_point_1;
04860                 target_point_1 = ref_plane.project(point_1);
04861                 CubitVector target_point_2;
04862                 target_point_2 = ref_plane.project(point_2);
04863                 //calc vector from point on curve to point on surface
04864                 CubitVector vec_1 = point_1 - target_point_1;
04865                 CubitVector vec_2 = point_2 - target_point_2;
04866                 //make them unit vectors
04867                 vec_1.normalize();
04868                 vec_2.normalize();
04869                 //calculate dot product
04870                 double dot = vec_1.x()*vec_2.x()+vec_1.y()*vec_2.y()+vec_1.z()*vec_2.z();
04871                 //check to see if dot product sign is zero
04872                 //the and statement checks for if the first or last vertex of the edge
04873                 //which may be sitting on the surface, this is alright
04874                 //and should still be able to sweep
04875 //              if (dot<0 && (jj+1!=num_points || jj==0))
04876                 if (dot<0 && (jj!=(num_points-2) || jj==0))
04877                 {
04878                     PRINT_ERROR( "The edge is traveling through the plane\n" );
04879                     PRINT_ERROR( "and thus forces the sweep direction to switch\n" );
04880                     PRINT_ERROR( "direction. Try splitting the edge.\n" );
04881                     return CUBIT_FAILURE;
04882                 }
04883             }
04884         }
04885         DLIList<BodySM*> webcut_results_list;
04886         DLIList<Body*> body_list;
04887         DLIList<BodySM*> sweep_result_list;
04888         DLIList<GeometryEntity*> geom_list;
04889         GeometryModifyEngine* gePtr1 = 0;
04890         CubitBoolean change_newids;
04891 
04892         if (!sweep_setup("translational", ref_ent_list , body_list, gePtr1,
04893             change_newids, geom_list, false))
04894             return CUBIT_FAILURE;
04895 
04896         //below block is default settings to be fed into sweep_translational
04897         CubitBoolean rigid = CUBIT_FALSE;
04898         CubitBoolean switchside = CUBIT_FALSE;
04899         int draft_type = 0;
04900         double draft_angle=0.0;
04901 
04902         //sweep the curve through and hopefully past the target surface
04903         CubitStatus status = gePtr1->sweep_translational( geom_list,sweep_result_list,
04904             max_result,draft_angle, draft_type,switchside,rigid);
04905 
04906         if (status == 0)
04907         {
04908             PRINT_ERROR( "Sweep operation failed!\n" );
04909             //delete sweep_result_list memory
04910             gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
04911             return CUBIT_FAILURE;
04912         }
04913 
04914         //below lines are used to define the ref_plane with three points for webcut input
04915         //find normal vector to user specified plane
04916         CubitVector vec1 = ref_plane.normal();
04917         CubitVector vec2;
04918         CubitVector vec3;
04919         //get orthogonal vectors of the normal vector
04920         vec1.orthogonal_vectors(vec2, vec3);
04921         //place the orthogonal vectors at a point on the plane as opposed to the origin
04922         vec2=vec2+target_mid_point;
04923         vec3=vec3+target_mid_point;
04924 
04925                 DLIList<BodySM*> neighbor_imprint_list;
04926         //do a webcut with a plane created from the three projected points above
04927         CubitStatus status2 = gePtr1->webcut(sweep_result_list,target_mid_point,
04928             vec2,vec3, neighbor_imprint_list, webcut_results_list);
04929 
04930         if (status2 == 0)
04931         {
04932             PRINT_ERROR( "Sweep operation worked; however, webcut operation failed.\n" );
04933             //delete memory since it failed
04934             gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
04935             return CUBIT_FAILURE;
04936         }
04937 
04938         if (webcut_results_list.size()==0)
04939         {
04940             PRINT_ERROR( "Number of bodies from webcut is zero, unable to perform rest of sweep operation\n" );
04941             //delete memory since it failed
04942             gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
04943             return CUBIT_FAILURE;
04944         }
04945 
04946         CubitVector created_curve_mid;
04947         CubitVector user_mid;
04948         DLIList<BodySM*> keep_bodies_list;
04949         DLIList<Curve*> curve_list;
04950 
04951         //generate a list of curves from the webcut_results_list
04952         for (int counter = 0;counter < webcut_results_list.size(); counter++)
04953         {
04954             BodySM* OO = webcut_results_list[counter];
04955             OO->curves(curve_list);
04956         }
04957 
04958         //step through each of the user specified edges
04959         for (int edge_counter = 0; edge_counter < edge_list.size(); edge_counter++)
04960         {
04961             //find the midpoint of a user specified edge
04962             edge_list[edge_counter]->position_from_fraction(.5,user_mid);
04963             double min_dist=DBL_MAX;
04964             double distance;
04965             Curve* closest_curve=0;
04966 
04967             //step through all of the curves
04968             for (int counter2 = 0; counter2 < curve_list.size(); counter2++)
04969             {
04970                 //find the midpoint of the created curve
04971                 curve_list[counter2]->position_from_fraction(.5,created_curve_mid);
04972                 //calculate the distance between the two midpoints
04973                 distance=created_curve_mid.distance_between(user_mid);
04974 
04975                 //find the minimum distance between all the curves
04976                 if (distance<min_dist)
04977                 {
04978                     //reset the min_distance
04979                     min_dist=distance;
04980                     //keep track of which curve is associated with the shortest distance
04981                     closest_curve=curve_list[counter2];
04982                 }
04983             }
04984             //find the parent body of the minimum distance curve
04985             BodySM* body_sm = closest_curve->bodysm();
04986             //append that body to a keep list
04987             keep_bodies_list.append(body_sm);
04988         }
04989         //delete bodies which repeat (useful only when in granite engine)
04990     keep_bodies_list.uniquify_ordered();
04991         //subtract the keep_list from the webcut_results_list
04992         webcut_results_list -=keep_bodies_list;
04993         //delete webcut_results_list memory
04994         gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
04995 
04996                 if( CubitUndo::get_undo_enabled() )
04997                   CubitUndo::save_state();
04998 
04999         //builds ref bodies
05000     DLIList<Body*> output_body_list;
05001         if (!sweep_finish("translational", body_list, keep_bodies_list, output_body_list, change_newids))
05002         {
05003             gePtr1->get_gqe()->delete_solid_model_entities(keep_bodies_list);
05004             status = CUBIT_FAILURE;
05005         }
05006 
05007     if( CubitUndo::get_undo_enabled())
05008     {
05009       if( status == CUBIT_FAILURE )
05010         CubitUndo::remove_last_undo();
05011       else
05012         CubitUndo::note_result_bodies( output_body_list );
05013     }
05014     }
05015     else
05016     {
05017         PRINT_ERROR( "No edge(s) found - sweep creation failed.\n" );
05018         return CUBIT_FAILURE;
05019     }
05020 
05021     return CUBIT_SUCCESS;
05022 }
05023 // Author: Derek Quam
05024 // Dec. 1, 2008
05025 CubitStatus GeometryModifyTool::sweep_surface_target(RefFace *face,
05026                                                      Body *target_body,
05027                                                      CubitVector distance,
05028                                                      CubitPlane stop_plane,
05029                                                      double magnitude)
05030 {
05031   //  Declare local variables
05032   Surface *source_surf;
05033   bool set_dist = true, set_plane = true, set_mag = true;
05034   CubitVector direction;
05035   CubitStatus status;
05036   DLIList<Body*> body_list;
05037   DLIList<GeometryEntity*> geom_list;
05038   GeometryModifyEngine* gePtr1 = 0;
05039   CubitBoolean change_newids;
05040   DLIList<RefEntity*> ref_ent_list;
05041   ref_ent_list.append(face);
05042 
05043   // Check to make sure the target body is a solid
05044   if (target_body->is_sheet_body())
05045   {
05046     PRINT_ERROR("Target body must be a solid body.\n");
05047     return CUBIT_FAILURE;
05048   }
05049 
05050   // Set up the sweep
05051   if (!sweep_setup("target", ref_ent_list, body_list, gePtr1,
05052                     change_newids, geom_list, false))
05053     return CUBIT_FAILURE;
05054 
05055   // Get the Surface * from the RefFace *
05056   source_surf = face->get_surface_ptr();
05057 
05058   // Check if the direction vector and stop plane were specified
05059   if (distance.length() < 0.0001)
05060     set_dist = false;
05061   if (stop_plane.normal().length() < 0.0001)
05062     set_plane = false;
05063   if (magnitude < 0.0001)
05064     set_mag = false;
05065 
05066   // Calculate the direction of the sweep
05067   if (!set_dist)
05068     direction = face->normal_at(face->center_point());
05069   else
05070     direction = distance;
05071   direction.normalize();
05072 
05073   double length = 0.0;
05074   if (!set_mag && !set_plane)
05075   {
05076     CubitVector center_body = target_body->center_point();
05077     CubitVector center_face = face->center_point();
05078     length = center_face.distance_between(center_body);
05079   }
05080   else if (set_plane)
05081   {
05082     length = stop_plane.intersect(face->center_point(), direction).distance_between(face->center_point());
05083   }
05084   else
05085   {
05086     length = magnitude;
05087   }
05088   if (set_mag && length > magnitude)
05089     length = magnitude;
05090   direction *= length;
05091 
05092   DLIList<BodySM*> new_bodies;
05093   status = gePtr1->sweep_to_body(source_surf, target_body->get_body_sm_ptr(), direction, new_bodies );
05094 
05095   if (status != CUBIT_SUCCESS)
05096     return status;
05097 
05098   if( CubitUndo::get_undo_enabled() )
05099     CubitUndo::save_state();
05100 
05101   // Make all the new bodies
05102   DLIList<Body*> output_body_list;
05103   if (!sweep_finish("target", body_list, new_bodies, output_body_list, change_newids))
05104     status = CUBIT_FAILURE;
05105 
05106   if( CubitUndo::get_undo_enabled())
05107     {
05108       if( status == CUBIT_FAILURE )
05109         CubitUndo::remove_last_undo();
05110       else
05111       {
05112         //For some reason the ouput_body_list contains one of the original
05113         //volumes that we do not want to delete when we are performing an 
05114         //undo on the sweep. So we remove that original volume from the 
05115         //"to undo" list.
05116         Body* to_delete = output_body_list[1];
05117         output_body_list.clean_out();
05118         output_body_list.append(to_delete);
05119         CubitUndo::note_result_bodies( output_body_list );
05120       }
05121     }
05122 
05123   /*
05124   for (int i = 0; i < new_bodies.size(); i++)
05125     GeometryQueryTool::instance()->make_Body(new_bodies.get_and_step());
05126     */
05127 
05128 
05129   return CUBIT_SUCCESS;
05130 }
05131 
05132 // Author: Andrew Rout and Derek Quam
05133 // Nov. 14, 2008
05134 CubitStatus GeometryModifyTool::sweep_curve_target(DLIList<RefEdge*>& edge_list,
05135                                                    Body *target_body,
05136                                                    DLIList<Body*> &out_bodies,
05137                                                    CubitVector distance,
05138                                                    CubitPlane stop_plane,
05139                                                    bool unite)
05140 {
05141   DLIList<BodySM*> new_bodies;
05142   DLIList<Curve*> curve_list;
05143   bool set_dist = true, set_plane = true;
05144   double larDist = 1.0;
05145   CubitVector dir = distance;
05146   CubitStatus status;
05147 
05148   // Check to make sure the target body is a sheetbody
05149   if (!target_body->is_sheet_body())
05150   {
05151     PRINT_ERROR("Target body must be a sheet body.\n");
05152     return CUBIT_FAILURE;
05153   }
05154 
05155   // Get the Curve *'s from the RefEdge *'s
05156   for (int i = 0; i < edge_list.size(); i++)
05157   {
05158     edge_list[i]->get_curve_ptr()->set_saved_id(edge_list[i]->id());
05159     curve_list.append(edge_list[i]->get_curve_ptr());
05160   }
05161   // Check if the direction vector and stop plane were specified
05162   if (distance.length() < 0.0001)
05163     set_dist = false;
05164   if (stop_plane.normal().length() < 0.0001)
05165     set_plane = false;
05166 
05167   // Check inputs
05168   if (!set_plane && !set_dist)
05169   {
05170     PRINT_ERROR("User must specify a stop plane, a direction, or both.\n");
05171     return CUBIT_FAILURE;
05172   }
05173 
05174   // Calculate the direction vector
05175   double begDist, midDist, endDist;
05176   for (int i = 0; i < edge_list.size(); i++)
05177   {
05178     CubitVector beg, mid, end, begP, midP, endP;
05179     RefEdge *temp = edge_list.get_and_step();
05180 
05181     // Retrieve the beginning, middle, and end coordinates of the edge
05182     beg = temp->start_coordinates();
05183     temp->mid_point(mid);
05184     end = temp->end_coordinates();
05185 
05186     if (set_plane)
05187     {
05188       // Project the start, mid, and end point onto the stop plane
05189       begP = stop_plane.project(beg);
05190       midP = stop_plane.project(mid);
05191       endP = stop_plane.project(end);
05192 
05193       // Calculate the distance between the points
05194       begDist = beg.distance_between(begP);
05195       midDist = mid.distance_between(midP);
05196       endDist = end.distance_between(endP);
05197     }
05198     else  // No stop plane specified
05199     {
05200       begDist = beg.distance_between(target_body->center_point());
05201       midDist = mid.distance_between(target_body->center_point());
05202       endDist = end.distance_between(target_body->center_point());
05203     }
05204 
05205     // Find the largest distance
05206     if (begDist > larDist)
05207       larDist = begDist;
05208     if (midDist > larDist)
05209       larDist = midDist;
05210     if (endDist > larDist)
05211       larDist = endDist;
05212 
05213     // Make sure the plane normal is pointing the right way
05214     if (set_plane)
05215     {
05216       double planeNorm = stop_plane.normal().interior_angle(beg-begP);
05217       if (planeNorm <= 90 || planeNorm >= 270)
05218         stop_plane.reverse();
05219     }
05220 
05221     if (!set_dist)
05222       dir += (midP-mid);
05223 
05224   } // End for loop
05225   if (!set_dist)
05226     dir /= edge_list.size();
05227 
05228   // Unitize the direction vector
05229   dir /= dir.length();
05230 
05231   // Add the magnitude to the direction vector and check for intersection with the stop plane
05232   dir *= larDist;
05233   if (set_plane)
05234   {
05235     double angle = dir.interior_angle(stop_plane.normal());
05236     if (angle >= 90 && angle <= 270)
05237       PRINT_WARNING("Direction vector does not intersect stop plane!\n");
05238   }
05239 
05240   // Call the geometry function
05241   status = get_gme()->sweep_to_body(curve_list, target_body->get_body_sm_ptr(), dir, new_bodies, unite);
05242 
05243   if (status != CUBIT_SUCCESS)
05244     return CUBIT_FAILURE;
05245 
05246   // Make all the new bodies
05247   for (int i = 0; i < new_bodies.size(); i++)
05248   {
05249     out_bodies.append(GeometryQueryTool::instance()->make_Body(new_bodies.get_and_step()));
05250     PRINT_INFO("Created volume in body %d\n", out_bodies[i]->id());
05251   }
05252 
05253   return CUBIT_SUCCESS;
05254 }
05255 
05256 //Author: Jonathan Bugman
05257 //Sept 10, 2006
05258 CubitStatus GeometryModifyTool::sweep_surface_target(CubitPlane ref_plane,
05259                                     DLIList<RefEntity*>& ref_ent_list)
05260 {
05261     DLIList<RefFace*> surface_list;
05262     CAST_LIST(ref_ent_list, surface_list, RefFace);
05263     double distance1;
05264     double distance2;
05265     double distance3;
05266     double temp_counter=0;
05267     CubitVector begin_point;
05268     CubitVector target_begin_point;
05269     CubitVector get_mid_point;
05270     CubitVector target_mid_point;
05271     CubitVector end_point;
05272     CubitVector target_end_point;
05273     CubitVector result;
05274     double max_distance_for_edge=0;
05275     CubitVector max_result;
05276     DLIList<RefEdge*> surf_edge_list;
05277 
05278     //make sure that only one surface has been selected
05279     if(surface_list.size() == 0)
05280     {
05281         PRINT_ERROR( "No surface found - sweep surface to target failed.\n" );
05282         return CUBIT_FAILURE;
05283     }
05284 
05285     //make sure that there are actually surfaces in list
05286     else if(surface_list.size() > 1)
05287     {
05288         PRINT_ERROR( "You can only use this operation \n with one surface selected at a time\n" );
05289         return CUBIT_FAILURE;
05290     }
05291     else
05292     {
05293         //this part of the code steps through all edges that could be
05294         //selected by user and finds the largest distance of all edges from three
05295         //points: midpoint, endpoint, and beginpoint
05296         for (int i=0;i<surface_list.size();i++)
05297         {
05298             surface_list[i]->ref_edges(surf_edge_list);
05299             for (int j=0;j<surf_edge_list.size();j++)
05300             {
05301                 //get midpoint of edge on surface
05302                 surf_edge_list[j]->mid_point(get_mid_point);
05303                 //Project the midpoint of each surface edge onto the specified plane
05304                 target_mid_point = ref_plane.project(get_mid_point);
05305 
05306                 //Calculate the distance between the mid_point, and target_point
05307                 distance1 = target_mid_point.distance_between(get_mid_point);
05308 
05309                 //the next two blocks are just copies of the above three steps
05310 
05311                 int fraction_along_curve = 1;
05312                 surf_edge_list[j]->position_from_fraction(fraction_along_curve, end_point);
05313                 target_end_point = ref_plane.project(end_point);
05314                 distance2 = target_end_point.distance_between(end_point);
05315 
05316                 fraction_along_curve = 0;
05317                 surf_edge_list[j]->position_from_fraction(fraction_along_curve, begin_point);
05318                 target_begin_point = ref_plane.project(begin_point);
05319                 distance3 = target_begin_point.distance_between(begin_point);
05320 
05321                 //see which of the three distances is greater of the edge
05322                 //and compare its distance to the other edges
05323                 if (distance1>distance2 && distance1>distance3)
05324                 {
05325                     result = 2*(target_mid_point - get_mid_point);
05326                     max_distance_for_edge=distance1;
05327                     if (max_distance_for_edge>temp_counter)
05328                     {
05329                         temp_counter = max_distance_for_edge;
05330                         max_result=result;
05331 
05332                     }
05333                 }
05334                 else if (distance2>distance3)
05335                 {
05336                     result = 2*(target_end_point - end_point);
05337                     max_distance_for_edge=distance2;
05338                     if (max_distance_for_edge>temp_counter)
05339                     {
05340                         temp_counter = max_distance_for_edge;
05341                         max_result=result;
05342 
05343                     }
05344                 }
05345                 else
05346                 {
05347                     result = 2*(target_begin_point - begin_point);
05348                     max_distance_for_edge=distance3;
05349                     if (max_distance_for_edge>temp_counter)
05350                     {
05351                         temp_counter = max_distance_for_edge;
05352                         max_result=result;
05353 
05354                     }
05355                 }
05356                 //just checking to make sure the user didn't specify a surface as both
05357                 //a target surface and sweeping surface which would result in a CUBIT crash
05358                 if (i==surface_list.size()-1 && j==surf_edge_list.size()-1 &&
05359                     max_distance_for_edge < 0.000000000000001)
05360                 {
05361                     PRINT_ERROR( "The sweep distance is less than the geometry tolerance\n" );
05362                     PRINT_ERROR( "This may be caused by selecting the same\n");
05363                     PRINT_ERROR( "sweep surface and target surface\n" );
05364                     return CUBIT_FAILURE;
05365                 }
05366             }
05367         }
05368         //using the facet edges defined by the drawing geometry code; take the leading
05369         //and trailing edge vectors of each facet edge;  With that, calc the dot product
05370         //and if negative (meaning the vector directions switched) the curve travels
05371         //through the plane and the sweep function will fail
05372         surface_list.reset();
05373         surf_edge_list.clean_out();
05374         for (int kk=0;kk<surface_list.size();kk++)
05375         {
05376             surface_list[kk]->ref_edges(surf_edge_list);
05377             for (int ii=0;ii<surf_edge_list.size();ii++)
05378             {
05379                 Curve *facet_curve;
05380                 facet_curve=surf_edge_list[ii]->get_curve_ptr();
05381                 CubitStatus response;
05382                 GMem g_mem;
05383 
05384                 //get number of points and their locations
05385                 //on the curve as defined by the drawing geometry algorithm
05386                 response = facet_curve->get_geometry_query_engine()->
05387                     get_graphics( facet_curve, &g_mem );
05388 
05389         int num_points = g_mem.pointListCount;
05390 
05391                 if (response==CUBIT_FAILURE || num_points == 0)
05392                 {
05393                     PRINT_WARNING("Unable to preview a curve\n" );
05394                 }
05395 
05396                 GPoint *point_data = g_mem.point_list();
05397 
05398                 for (int jj=0; jj < (num_points-1); jj++)
05399                 {
05400                     //get first points vectors
05401                     CubitVector point_1;
05402                     point_1.x(point_data[jj].x);
05403                     point_1.y(point_data[jj].y);
05404                     point_1.z(point_data[jj].z);
05405                     //get second points vectors
05406                     CubitVector point_2;
05407                     point_2.x(point_data[jj+1].x);
05408                     point_2.y(point_data[jj+1].y);
05409                     point_2.z(point_data[jj+1].z);
05410                     //project the two points onto target plane
05411                     CubitVector target_point_1;
05412                     target_point_1 = ref_plane.project(point_1);
05413                     CubitVector target_point_2;
05414                     target_point_2 = ref_plane.project(point_2);
05415                     //calc vector from point on curve to point on surface
05416                     CubitVector vec_1 = point_1 - target_point_1;
05417                     CubitVector vec_2 = point_2 - target_point_2;
05418                     //make them unit vectors
05419                     vec_1.normalize();
05420                     vec_2.normalize();
05421                     //double dot = DotProduct(vec_1,vec_2);
05422                     //calculate dot product
05423                     double dot = vec_1.x()*vec_2.x()+vec_1.y()*vec_2.y()+vec_1.z()*vec_2.z();
05424 
05425                     //check to see if dot product sign is zero
05426                     //the and statement checks for if the first or last vertex of the edge
05427                     //which may be sitting on the surface, this is alright
05428                     //and should still be able to sweep
05429                     if (dot<0 && 0<jj && jj<(num_points-2))
05430                     {
05431                         PRINT_ERROR( "The surface is traveling through the plane\n" );
05432                         PRINT_ERROR( "and thus forces the sweep direction to switch\n" );
05433                         PRINT_ERROR( "direction. Try splitting the surface.\n" );
05434                         return CUBIT_FAILURE;
05435                     }
05436                 }
05437             }
05438         }
05439 
05440         DLIList<Body*> body_list;
05441         DLIList<GeometryEntity*> geom_list;
05442         GeometryModifyEngine* gePtr1 = 0;
05443         CubitBoolean change_newids;
05444 
05445         if (!sweep_setup("translational", ref_ent_list, body_list, gePtr1,
05446             change_newids, geom_list, false ))
05447             return CUBIT_FAILURE;
05448 
05449     if( CubitUndo::get_undo_enabled())
05450       //Faces will get consumed so you have to save out original entities
05451       CubitUndo::save_state_with_cubit_file( surface_list );
05452 
05453         DLIList<BodySM*> sweep_result_list;
05454 
05455         //below block is default settings to be fed into sweep_translational
05456         CubitBoolean rigid = CUBIT_FALSE;
05457         CubitBoolean switchside = CUBIT_FALSE;
05458         int draft_type = 0;
05459         double draft_angle=0.0;
05460 
05461         //find normal vector to user specified plane
05462         CubitVector vec1 = ref_plane.normal();
05463         CubitVector vec2;
05464         CubitVector vec3;
05465         //get orthogonal vectors of the normal vector
05466         vec1.orthogonal_vectors(vec2, vec3);
05467         //place the orthogonal vectors at a point on the plane as opposed to the origin
05468         vec2=vec2+target_mid_point;
05469         vec3=vec3+target_mid_point;
05470         DLIList<BodySM*> webcut_results_list;
05471         //get a point on the first user specified surface before it gets consumed in the sweep_translational function
05472         CubitVector mid_point_surface;
05473         mid_point_surface = surface_list[0]->center_point();
05474 
05475         //sweep the curve down through and hopefully past the target surface
05476         CubitStatus status = gePtr1->sweep_translational( geom_list,sweep_result_list,
05477             max_result,draft_angle, draft_type,switchside,rigid,CUBIT_FALSE,CUBIT_FALSE);
05478 
05479         if (status == 0)
05480         {
05481             //If in here, sweep_translational failed so delete result_list and
05482             //print an error to the screen for the user
05483             gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
05484             PRINT_ERROR( "Error occured in the sweep operation.\n" );
05485 
05486                         if( CubitUndo::get_undo_enabled())
05487                           CubitUndo::remove_last_undo();
05488             return CUBIT_FAILURE;
05489         }
05490 
05491                 DLIList<BodySM*> neighbor_imprint_list;
05492         //do a webcut with a plane created from the three projected points
05493         CubitStatus status2 = gePtr1->webcut(sweep_result_list,target_mid_point,
05494             vec2,vec3,neighbor_imprint_list, webcut_results_list);
05495 
05496         if (status2 == 0)
05497         {
05498             //If in here, webcut operation failed so delete result_list and
05499             //print an error to the screen for the user
05500             gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
05501             gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
05502             PRINT_ERROR( "Error occured in the webcut operation.\n" );
05503 
05504                         if( CubitUndo::get_undo_enabled())
05505                           CubitUndo::remove_last_undo();
05506             return CUBIT_FAILURE;
05507         }
05508 
05509         DLIList<BodySM*> keep_bodies_list = webcut_results_list;
05510         int bodies_deleted_counter=0;
05511         CubitVector target_mid_point_volume;
05512         CubitVector mid_point_volume;
05513         CubitVector target_mid_point_surface;
05514         double volume_size;
05515 
05516         //project the mid_point of user specified surface onto target plane
05517         target_mid_point_surface = ref_plane.project(mid_point_surface);
05518         //calculate vector between the two points and then normalize
05519         CubitVector vec_1 = mid_point_surface - target_mid_point_surface;
05520         vec_1.normalize();
05521 
05522         //step through the
05523         for (int counter=0;counter<webcut_results_list.size();counter++)
05524         {
05525             //find the geometric midpoint of the body and project that point on the target plane
05526             webcut_results_list[counter]->mass_properties(mid_point_volume,volume_size);
05527             target_mid_point_volume = ref_plane.project(mid_point_volume);
05528             //generate a vector between the two points and then normalize
05529             CubitVector vec_2 = mid_point_volume - target_mid_point_volume;
05530             vec_2.normalize();
05531 
05532             //calculate the dot product
05533             double dot = vec_1.x()*vec_2.x()+vec_1.y()*vec_2.y()+vec_1.z()*vec_2.z();
05534 
05535             //if a negative dot product delete it because it is on the opposite side of the target plane
05536             if (dot < 0)
05537             {
05538                 keep_bodies_list.remove(webcut_results_list[counter]);
05539                 bodies_deleted_counter = bodies_deleted_counter + 1;
05540             }
05541 
05542         }
05543 
05544         //test to see if all bodies have been deleted and if so let the user know
05545         if (bodies_deleted_counter == webcut_results_list.size())
05546         {
05547             PRINT_ERROR( "All sweeped surfaces deleted - sweep_target failed.\n" );
05548             PRINT_ERROR( "This may be due to granite engine limitations and/or\n" );
05549             PRINT_ERROR( "angle between curve and target surface\n" );
05550 
05551                         if( CubitUndo::get_undo_enabled())
05552                           CubitUndo::remove_last_undo();
05553             return CUBIT_FAILURE;
05554         }
05555 
05556         //delete webcut_results_list since it is no longer of use
05557         webcut_results_list -= keep_bodies_list;
05558         gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
05559 
05560         //builds ref bodies
05561     DLIList<Body*> output_body_list;
05562         if (!sweep_finish("translational", body_list, keep_bodies_list, output_body_list, change_newids))
05563             status = CUBIT_FAILURE;
05564 
05565     if( CubitUndo::get_undo_enabled())
05566     {
05567       if( status == CUBIT_FAILURE )
05568         CubitUndo::remove_last_undo();
05569       else
05570         CubitUndo::note_result_bodies( output_body_list );
05571     }
05572 
05573     }
05574     return CUBIT_SUCCESS;
05575 }
05576 
05577 
05578 CubitStatus GeometryModifyTool::sweep_perpendicular( DLIList<RefEntity*>& ref_ent_list,
05579                                                      double distance,
05580                                                      double draft_angle,
05581                                                      int draft_type,
05582                                                      CubitBoolean switchside,
05583                                                      CubitBoolean rigid,
05584                                                      CubitBoolean anchor_entity,
05585                                                      CubitBoolean keep_old,
05586                                                      DLIList<Body*>& output_body_list)
05587 {
05588   DLIList<Body*> body_list;
05589   DLIList<GeometryEntity*> geom_list;
05590   GeometryModifyEngine* gePtr1 = 0;
05591   CubitBoolean change_newids;
05592   if (!sweep_setup("translational", ref_ent_list, body_list, gePtr1,
05593                    change_newids, geom_list, keep_old))
05594     return CUBIT_FAILURE;
05595 
05596   if( CubitUndo::get_undo_enabled())
05597   {
05598     DLIList<RefEdge*> edge_list;
05599     DLIList<RefFace*> face_list;
05600 
05601     CAST_LIST( ref_ent_list, edge_list, RefEdge );
05602     CAST_LIST( ref_ent_list, face_list, RefFace );
05603 
05604     //Edges aren't consumed, so there's nothing to save out
05605     if( edge_list.size() || keep_old )
05606       CubitUndo::save_state();
05607     else
05608      //Faces will get consumed so you have to save out original entities
05609       CubitUndo::save_state_with_cubit_file( face_list );
05610   }
05611 
05612   DLIList<BodySM*> result_list;
05613   CubitStatus status = gePtr1->
05614     sweep_perpendicular( geom_list,
05615                          result_list,
05616                          distance,
05617                          draft_angle,
05618                          draft_type,
05619                          switchside,
05620                          rigid,
05621                          anchor_entity,
05622                          keep_old );
05623 
05624   if( keep_old )
05625     body_list.clean_out();
05626 
05627   if (!sweep_finish("perpendicular", body_list, result_list, output_body_list, change_newids))
05628     status = CUBIT_FAILURE;
05629 
05630   if( CubitUndo::get_undo_enabled())
05631   {
05632     if( status == CUBIT_FAILURE )
05633       CubitUndo::remove_last_undo();
05634     else
05635       CubitUndo::note_result_bodies( output_body_list );
05636   }
05637 
05638   return status;
05639 }
05640 CubitStatus GeometryModifyTool::sweep_along_curve(DLIList<RefEntity*>& ref_ent_list,
05641                                                   DLIList<RefEdge*>& ref_edge_list,
05642                                                   DLIList<Body*>& output_body_list,
05643                                                   CubitBoolean anchor_entity,
05644                                                   CubitBoolean keep_old,
05645                                                   double draft_angle,
05646                                                   int draft_type,
05647                                                   CubitBoolean rigid)
05648 
05649 {
05650   DLIList<GeometryEntity*> geom_list(ref_ent_list.size());
05651   DLIList<Curve*> curve_list(ref_edge_list.size());
05652   DLIList<Body*> body_list(ref_ent_list.size());
05653   GeometryModifyEngine* engine_ptr = 0;
05654   CubitBoolean changed_new_ids = CUBIT_FALSE;
05655   CubitStatus status = sweep_setup( "along_curve",
05656                                     ref_ent_list,
05657                                     body_list,
05658                                     engine_ptr,
05659                                     changed_new_ids,
05660                                     geom_list,
05661                                     keep_old,
05662                                     &ref_edge_list,
05663                                     &curve_list );
05664   if (status != CUBIT_SUCCESS)
05665   return status;
05666 
05667   if( CubitUndo::get_undo_enabled())
05668   {
05669     DLIList<RefEdge*> edge_list;
05670     DLIList<RefFace*> face_list;
05671 
05672     CAST_LIST( ref_ent_list, edge_list, RefEdge );
05673     CAST_LIST( ref_ent_list, face_list, RefFace );
05674 
05675     //Edges aren't consumed, so there's nothing to save out
05676     if( keep_old )
05677       CubitUndo::save_state();
05678     else
05679     {
05680       bool free_curves = false;
05681       for( int i=edge_list.size(); i--; )
05682       {
05683         if( edge_list.get_and_step()->num_parent_ref_entities() == 0 )
05684         {
05685           free_curves = true;
05686           break;
05687         }
05688       }
05689 
05690       DLIList<Body*> bodies_to_save;
05691       DLIList<RefEntity*> free_surfaces;
05692       for( int i=face_list.size(); i--; )
05693       {
05694         RefFace *ref_face = face_list.get_and_step();
05695 
05696         if( ref_face->num_parent_ref_entities() == 0 )
05697           free_surfaces.append( ref_face );
05698         else
05699           bodies_to_save.append_unique( ref_face->ref_volume()->body() );
05700       }
05701       //Faces will get consumed so you have to save out original entities
05702       if( bodies_to_save.size() || free_surfaces.size() )
05703         CubitUndo::save_state_with_cubit_file( bodies_to_save, &free_surfaces );
05704       else if(free_curves )
05705         CubitUndo::save_state_with_cubit_file( edge_list );
05706       else
05707         CubitUndo::save_state();
05708     }
05709   }
05710 
05711   DLIList<BodySM*> result_list;
05712   status = engine_ptr->sweep_along_curve( geom_list,
05713                                           result_list,
05714                                           curve_list,
05715                                           draft_angle,
05716                                           draft_type,
05717                                           rigid,
05718                                           anchor_entity,
05719                                           keep_old);
05720 
05721   if( keep_old )
05722     body_list.clean_out();
05723 
05724   if (!sweep_finish("along_curve", body_list, result_list, output_body_list, changed_new_ids))
05725   status = CUBIT_FAILURE;
05726 
05727   if( CubitUndo::get_undo_enabled())
05728   {
05729     if( status == CUBIT_FAILURE )
05730       CubitUndo::remove_last_undo();
05731     else
05732       CubitUndo::note_result_bodies( output_body_list );
05733   }
05734 
05735   return status;
05736 }
05737 
05738 void GeometryModifyTool::initialize_settings() {
05739 
05740 
05741   SettingHandler::instance()->add_setting("Group Imprint",
05742                       GeometryModifyTool::set_group_imprint,
05743                       GeometryModifyTool::get_group_imprint);
05744 
05745   SettingHandler::instance()->add_setting("NonRegImprint",
05746                       GeometryModifyTool::set_all_edges_imprint,
05747                       GeometryModifyTool::get_all_edges_imprint);
05748 
05749   SettingHandler::instance()->add_setting("New Ids",
05750                       GeometryModifyTool::set_new_ids,
05751                       GeometryModifyTool::get_new_ids);
05752 
05753   SettingHandler::instance()->add_setting("Separate After Webcut",
05754                       GeometryModifyTool::set_sep_after_webcut_setting,
05755                       GeometryModifyTool::get_sep_after_webcut_setting);
05756 
05757   SettingHandler::instance()->add_setting("old names",
05758             GeometryModifyTool::set_old_names,
05759             GeometryModifyTool::get_old_names);
05760 }
05761 
05762 
05763 
05764 // ********** END PUBLIC FUNCTIONS         **********
05765 
05766 // ********** BEGIN PROTECTED FUNCTIONS    **********
05767 
05768 //-------------------------------------------------------------------------
05769 // Purpose       : Constructor of the GeometryModifyTool class.
05770 //
05771 // Special Notes :
05772 //
05773 // Creator       : Xuechen Liu
05774 //
05775 // Creation Date : 07/11/96
05776 //-------------------------------------------------------------------------
05777 GeometryModifyTool::GeometryModifyTool(GeometryModifyEngine*gme_ptr)
05778 {
05779   if (gme_ptr) gmeList.append(gme_ptr);
05780 }
05781 
05782 //-------------------------------------------------------------------------
05783 // Purpose       : This functions webcuts a list of bodies through a plane.
05784 //                 The newly created bodies are and merged depeding on the
05785 //                 respective flags.
05786 //
05787 // Special Notes :
05788 //
05789 // Creator       : Raikanta Sahu
05790 //
05791 // Creation Date : 12/17/96
05792 //-------------------------------------------------------------------------
05793 
05794 CubitStatus GeometryModifyTool::webcut_with_brick(
05795                                            DLIList<Body*>& webcut_body_list,
05796                                            const CubitVector &center,
05797                                            const CubitVector axes[3],
05798                                            const CubitVector &extension,
05799                                            DLIList<Body*> &results_list,
05800                                            DLIList<Body*> &neighboring_bodies,
05801                                            ImprintType imprint_type,
05802                                            CubitBoolean merge,
05803                                            CubitBoolean preview)
05804 {
05805    // Make sure that entity creation is possible.  Allow at most
05806    // only one of the dimensions to be zero - in which case a planar
05807    // sheet is used to do the cutting.
05808    double width = 2.0*extension.x();
05809    double height = 2.0*extension.y();
05810    double depth = 2.0*extension.z();
05811    if ( width < 0.0 || height < 0.0 || depth < 0.0 )
05812    {
05813       PRINT_ERROR( "Cannot make a brick of size %f x %f x %f\n"
05814                    "     Negative dimensions are not allowed.\n",
05815                    width, height, depth );
05816       return CUBIT_FAILURE ;
05817    }
05818 
05819    BodySM *cutting_tool_ptr = NULL;
05820    CubitBoolean is_sheet_body = CUBIT_FALSE;
05821    CubitVector p1, p2, p3, p4;
05822    int wz = width < GEOMETRY_RESABS;
05823    int hz = height < GEOMETRY_RESABS;
05824    int dz = depth < GEOMETRY_RESABS;
05825    int num_zero_dim = wz + hz + dz;
05826    if( num_zero_dim > 0 )
05827    {
05828       if( num_zero_dim > 1 )
05829       {
05830          PRINT_ERROR( "Cannot make a sheet of size %f x %f x %f\n"
05831             "     At least two dimensions must be nonzero.\n",
05832             width, height, depth );
05833          return CUBIT_FAILURE ;
05834       }
05835 
05836       // Make a sheet body instead of a cuboid
05837       CubitVector sheet_axes[2];
05838       if( wz )
05839       {
05840          sheet_axes[0] = axes[1];
05841          sheet_axes[1] = axes[2];
05842          width = depth;
05843       }
05844       else if( hz )
05845       {
05846          sheet_axes[0] = axes[2];
05847          sheet_axes[1] = axes[0];
05848          height = depth;
05849       }
05850       else
05851       {
05852          sheet_axes[0] = axes[0];
05853          sheet_axes[1] = axes[1];
05854       }
05855 
05856       // Get the corners of the sheet ready
05857       center.next_point( axes[0], width/2.0, p1 );
05858       p1.next_point( axes[1], -height/2.0, p1 );
05859       p1.next_point( axes[1], height, p2 );
05860       p2.next_point( axes[0], -width, p3 );
05861       p3.next_point( axes[1], -height, p4 );
05862    }
05863 
05864    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
05865      return CUBIT_FAILURE;
05866 
05867    CubitVector tmp_vec( center.x()+width, center.y()+height, center.z()+depth );
05868    CubitBox tmp_box(tmp_vec);
05869    tmp_vec.set( center.x()-width, center.y()-height, center.z()-depth );
05870    tmp_box |= tmp_vec;
05871    remove_bodies_outside_bounding_box( webcut_body_list, tmp_box );
05872 
05873    if( webcut_body_list.size() == 0 )
05874    {
05875      PRINT_INFO("Tool does not intersect any bodies/volumes.\n");
05876      return CUBIT_FAILURE;
05877    }
05878 
05879    if( CubitUndo::get_undo_enabled() )
05880    {
05881      DLIList<Body*> bodies_to_save;
05882      bodies_to_save += webcut_body_list;
05883      bodies_to_save += neighboring_bodies;
05884      CubitUndo::save_state_with_cubit_file( bodies_to_save );
05885    }
05886 
05887    CubitStatus rval = CUBIT_SUCCESS;
05888 
05889    const int count = webcut_body_list.size();
05890    DLIList<BodySM*> result_sm_list;
05891    DLIList<Body*> body_list(webcut_body_list);
05892    DLIList<BodySM*> engine_body_sms(count);
05893    DLIList<Body*> engine_bodies(count);
05894    GeometryModifyEngine* gme = 0;
05895 
05896    while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
05897    {
05898      DLIList<int> merged_surface_ids;
05899      DLIList<int> merged_curve_ids;
05900      DLIList<BodySM*> neighbor_imprint_list;
05901      if (!preview)
05902      {
05903        int i;
05904        for( i=neighboring_bodies.size(); i--; )
05905        {
05906          Body *neighbor_body = neighboring_bodies.get_and_step();
05907          BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
05908          GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
05909 
05910          if( gme == neighbor_gme )
05911          {
05912            neighbor_imprint_list.append( tmp_body );
05913            engine_bodies.append( neighbor_body );
05914          }
05915        }
05916 
05917        do_attribute_setup();
05918        DLIList<BodySM*> bodies_to_modify;
05919        bodies_to_modify += engine_body_sms;
05920        bodies_to_modify += neighbor_imprint_list;
05921        push_attributes_before_modify( bodies_to_modify );
05922        get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
05923      }
05924 
05925      // Create the brick to cut with
05926     if (is_sheet_body)
05927       cutting_tool_ptr = gme->planar_sheet(p1,p2,p3,p4);
05928     else
05929       cutting_tool_ptr = gme->brick( center, axes, extension );
05930     if( cutting_tool_ptr == NULL )
05931        return CUBIT_FAILURE;
05932 
05933     CubitStatus status = gme->webcut (
05934       engine_body_sms, cutting_tool_ptr,
05935       neighbor_imprint_list,
05936       result_sm_list, imprint_type, preview );
05937 
05938     // Delete the BodySM that was created to be used as a tool
05939     gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
05940 
05941       // just continue the loop if previewing
05942       if (preview)
05943       {
05944         rval = status;
05945         continue;
05946       }
05947 
05948       restore_vg_after_modify(result_sm_list, engine_bodies, gme);
05949       remove_pushed_attributes(result_sm_list, engine_bodies);
05950 
05951       status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list,
05952                               &merged_surface_ids, &merged_curve_ids );
05953 
05954       if (!status)
05955         rval = CUBIT_FAILURE;
05956 
05957       engine_bodies.clean_out();
05958       engine_body_sms.clean_out();
05959       result_sm_list.clean_out();
05960    }
05961 
05962    if (!preview)
05963      do_attribute_cleanup();
05964 
05965    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
05966    {
05967      if( results_list.size() ) //if there are new bodies...something succeeded
05968        CubitUndo::note_result_bodies( results_list );
05969      else
05970        CubitUndo::remove_last_undo();
05971    }
05972 
05973    return rval;
05974 }
05975 
05976 CubitStatus GeometryModifyTool::webcut_with_planar_sheet(
05977                                            DLIList<Body*>& webcut_body_list,
05978                                            const CubitVector &center,
05979                                            const CubitVector axes[2],
05980                                            double width, double height,
05981                                            DLIList<Body*> &results_list,
05982                                            DLIList<Body*> &neighboring_bodies,
05983                                            ImprintType imprint_type,
05984                                            CubitBoolean merge,
05985                                            CubitBoolean preview)
05986 {
05987    if ( width <= GEOMETRY_RESABS || height <= GEOMETRY_RESABS )
05988    {
05989       PRINT_ERROR( "Cannot webcut with a sheet of size %f x %f\n"
05990                    "     Negative or zero dimensions are not allowed.\n",
05991                    width, height );
05992       return CUBIT_FAILURE ;
05993    }
05994 
05995    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
05996      return CUBIT_FAILURE;
05997 
05998    CubitStatus rval = CUBIT_SUCCESS;
05999 
06000   if( CubitUndo::get_undo_enabled() )
06001   {
06002     DLIList<Body*> bodies_to_save;
06003     bodies_to_save += webcut_body_list;
06004     bodies_to_save += neighboring_bodies;
06005     CubitUndo::save_state_with_cubit_file( bodies_to_save );
06006   }
06007 
06008    const int count = webcut_body_list.size();
06009    DLIList<BodySM*> result_sm_list;
06010    DLIList<Body*> body_list(webcut_body_list);
06011    DLIList<BodySM*> engine_body_sms(count);
06012    DLIList<Body*> engine_bodies(count);
06013    GeometryModifyEngine* gme = 0;
06014 
06015    while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
06016    {
06017      DLIList<int> merged_surface_ids;
06018      DLIList<int> merged_curve_ids;
06019      DLIList<BodySM*> neighbor_imprint_list;
06020      if (!preview)
06021      {
06022        int i;
06023        for( i=neighboring_bodies.size(); i--; )
06024        {
06025          Body *neighbor_body = neighboring_bodies.get_and_step();
06026          BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
06027          GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
06028 
06029          if( gme == neighbor_gme )
06030          {
06031            neighbor_imprint_list.append( tmp_body );
06032            engine_bodies.append( neighbor_body );
06033          }
06034        }
06035 
06036        do_attribute_setup();
06037        DLIList<BodySM*> bodies_sms_to_modify;
06038        bodies_sms_to_modify += engine_body_sms;
06039        bodies_sms_to_modify += neighbor_imprint_list;
06040        push_attributes_before_modify( bodies_sms_to_modify );
06041        get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
06042      }
06043 
06044      // Create the planar sheet to cut with
06045      CubitVector p1, p2, p3, p4;
06046 
06047      // Get the corners of the sheet
06048      center.next_point( axes[0], width/2.0, p1 );
06049      p1.next_point( axes[1], -height/2.0, p1 );
06050      p1.next_point( axes[1], height, p2 );
06051      p2.next_point( axes[0], -width, p3 );
06052      p3.next_point( axes[1], -height, p4 );
06053 
06054      BodySM *cutting_tool_ptr = gme->planar_sheet(p1,p2,p3,p4);
06055      if( cutting_tool_ptr == NULL )
06056         return CUBIT_FAILURE;
06057 
06058      CubitStatus status = gme->webcut (
06059        engine_body_sms, cutting_tool_ptr,
06060        neighbor_imprint_list,
06061        result_sm_list, imprint_type, preview );
06062 
06063      // Delete the BodySM that was created to be used as a tool
06064      gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
06065 
06066       // just continue the loop if previewing
06067       if (preview)
06068       {
06069         rval = status;
06070         continue;
06071       }
06072 
06073       restore_vg_after_modify(result_sm_list, engine_bodies, gme);
06074       remove_pushed_attributes(result_sm_list, engine_bodies);
06075 
06076       status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list,
06077                               &merged_surface_ids, &merged_curve_ids );
06078       if (!status)
06079         rval = CUBIT_FAILURE;
06080 
06081       engine_bodies.clean_out();
06082       engine_body_sms.clean_out();
06083       result_sm_list.clean_out();
06084    }
06085 
06086    if (!preview)
06087      do_attribute_cleanup();
06088 
06089   if( preview == CUBIT_FALSE && CubitUndo::get_undo_enabled() )
06090   {
06091     if( rval == CUBIT_SUCCESS )
06092       CubitUndo::note_result_bodies( results_list );
06093     else
06094       CubitUndo::remove_last_undo();
06095   }
06096 
06097    return rval;
06098 }
06099 
06100 CubitStatus GeometryModifyTool::webcut_with_plane(
06101                                     DLIList<Body*>& webcut_body_list,
06102                                     const CubitVector &vector1,
06103                                     const CubitVector &vector2,
06104                                     const CubitVector &vector3,
06105                                     DLIList<Body*>& results_list,
06106                                     DLIList<Body*> &neighboring_bodies,
06107                                     ImprintType imprint_type,
06108                                     CubitBoolean merge,
06109                                     CubitBoolean preview)
06110 {
06111   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
06112     return CUBIT_FAILURE;
06113 
06114   GfxPreview::clear();
06115 
06116   CubitStatus rval = CUBIT_SUCCESS;
06117   if (preview)
06118   {
06119     GeometryModifyTool::plane_preview(webcut_body_list, vector1, vector2, vector3);
06120     return rval;
06121   }
06122 
06123   //remove bodies that won't intersect plane bounding box
06124   remove_bodies_outside_bounding_box( webcut_body_list, vector1, vector2, vector3 );
06125 
06126   if( webcut_body_list.size() == 0 )
06127   {
06128     PRINT_INFO("Tool does not intersect any bodies/volumes.\n");
06129     return CUBIT_FAILURE;
06130   }
06131 
06132   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
06133   {
06134     DLIList<Body*> bodies_to_save;
06135     bodies_to_save += webcut_body_list;
06136     bodies_to_save += neighboring_bodies;
06137     CubitUndo::save_state_with_cubit_file( bodies_to_save );
06138   }
06139 
06140   const int count = webcut_body_list.size();
06141   DLIList<BodySM*> temp_sm_list(webcut_body_list.size());
06142   DLIList<BodySM*> result_sm_list;
06143   DLIList<Body*> body_list(webcut_body_list);
06144   DLIList<BodySM*> engine_body_sms(count);
06145   DLIList<Body*> engine_bodies(count);
06146   GeometryModifyEngine* gme = 0;
06147 
06148   // all preview stuff handled before this point
06149   if(!preview)
06150     do_attribute_setup();
06151 
06152   while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
06153   {
06154 
06155     //get all the child entities that have been merged
06156     DLIList<int> merged_surface_ids;
06157     DLIList<int> merged_curve_ids;
06158     DLIList<BodySM*> neighbor_imprint_list;
06159 
06160     if (!preview)
06161     {
06162       int i;
06163       for( i=neighboring_bodies.size(); i--; )
06164       {
06165         Body *neighbor_body = neighboring_bodies.get_and_step();
06166         BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
06167         GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
06168 
06169         if( gme == neighbor_gme )
06170         {
06171           neighbor_imprint_list.append( tmp_body );
06172           engine_bodies.append( neighbor_body );
06173         }
06174       }
06175 
06176       DLIList<BodySM*> bodies_sms_to_modify;
06177       bodies_sms_to_modify += engine_body_sms;
06178       bodies_sms_to_modify += neighbor_imprint_list;
06179       push_attributes_before_modify( bodies_sms_to_modify );
06180       get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
06181     }
06182 
06183     CubitStatus status = gme->webcut(engine_body_sms, vector1, vector2,
06184               vector3, neighbor_imprint_list, result_sm_list, imprint_type, preview );
06185 
06186     if ( status != CUBIT_FAILURE )
06187     {
06188       if(!preview)
06189       {
06190         restore_vg_after_modify(result_sm_list, engine_bodies, gme);
06191         remove_pushed_attributes(result_sm_list, engine_bodies);
06192       }
06193       status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list,
06194                               &merged_surface_ids, &merged_curve_ids );
06195     }
06196     else
06197     {
06198       if(!preview)
06199         remove_pushed_attributes(result_sm_list, engine_bodies);
06200     }
06201 
06202     engine_bodies.clean_out();
06203     engine_body_sms.clean_out();
06204     result_sm_list.clean_out();
06205 
06206     if ( status == CUBIT_FAILURE )
06207     {
06208       rval = CUBIT_FAILURE;
06209       break;
06210     }
06211   }
06212 
06213   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
06214   {
06215     if( rval == CUBIT_SUCCESS )
06216       CubitUndo::note_result_bodies( results_list );
06217     else
06218       CubitUndo::remove_last_undo();
06219   }
06220 
06221   if(!preview)
06222     do_attribute_cleanup();
06223 
06224   return rval;
06225 }
06226 
06227 void GeometryModifyTool::remove_pushed_attributes(DLIList<BodySM*> &new_sms,
06228                                                         DLIList<Body*> &old_bodies)
06229 {
06230   DLIList<TopologyBridge*> old_bridges(old_bodies.size());
06231   DLIList<TopologyBridge*> new_bridges(new_sms.size());
06232   CAST_LIST(new_sms, new_bridges, TopologyBridge);
06233 
06234   // Get bridges for all of the old Bodies.
06235   int k;
06236   for(k = old_bodies.size(); k>0; k--)
06237   {
06238     Body *body = old_bodies.get_and_step();
06239     TopologyBridge *tb = body->bridge_manager()->topology_bridge();
06240     if(tb)
06241     {
06242       old_bridges.append(tb);
06243       DLIList<TopologyBridge*> bridge_list;
06244       bridge_list.append(tb);
06245       // Add any bodies with composites to the new_sms list so that
06246       // make_Body gets called on them.  This will make sure that the
06247       // virtual gets ref entities properly built.
06248       if(this->contains_composites(bridge_list))
06249       {
06250         BodySM *bsm = dynamic_cast<BodySM*>(tb);
06251         if(bsm)
06252           new_sms.append_unique(bsm);
06253       }
06254     }
06255   }
06256 
06257   // Make a list including all of the bridges passed in.
06258   DLIList<TopologyBridge*> all_bridges;
06259   all_bridges = new_bridges;
06260   for(k=old_bridges.size(); k--;)
06261     all_bridges.append_unique(old_bridges.get_and_step());   
06262   
06263   
06264   //Remove ENTITY_ID attributes off non-virtual entities
06265   DLIList<CubitSimpleAttrib> list;
06266   for( k=all_bridges.size(); k--; )
06267   {
06268     TopologyBridge *top_bridge = all_bridges.get_and_step();    
06269     GeometryModifyEngine *gme = get_engine(top_bridge);    
06270     DLIList<TopologyBridge*> children;
06271     gme->get_possible_invalid_tbs(all_bridges, children);
06272 
06273     for( int j=children.size(); j--; )
06274     {
06275       TopologyBridge *tmp_bridge = children.get_and_step();
06276       if( !GeometryQueryTool::instance()->is_intermediate_geometry( tmp_bridge ) )
06277       {
06278         tmp_bridge->get_simple_attribute( "ENTITY_ID", list );
06279         while( list.size() )    
06280           tmp_bridge->remove_simple_attribute_virt(list.pop());
06281       }
06282     }
06283   }    
06284 
06285   // At this point we don't need any more attributes on the underlying
06286   // entities so make sure they are cleaned up.
06287   GeometryQueryTool::instance()->ige_remove_attributes( all_bridges );
06288 }
06289 
06290 CubitStatus GeometryModifyTool::restore_vg_after_modify(DLIList<BodySM*> &new_sms,
06291                                                         DLIList<Body*> &old_bodies,
06292                                                         GeometryModifyEngine *gme)
06293 {
06294   DLIList<TopologyBridge*> old_bridges(old_bodies.size());
06295   DLIList<TopologyBridge*> new_bridges(new_sms.size());
06296   CAST_LIST(new_sms, new_bridges, TopologyBridge);
06297 
06298   // Get bridges for all of the old Bodies.
06299   int k;
06300   for(k = old_bodies.size(); k>0; k--)
06301   {
06302     Body *body = old_bodies.get_and_step();
06303     TopologyBridge *tb = body->bridge_manager()->topology_bridge();
06304     if(tb)
06305     {
06306       old_bridges.append(tb);
06307       DLIList<TopologyBridge*> bridge_list;
06308       bridge_list.append(tb);
06309       // Add any bodies with composites to the new_sms list so that
06310       // make_Body gets called on them.  This will make sure that the
06311       // virtual gets ref entities properly built.
06312       if(this->contains_composites(bridge_list))
06313       {
06314         BodySM *bsm = dynamic_cast<BodySM*>(tb);
06315         if(bsm)
06316           new_sms.append_unique(bsm);
06317       }
06318     }
06319   }
06320 
06321   // Make a list including all of the bridges passed in.
06322   DLIList<TopologyBridge*> all_bridges;
06323   all_bridges = new_bridges;
06324   for(k=old_bridges.size(); k--;)
06325     all_bridges.append_unique(old_bridges.get_and_step());
06326 
06327   DLIList<TopologyBridge*> tbs_to_check;
06328   if(gme)
06329     gme->get_possible_invalid_tbs(all_bridges, tbs_to_check);
06330 
06331   DLIList<Surface*> all_surfs;
06332   DLIList<Curve*> all_curves;
06333   DLIList<TBPoint*> all_points;
06334   if(tbs_to_check.size() > 0)
06335   {
06336     for(k=tbs_to_check.size(); k--;)
06337     {
06338       TopologyBridge *tb = tbs_to_check.get_and_step();
06339       Surface *surf = dynamic_cast<Surface*>(tb);
06340       if(surf)
06341         all_surfs.append(surf);
06342       else
06343       {
06344         Curve *cur = dynamic_cast<Curve*>(tb);
06345         if(cur)
06346           all_curves.append(cur);
06347         else
06348         {
06349           TBPoint *pt = dynamic_cast<TBPoint*>(tb);
06350           if(pt)
06351             all_points.append(pt);
06352         }
06353       }
06354     }
06355   }
06356 
06357   // This function has been changed to blown away any virtual (really only doing
06358   // composites right now).  The virtual will rebuilt from the attributes stored
06359   // on the  entities.
06360   GeometryQueryTool::instance()->ige_remove_modified(all_surfs, all_curves, all_points);
06361 
06362   //Restore virtual
06363   GeometryQueryTool::instance()->ige_import_geom( all_bridges );
06364 
06365   return CUBIT_SUCCESS;
06366 }
06367 
06368 GeometryModifyEngine* GeometryModifyTool::group_bodies_by_engine(
06369                                   DLIList<Body*>& remaining_bodies,
06370                                   DLIList<Body*>& engine_bodies,
06371                                   DLIList<BodySM*>& engine_body_sms ) const
06372 {
06373   int i = remaining_bodies.size();
06374   remaining_bodies.reset();
06375   GeometryModifyEngine* engine = 0;
06376 
06377   if (i == 0)
06378     return 0;
06379 
06380     // Skip over any bodies that don't have a modify engine.
06381   while (i--)
06382   {
06383     Body* body = remaining_bodies.get();
06384     TopologyBridge* bridge = 0;
06385     engine = get_engine(body, &bridge);
06386     if (engine)
06387     {
06388       remaining_bodies.change_to(0);
06389       engine_bodies.append(body);
06390       engine_body_sms.append(dynamic_cast<BodySM*>(bridge));
06391       remaining_bodies.step();
06392       break;
06393     }
06394     remaining_bodies.step();
06395   }
06396 
06397   // catch case where no engine was found
06398   if (0 == engine)
06399   {
06400     PRINT_WARNING("No geometry modify engine found for this operation.");
06401     return engine;
06402   }
06403 
06404 
06405     // Get remaining bodies with same modify engine.
06406   while (i--)
06407   {
06408     Body* body = remaining_bodies.get();
06409     TopologyBridge* bridge = 0;
06410     if (get_engine(body, &bridge) == engine)
06411     {
06412       remaining_bodies.change_to(0);
06413       engine_bodies.append(body);
06414       engine_body_sms.append(dynamic_cast<BodySM*>(bridge));
06415     }
06416     remaining_bodies.step();
06417   }
06418 
06419   remaining_bodies.remove_all_with_value(0);
06420   return engine;
06421 }
06422 
06423 
06424 
06425 
06426 // ********** END PRIVATE FUNCTIONS        **********
06427 
06428 // ********** BEGIN HELPER CLASSES         **********
06429 // ********** END HELPER CLASSES           **********
06430 
06431 // ********** BEGIN EXTERN FUNCTIONS       **********
06432 // ********** END EXTERN FUNCTIONS         **********
06433 
06434 // ********** BEGIN STATIC FUNCTIONS       **********
06435 // ********** END STATIC FUNCTIONS         **********
06436 
06437 CubitStatus GeometryModifyTool::unite( DLIList<BodySM*> &body_sm_list,
06438                                        DLIList<BodySM*> &new_body_sm_list,
06439                                        bool keep_old)
06440 {
06441   //this assumes that all bodies have the same modify engine
06442   GeometryModifyEngine *gme = get_engine( body_sm_list.get() );
06443   CubitStatus result = gme->unite(body_sm_list, new_body_sm_list, keep_old);
06444   return result;
06445 }
06446 
06447 CubitStatus
06448 GeometryModifyTool::unite( DLIList<Body*> &bodies,
06449                            DLIList<Body*> &new_body_list,
06450                            bool keep_old )
06451 {
06452   if( bodies.size() <= 1 )
06453   {
06454     PRINT_WARNING("There is only one volume in the list. Nothing modified.\n");
06455     return CUBIT_FAILURE;
06456   }
06457   if (!okay_to_modify( bodies, "UNITE" ))
06458     return CUBIT_FAILURE;
06459 
06460   int i;
06461   const int count = bodies.size();
06462   DLIList<TopologyEntity*> entity_list(count);
06463   DLIList<TopologyBridge*> bridge_list(count);
06464   bodies.reset();
06465   for (i = bodies.size(); i--; )
06466     entity_list.append_unique(bodies.get_and_step());
06467   GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
06468 
06469   if( !gme )
06470   {
06471     PRINT_ERROR("Performing UNITE with volumes containing geometry from\n"
06472       "different modeling engines is not allowed.\n"
06473       "Delete uncommon geometry on these volumes before operation.\n\n");
06474     return CUBIT_FAILURE;
06475   }
06476 
06477   // Cubit can't mesh mixed sheet/solid bodies that are united together. If
06478   // required, separate the unite between these types.
06479   CubitStatus result;
06480   if( GeometryModifyTool::instance()->unite_mixed_models() )
06481     result = unite_all( gme, bodies, new_body_list, keep_old );
06482   else
06483     result = unite_separately( gme, bodies, new_body_list, keep_old );
06484 
06485   if( result == CUBIT_FAILURE )
06486     PRINT_ERROR("UNITE failed\n");
06487 
06488   return result;
06489 }
06490 
06491 CubitStatus
06492 GeometryModifyTool::unite_separately( GeometryModifyEngine *gme_ptr,
06493                                       DLIList<Body*> &bodies,
06494                                       DLIList<Body*> &new_body_list,
06495                                       bool keep_old )
06496 {
06497   // Cubit can't mesh mixed sheet/solid bodies that are united together. Sort
06498   // based on these types.
06499   int i;
06500   Body *body_ptr;
06501   DLIList<Body*> solid_body_list;
06502   DLIList<Body*> sheet_body_list;
06503   bodies.reset();
06504   for( i=bodies.size(); i--; )
06505   {
06506     body_ptr = bodies.get_and_step();
06507 
06508     if( body_ptr->is_sheet_body() )
06509       sheet_body_list.append( body_ptr );
06510     else
06511       solid_body_list.append( body_ptr );
06512   }
06513 
06514   if( sheet_body_list.size() == 1 && solid_body_list.size() == 1 )
06515   {
06516     PRINT_ERROR( "Cannot unite solid and sheet bodies together\n" );
06517     return CUBIT_FAILURE;
06518   }
06519 
06520   // Setup undo
06521   if( CubitUndo::get_undo_enabled() )
06522   {
06523     if( keep_old )
06524       CubitUndo::save_state();
06525     else
06526       CubitUndo::save_state_with_cubit_file( bodies );
06527   }
06528 
06529   // Unite solids with each other, and sheets with each other separately
06530   CubitStatus result1 = CUBIT_SUCCESS;
06531   CubitStatus result2 = CUBIT_SUCCESS;
06532   if( solid_body_list.size() > 1 )
06533     result1 = unite_private( gme_ptr, solid_body_list, new_body_list, keep_old );
06534   if( sheet_body_list.size() > 1 )
06535     result2 = unite_private( gme_ptr, sheet_body_list, new_body_list, keep_old );
06536 
06537   // Finish undo
06538   if( CubitUndo::get_undo_enabled() )
06539   {
06540     if( new_body_list.size() )
06541       CubitUndo::note_result_bodies( new_body_list );
06542     else
06543       CubitUndo::remove_last_undo();
06544   }
06545 
06546   // Return success if both unites successful
06547   if( result1 == CUBIT_SUCCESS && result2 == CUBIT_SUCCESS )
06548     return CUBIT_SUCCESS;
06549 
06550   // Return success if either unite was successful
06551   if( ( solid_body_list.size() > 1 && result1 == CUBIT_SUCCESS ) ||
06552       ( sheet_body_list.size() > 1 && result2 == CUBIT_SUCCESS ) )
06553   {
06554     // Give warning if one or the other failed
06555     if( result1 == CUBIT_FAILURE )
06556       PRINT_WARNING( "Unite of solid volumes failed\n" );
06557     if( result2 == CUBIT_FAILURE )
06558       PRINT_WARNING( "Unite of sheet bodies failed\n" );
06559 
06560     return CUBIT_SUCCESS;
06561   }
06562 
06563   return CUBIT_FAILURE;
06564 }
06565 
06566 CubitStatus
06567 GeometryModifyTool::unite_all( GeometryModifyEngine *gme_ptr,
06568                                DLIList<Body*> &bodies,
06569                                DLIList<Body*> &new_body_list,
06570                                bool keep_old )
06571 {
06572   // Setup undo
06573   if( CubitUndo::get_undo_enabled() )
06574   {
06575     if( keep_old )
06576       CubitUndo::save_state();
06577     else
06578       CubitUndo::save_state_with_cubit_file( bodies );
06579   }
06580 
06581   // Unite solids with each other, and sheets with each other separately
06582   CubitStatus result = unite_private( gme_ptr, bodies, new_body_list, keep_old );
06583 
06584   // Finish undo
06585   if( CubitUndo::get_undo_enabled() )
06586   {
06587     if( new_body_list.size() )
06588       CubitUndo::note_result_bodies( new_body_list );
06589     else
06590       CubitUndo::remove_last_undo();
06591   }
06592 
06593   return result;
06594 }
06595 
06596 // Private workhorse function for unite
06597 CubitStatus
06598 GeometryModifyTool::unite_private( GeometryModifyEngine *gme_ptr,
06599                                    DLIList<Body*> &body_list,
06600                                    DLIList<Body*> &new_body_list,
06601                                    bool keep_old )
06602 {
06603   if( !body_list.size() )
06604     return CUBIT_SUCCESS;
06605 
06606   int i, j;
06607   Body *body_ptr;
06608   CubitStatus result;
06609 
06610   // Give 1st body all the names of all bodies being united
06611   std::list<CubitString> names_list;
06612   DLIList<CubitString> entity_names;
06613 
06614   body_list.reset();
06615   for( i=body_list.size(); i--; )
06616   {
06617     body_ptr = body_list.get_and_step();
06618 
06619     // See if body has names
06620     if( body_ptr->num_names() )
06621     {
06622       // Put the names in a list
06623       body_ptr->entity_names( entity_names );
06624       entity_names.reset();
06625 
06626       // Loop through names
06627       for( j=entity_names.size(); j--; )
06628         names_list.push_back( entity_names.get_and_step() );
06629 
06630       entity_names.clean_out();
06631       body_ptr->remove_entity_names();
06632     }
06633   }
06634 
06635   do_attribute_setup();
06636 
06637   DLIList<TopologyEntity*> entity_list(body_list.size());
06638   DLIList<TopologyBridge*> bridge_list(body_list.size());
06639   body_list.reset();
06640   for( i=body_list.size(); i--; )
06641     entity_list.append_unique(body_list.get_and_step());
06642   common_modify_engine( entity_list, bridge_list );
06643 
06644   DLIList<BodySM*> body_sm_list(body_list.size());
06645   CAST_LIST(bridge_list, body_sm_list, BodySM);
06646 
06647   push_attributes_before_modify(body_sm_list);
06648 
06649   DLIList<int> merged_surface_ids;
06650   DLIList<int> merged_curve_ids;
06651 
06652   get_merged_curve_and_surface_ids( body_list, merged_surface_ids, merged_curve_ids );
06653 
06654   DLIList<BodySM*> new_body_sm_list;
06655   result = unite( body_sm_list, new_body_sm_list, keep_old );
06656 
06657   restore_vg_after_modify( new_body_sm_list, body_list, gme_ptr );
06658   remove_pushed_attributes( new_body_sm_list, body_list );
06659 
06660   DLIList<Body*> result_list;
06661   if( !finish_sm_op(body_list, new_body_sm_list, result_list) )
06662     result = CUBIT_FAILURE;
06663 
06664   if( keep_old == CUBIT_FALSE )
06665     fixup_merged_entities( merged_surface_ids, merged_curve_ids );
06666 
06667   do_attribute_cleanup();
06668 
06669   if( result )
06670   {
06671     new_body_list += result_list;
06672 
06673     for( j=result_list.size(); j--; )
06674     {
06675       //Add names to 1st body
06676       std::list<CubitString>::iterator iter, end = names_list.end();
06677       for (iter = names_list.begin(); iter != end; ++iter)
06678         result_list.get_and_step()->entity_name( *iter );
06679     }
06680   }
06681 
06682   return result;
06683 }
06684 
06685 CubitStatus GeometryModifyTool::chop( DLIList<Body*> &bodies,
06686                                       DLIList<Body*> &intersectBodies,
06687                                       DLIList<Body*> &outsideBodies,
06688                                       Body*& leftoversBody,
06689                                       bool keep_old,
06690                                       bool nonreg )
06691 {
06692    leftoversBody = 0;
06693    if (bodies.size() <= 1)
06694    {
06695       PRINT_WARNING("There is only one body in the list. Nothing modified\n");
06696       return CUBIT_FAILURE;
06697    }
06698    if (!okay_to_modify( bodies, "CHOP" ))
06699      return CUBIT_FAILURE;
06700 
06701   int i;
06702   const int count = bodies.size();
06703   DLIList<Body*> original_body_list = bodies;
06704   DLIList<TopologyEntity*> entity_list(count);
06705   DLIList<TopologyBridge*> bridge_list(count);
06706   bodies.reset();
06707   for (i = bodies.size(); i--; )
06708     entity_list.append_unique(bodies.get_and_step());
06709   GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
06710 
06711   if ( !gme )
06712   {
06713       PRINT_ERROR("Performing CHOP with volumes containing geometry\n"
06714                   " from different modeling engines is not allowed.\n"
06715                   "Delete uncommon geometry on these volumes before operation.\n\n");
06716       return CUBIT_FAILURE;
06717   }
06718 
06719    DLIList<BodySM*> body_sm_list;
06720    CAST_LIST( bridge_list, body_sm_list, BodySM );
06721    DLIList<BodySM*> intersect_bodies, outside_bodies;
06722    BodySM *leftovers_body = 0;
06723 
06724    if( CubitUndo::get_undo_enabled() )
06725    {
06726      if( keep_old )
06727        CubitUndo::save_state();
06728      else
06729      {
06730        //Get all the bodies associated with the vertex
06731        CubitUndo::save_state_with_cubit_file( bodies );
06732      }
06733    }
06734 
06735    DLIList<int> merged_surface_ids;
06736    DLIList<int> merged_curve_ids;
06737    DLIList<Body*> tmp_bodies(1);
06738    tmp_bodies.append( bodies.get() );
06739    if( keep_old == CUBIT_FALSE )
06740      get_merged_curve_and_surface_ids( tmp_bodies, merged_surface_ids, merged_curve_ids );
06741 
06742    do_attribute_setup();
06743 
06744    // Push attributes down onto the blank body (first one in list).
06745    DLIList<BodySM*> tmp_body_sm_list;
06746    body_sm_list.reset();
06747    tmp_body_sm_list.append(body_sm_list.get());
06748    push_attributes_before_modify(tmp_body_sm_list);
06749 
06750    CubitStatus result = gme->chop( body_sm_list, intersect_bodies,
06751                           outside_bodies, leftovers_body, keep_old, nonreg );
06752 
06753    if( result == CUBIT_FAILURE )
06754    {
06755      if( CubitUndo::get_undo_enabled() )
06756        CubitUndo::remove_last_undo();
06757 
06758      PRINT_ERROR("CHOP failed\n");
06759      remove_pushed_attributes(tmp_body_sm_list, tmp_bodies);
06760      do_attribute_cleanup();
06761      return CUBIT_FAILURE;
06762    }
06763 
06764    DLIList<BodySM*> all_sms = intersect_bodies;
06765    all_sms += outside_bodies;
06766 
06767    restore_vg_after_modify(all_sms, tmp_bodies, gme);
06768    remove_pushed_attributes(all_sms, tmp_bodies);
06769 
06770    DLIList<Body*> result_bodies;
06771 
06772    body_sm_list.clean_out();
06773    body_sm_list += intersect_bodies;
06774 
06775    CubitStatus stat = finish_sm_op(bodies, body_sm_list, result_bodies);
06776 
06777    if( CubitUndo::get_undo_enabled() )
06778    {
06779      if( stat == CUBIT_SUCCESS )
06780        CubitUndo::note_result_bodies( result_bodies );
06781      else
06782        CubitUndo::remove_last_undo();
06783    }
06784 
06785    if( stat == CUBIT_FAILURE )
06786    {
06787      if( CubitUndo::get_undo_enabled() )
06788        CubitUndo::remove_last_undo();
06789 
06790      PRINT_ERROR("CHOP failed\n");
06791      do_attribute_cleanup();
06792      return CUBIT_FAILURE;
06793    }
06794    intersectBodies += result_bodies;
06795    bodies.clean_out();
06796 
06797    body_sm_list.clean_out();
06798    body_sm_list += outside_bodies;
06799    result_bodies.clean_out();
06800    if (!finish_sm_op(bodies, body_sm_list, result_bodies))
06801    {
06802      if( CubitUndo::get_undo_enabled() )
06803        CubitUndo::remove_last_undo();
06804 
06805      PRINT_ERROR("CHOP failed\n");
06806      do_attribute_cleanup();
06807      return CUBIT_FAILURE;
06808    }
06809    outsideBodies += result_bodies;
06810 
06811    if( leftovers_body )
06812    {
06813      body_sm_list.clean_out();
06814      body_sm_list.append( leftovers_body );
06815      result_bodies.clean_out();
06816      if (!finish_sm_op(bodies, body_sm_list, result_bodies))
06817      {
06818        if( CubitUndo::get_undo_enabled() )
06819          CubitUndo::remove_last_undo();
06820 
06821        PRINT_ERROR("CHOP failed\n");
06822        do_attribute_cleanup();
06823        return CUBIT_FAILURE;
06824      }
06825      leftoversBody = result_bodies.get();
06826 
06827    }
06828 
06829    if( keep_old == CUBIT_FALSE )
06830      fixup_merged_entities( merged_surface_ids, merged_curve_ids);
06831 
06832   if( CubitUndo::get_undo_enabled() )
06833   {
06834     if( leftoversBody )
06835     {
06836       DLIList<Body*> tmp_list(1);
06837       tmp_list.append( leftoversBody );
06838       CubitUndo::note_result_bodies( tmp_list );
06839     }
06840     CubitUndo::note_result_bodies( intersectBodies );
06841     CubitUndo::note_result_bodies( outsideBodies );
06842   }
06843 
06844   do_attribute_cleanup();
06845   return CUBIT_SUCCESS;
06846 }
06847 
06848 CubitStatus GeometryModifyTool::hollow( DLIList<Body*>& bodies,
06849                                         DLIList<RefFace*> faces_to_remove,
06850                                         DLIList<Body*>& new_bodies,
06851                                         double depth)
06852 {
06853   if (bodies.size() <= 0 || faces_to_remove.size() <= 0)
06854   {
06855      PRINT_WARNING("Needs at least one body and one face. Nothing modified\n");
06856      return CUBIT_FAILURE;
06857   }
06858 
06859   if (!okay_to_modify( bodies, "HOLLOW" ))
06860     return CUBIT_FAILURE;
06861 
06862   // Get the GeometryEngine for each Body of the list to check
06863   // if they are the same and if they are GeometryModifyEngine
06864 
06865   const int count = bodies.size();
06866   DLIList<TopologyEntity*> entity_list(count);
06867   DLIList<TopologyBridge*> bridge_list(count);
06868   CAST_LIST_TO_PARENT(bodies, entity_list);
06869   GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
06870 
06871   if (!gme)
06872   {
06873      PRINT_ERROR("Performing THICKEN with volumes containing geometry\n"
06874                  " from different modeling engines is not allowed.\n"
06875                  "Delete uncommon geometry on these volumes before operation.\n\n");
06876      return CUBIT_FAILURE;
06877   }
06878 
06879   DLIList<BodySM*> new_sms(count);
06880   DLIList<BodySM*> body_sms(count);
06881   CAST_LIST(bridge_list, body_sms, BodySM);
06882 
06883   if( CubitUndo::get_undo_enabled() )
06884   {
06885     CubitUndo::save_state_with_cubit_file( bodies );
06886   }
06887 
06888   DLIList <Surface*> surfs_to_remove;
06889   for(int i = 0 ; i < faces_to_remove.size(); i++)
06890   {
06891     Surface* surf = faces_to_remove.get_and_step()->get_surface_ptr();
06892     if(surf)
06893       surfs_to_remove.append(surf);
06894   }
06895 
06896 
06897   DLIList<int> merged_surface_ids;
06898   DLIList<int> merged_curve_ids;
06899   get_merged_curve_and_surface_ids( bodies, merged_surface_ids, merged_curve_ids );
06900   do_attribute_setup();
06901 
06902   // Push attributes down onto the bodies to be hollowed
06903   push_attributes_before_modify( body_sms );
06904 
06905   CubitStatus result = gme->hollow( body_sms, surfs_to_remove, new_sms, depth);
06906 
06907    if( result == CUBIT_FAILURE )
06908    {
06909      if( CubitUndo::get_undo_enabled() )
06910        CubitUndo::remove_last_undo();
06911 
06912      PRINT_ERROR("Hollow failed\n");
06913      remove_pushed_attributes(body_sms, bodies);
06914      do_attribute_cleanup();
06915      return CUBIT_FAILURE;
06916    }
06917 
06918   // check for resued entities, they have been moved and we need to notify observers
06919   DLIList<RefEntity*> entities_to_update;
06920   int i;
06921   for(i=0; i<new_sms.size(); i++)
06922   {
06923     BodySM* bodysm = new_sms.get_and_step();
06924     DLIList<TopologyBridge*> to_check;
06925     DLIList<TopologyBridge*> tmp;
06926     DLIList<Surface*> surfs;
06927     bodysm->surfaces(surfs);
06928     DLIList<Curve*> curves;
06929     bodysm->curves(curves);
06930     DLIList<TBPoint*> points;
06931     bodysm->points(points);
06932     to_check.append(bodysm);
06933     to_check.append(bodysm->lump());
06934     CAST_LIST_TO_PARENT(surfs, tmp);
06935     to_check += tmp;
06936     CAST_LIST_TO_PARENT(curves, tmp);
06937     to_check += tmp;
06938     CAST_LIST_TO_PARENT(points, tmp);
06939     to_check += tmp;
06940 
06941     int k;
06942     for(k=0; k<to_check.size(); k++)
06943       if(BridgeManager* m = to_check.get_and_step()->bridge_manager())
06944         if(TopologyEntity* t = m->topology_entity())
06945           entities_to_update.append(CAST_TO(t, RefEntity));
06946 
06947   }
06948 
06949   restore_vg_after_modify( new_sms, bodies, gme );
06950   remove_pushed_attributes( new_sms, bodies );
06951 
06952   result = finish_sm_op(bodies, new_sms, new_bodies);
06953   fixup_merged_entities( merged_surface_ids, merged_curve_ids);
06954 
06955   if (CUBIT_FAILURE == result) {
06956     if( CubitUndo::get_undo_enabled() )
06957       CubitUndo::remove_last_undo();
06958 
06959     PRINT_ERROR("Hollow failed\n");
06960     do_attribute_cleanup();
06961     return CUBIT_FAILURE;
06962   }
06963   else if( CubitUndo::get_undo_enabled() ) {
06964     CubitUndo::note_result_bodies( new_bodies );
06965   }
06966 
06967   do_attribute_cleanup();
06968   return CUBIT_SUCCESS;
06969 }
06970 
06971 CubitStatus GeometryModifyTool::thicken( DLIList<Body*>& bodies,
06972                                          DLIList<Body*>& new_bodies,
06973                                          double depth,
06974                                          bool both )
06975 {
06976   if (bodies.size() <= 0)
06977   {
06978      PRINT_WARNING("There is only one body in the list. Nothing modified\n");
06979      return CUBIT_FAILURE;
06980   }
06981 
06982   if (!okay_to_modify( bodies, "THICKEN" ))
06983     return CUBIT_FAILURE;
06984 
06985   // Get the GeometryEngine for each Body of the list to check
06986   // if they are the same and if they are GeometryModifyEngine
06987 
06988   const int count = bodies.size();
06989   DLIList<TopologyEntity*> entity_list(count);
06990   DLIList<TopologyBridge*> bridge_list(count);
06991   CAST_LIST_TO_PARENT(bodies, entity_list);
06992   GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
06993 
06994   if (!gme)
06995   {
06996      PRINT_ERROR("Performing THICKEN with volumes containing geometry\n"
06997                  " from different modeling engines is not allowed.\n"
06998                  "Delete uncommon geometry on these volumes before operation.\n\n");
06999      return CUBIT_FAILURE;
07000   }
07001 
07002   if( CubitUndo::get_undo_enabled() )
07003     CubitUndo::save_state_with_cubit_file( bodies );
07004 
07005   DLIList<BodySM*> new_sms(count);
07006   DLIList<BodySM*> body_sms(count);
07007   CAST_LIST(bridge_list, body_sms, BodySM);
07008   CubitStatus result = gme->thicken( body_sms, new_sms, depth, both);
07009 
07010   // check for resued entities, they have been moved and we need to notify observers
07011   DLIList<RefEntity*> entities_to_update;
07012   int i;
07013   for(i=0; i<new_sms.size(); i++)
07014   {
07015     BodySM* bodysm = new_sms.get_and_step();
07016     DLIList<TopologyBridge*> to_check;
07017     DLIList<TopologyBridge*> tmp;
07018     DLIList<Surface*> surfs;
07019     bodysm->surfaces(surfs);
07020     DLIList<Curve*> curves;
07021     bodysm->curves(curves);
07022     DLIList<TBPoint*> points;
07023     bodysm->points(points);
07024     to_check.append(bodysm);
07025     to_check.append(bodysm->lump());
07026     CAST_LIST_TO_PARENT(surfs, tmp);
07027     to_check += tmp;
07028     CAST_LIST_TO_PARENT(curves, tmp);
07029     to_check += tmp;
07030     CAST_LIST_TO_PARENT(points, tmp);
07031     to_check += tmp;
07032 
07033     int k;
07034     for(k=0; k<to_check.size(); k++)
07035       if(BridgeManager* m = to_check.get_and_step()->bridge_manager())
07036         if(TopologyEntity* t = m->topology_entity())
07037           entities_to_update.append(CAST_TO(t, RefEntity));
07038 
07039   }
07040 
07041   if (!finish_sm_op(bodies, new_sms, new_bodies))
07042     result = CUBIT_FAILURE;
07043 
07044   if( CubitUndo::get_undo_enabled() )
07045   {
07046     if( new_bodies.size() )
07047       CubitUndo::note_result_bodies( new_bodies );
07048     else
07049       CubitUndo::remove_last_undo();
07050   }
07051 
07052   // Update graphics
07053   while (entities_to_update.size())
07054   {
07055     RefEntity* entity = entities_to_update.pop();
07056     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entity));
07057   }
07058 
07059   return result;
07060 }
07061 
07062 
07063 CubitStatus GeometryModifyTool::validate_normals(DLIList<Body*>& bodies,
07064                                                  RefFace *surf_ref,
07065                                                  bool reverse)
07066 {
07067    if (bodies.size() <= 0)
07068    {
07069       PRINT_WARNING("There are no entities in the list. Nothing modified\n");
07070       return CUBIT_FAILURE;
07071    }
07072 
07073    DLIList<RefEntity*> temp;
07074    CAST_LIST_TO_PARENT(bodies, temp);
07075    if ( !same_modify_engine(temp, CUBIT_TRUE))
07076    {
07077       PRINT_ERROR("Performing VALIDATE NORMALS with volumes containing geometry\n"
07078             "      from different modeling engines is not allowed. Delete uncommon\n"
07079             "      geometry on these volumes before operation.\n\n");
07080       return CUBIT_FAILURE;
07081    }
07082 
07083    // Get the GeometryEngine for each Body of the list to check
07084    // if they are the same and if they are GeometryModifyEngine
07085    GeometryModifyEngine* gePtr1 = get_engine(bodies.get());
07086    GeometryModifyEngine* gePtr2;
07087    Body* Body_ptr = NULL;
07088    bodies.reset();
07089    for( int i = bodies.size(); i > 0; i--)
07090    {
07091       Body_ptr = bodies.get_and_step();
07092       gePtr2 = get_engine(Body_ptr);
07093       if (gePtr1 != gePtr2)
07094       {
07095          PRINT_ERROR("In GeometryModifyTool::validate_normals\n"
07096             "  Volumes are associated with different GMEs. \n");
07097          return CUBIT_FAILURE;
07098       }
07099       if ( gePtr2 == NULL)
07100       {
07101          PRINT_ERROR("In GeometryModifyTool::validate_normals\n"
07102             "       Body %d is not associated with a SME.\n",
07103             Body_ptr->id());
07104          return CUBIT_FAILURE;
07105       }
07106    }
07107 
07108 
07109    DLIList<RefFace*> ref_face_list;
07110    DLIList<RefFace*> free_face_list;
07111    DLIList<RefFace*> bad_face_list;
07112 
07113    //gather all the faces from all the bodies
07114    bodies.reset();
07115    for( int i=bodies.size(); i--; )
07116    {
07117      Body* BodyPtr = bodies.get_and_step();
07118      BodyPtr->ref_faces(free_face_list);
07119    }
07120 
07121    RefFace *ref_face_ptr;
07122    RefFace *inter_face_ptr;
07123 
07124    if(surf_ref != NULL)   // getting the starting surface
07125    {
07126      ref_face_ptr = surf_ref;
07127    }
07128    else
07129    {
07130      ref_face_ptr = free_face_list.get_and_step();
07131    }
07132 
07133    ref_face_list.append(ref_face_ptr);
07134    free_face_list.remove(ref_face_ptr);
07135    free_face_list.reset();
07136 
07137    while(free_face_list.size())
07138    {
07139       DLIList<RefEdge*> curve_list;
07140       ref_face_ptr->ref_edges(curve_list);
07141       free_face_list.reset();
07142       for(int jj=free_face_list.size(); jj > 0; jj--)  // getting a new searching surface
07143       {
07144          inter_face_ptr = free_face_list.get_and_step();
07145          DLIList<RefEdge*> inter_curve_list;
07146          inter_face_ptr->ref_edges(inter_curve_list);
07147          curve_list.reset();
07148         // PRINT_INFO("base face %d working on face %d\n", ref_face_ptr->id(),inter_face_ptr->id());
07149 
07150          for (int k= curve_list.size(); k > 0; k--)  // looping through all of the surface curves
07151          {
07152             RefEdge *ref_check_curve = curve_list.step_and_get();
07153             inter_curve_list.reset();
07154 
07155             for (int kk = inter_curve_list.size(); kk > 0; kk--)
07156             {
07157                RefEdge *check_curve = inter_curve_list.step_and_get();
07158 
07159                if(ref_check_curve == check_curve)  // finding if a surface is connected
07160                {
07161                   DLIList<CoEdge*> coedge_list;
07162                   check_curve->co_edges(coedge_list);
07163 
07164                   CoEdge* first_coedge = coedge_list.get_and_step();
07165                   CoEdge* second_coedge = coedge_list.get_and_step();
07166 
07167                   if((first_coedge->get_sense() == second_coedge->get_sense() &&
07168                      !bad_face_list.is_in_list(ref_face_ptr) ) ||
07169                      (first_coedge->get_sense() != second_coedge->get_sense() &&
07170                      bad_face_list.is_in_list(ref_face_ptr) ))    // finding if a surface has a fliped normal
07171                   {
07172                      bad_face_list.append(inter_face_ptr);
07173                      PRINT_INFO("Surface %d is not consistent\n", inter_face_ptr->id());
07174                   }
07175 
07176                   ref_face_list.append(inter_face_ptr);  // adding to the searched list
07177                   free_face_list.remove(inter_face_ptr); // removing from the unsearched list
07178                }
07179 
07180             }
07181 
07182          }
07183 
07184       }
07185 
07186       ref_face_list.remove(ref_face_ptr);     // removeing from the searched list
07187       ref_face_list.last();
07188       if(ref_face_list.size() <= 0)
07189       {
07190          PRINT_ERROR("In GeometryModifyTool::validate_normals\n"
07191             "       all surfaces must be connected\n");
07192          return CUBIT_FAILURE;
07193       }
07194       ref_face_ptr = ref_face_list.get();
07195   }
07196 
07197   if (reverse && bad_face_list.size())
07198   {
07199      //CubitStatus result = gePtr1->flip_normals(bad_face_list);
07200      CubitStatus result = GeometryModifyTool::instance()->reverse(bad_face_list);
07201      if ( result == CUBIT_FAILURE )
07202      {
07203        return CUBIT_FAILURE;
07204     }
07205   }
07206   else if(!bad_face_list.size())
07207   {
07208     PRINT_INFO("All surfaces are consistent\n");
07209   }
07210   return CUBIT_SUCCESS;
07211 }
07212 
07213 
07214 
07215 CubitStatus GeometryModifyTool::subtract( Body* tool_body, DLIList<Body*> &from_bodies,
07216                                           DLIList<Body*> &new_bodies,
07217                                           bool imprint,
07218                                           bool keep_old )
07219 {
07220   DLIList<Body*> temp_body_list;
07221   temp_body_list.append(tool_body);
07222   return subtract(temp_body_list, from_bodies, new_bodies, imprint, keep_old);
07223 }
07224 
07225 
07226 CubitStatus GeometryModifyTool::subtract( DLIList<Body*>  &tool_body_list,
07227                                           DLIList<Body*> &from_bodies,
07228                                           DLIList<Body*> &new_bodies,
07229                                           bool imprint,
07230                                           bool keep_old )
07231 {
07232    if(tool_body_list.size() == 0 )
07233        return CUBIT_FAILURE;
07234    if(from_bodies.size() == 0 )
07235        return CUBIT_FAILURE;
07236    DLIList<Body*> tem_bodies(tool_body_list);
07237 
07238    // cannot subtract from self
07239    int old_size = from_bodies.size();
07240    from_bodies -= tool_body_list;
07241    if (from_bodies.size() != old_size)
07242    {
07243      PRINT_WARNING("Cannot subtract body from itself.  Ignoring \"from\" body.\n");
07244      if (!from_bodies.size())
07245        return CUBIT_FAILURE;
07246    }
07247 
07248    tem_bodies += from_bodies;
07249    if (!okay_to_modify( tem_bodies, "SUBTRACT" ))
07250      return CUBIT_FAILURE;
07251 
07252    DLIList<BodySM*> tool_sms(tool_body_list.size());
07253    DLIList<BodySM*> from_sms(from_bodies.size());
07254    GeometryModifyEngine* gme = common_modify_engine( tool_body_list, tool_sms );
07255    GeometryModifyEngine* gme2 = common_modify_engine( from_bodies, from_sms );
07256    if (!gme || gme != gme2)
07257    {
07258       PRINT_ERROR("Performing SUBTRACTION with volumes containing geometry\n"
07259                   "from different modeling engines is not allowed.\n"
07260                   "Delete uncommon geometry on these volumes before operation.\n\n");
07261       return CUBIT_FAILURE;
07262    }
07263 
07264    if( CubitUndo::get_undo_enabled() )
07265    {
07266      if( keep_old )
07267        CubitUndo::save_state();
07268      else
07269      {
07270        //Get all the bodies associated with the vertex
07271        DLIList<Body*> bodies;
07272        bodies += tool_body_list;
07273        bodies += from_bodies;
07274        CubitUndo::save_state_with_cubit_file( bodies );
07275      }
07276    }
07277 
07278    DLIList<int> merged_surface_ids;
07279    DLIList<int> merged_curve_ids;
07280    if( keep_old == CUBIT_FALSE )
07281      get_merged_curve_and_surface_ids( from_bodies, merged_surface_ids, merged_curve_ids );
07282 
07283 
07284      // Do the subtract operation
07285    DLIList<BodySM*> new_sms;
07286    CubitStatus result = gme->subtract(tool_sms, from_sms, new_sms, imprint, keep_old );
07287 
07288    if( CubitUndo::get_undo_enabled() && result == CUBIT_FAILURE )
07289      CubitUndo::remove_last_undo();
07290 
07291    CubitStatus result2 = finish_sm_op(tem_bodies, new_sms, new_bodies);
07292 
07293    if( CubitUndo::get_undo_enabled() )
07294    {
07295      if( result == CUBIT_SUCCESS )
07296        CubitUndo::note_result_bodies( new_bodies );
07297      else
07298        CubitUndo::remove_last_undo();
07299    }
07300 
07301    if ( result == CUBIT_FAILURE || result2 == CUBIT_FAILURE)
07302    {
07303      PRINT_ERROR("Subtract FAILED\n" );
07304      return CUBIT_FAILURE;
07305    }
07306 
07307    if( keep_old == CUBIT_FALSE )
07308      fixup_merged_entities( merged_surface_ids, merged_curve_ids);
07309 
07310    return CUBIT_SUCCESS;
07311 }
07312 
07313 CubitStatus GeometryModifyTool::intersect( DLIList<Body*> &from_bodies,
07314                                            DLIList<Body*> &new_bodies,
07315                                            bool keep_old,
07316                                            bool preview)
07317 {
07318   DLIList<Body*> tem_bodies = from_bodies;
07319   if (!okay_to_modify( tem_bodies, "INTERSECT" ))
07320     return CUBIT_FAILURE;
07321 
07322   GfxPreview::clear();
07323 
07324   DLIList<BodySM*> from_sm_list(tem_bodies.size());
07325   GeometryModifyEngine* engine = common_modify_engine(tem_bodies, from_sm_list);
07326   if ( NULL == engine )
07327   {
07328     PRINT_ERROR("Performing INTERSECTION with volumes containing geometry\n"
07329                 "from different modeling engines is not allowed.\n"
07330                 "Delete uncommon geometry on these volumes before operation.\n\n");
07331     return CUBIT_FAILURE;
07332   }
07333 
07334   if( !preview && CubitUndo::get_undo_enabled() )
07335   {
07336     if( keep_old )
07337       CubitUndo::save_state();
07338     else
07339       CubitUndo::save_state_with_cubit_file( from_bodies );
07340   }
07341 
07342   DLIList<int> merged_surface_ids;
07343   DLIList<int> merged_curve_ids;
07344   if( !preview && (keep_old == CUBIT_FALSE) )
07345     get_merged_curve_and_surface_ids( from_bodies, merged_surface_ids, merged_curve_ids );
07346 
07347   GeometryModifyEngine* gme_ptr = get_engine(from_sm_list.get());
07348   GeometryQueryEngine* gqe_ptr = gme_ptr->get_gqe();
07349 
07350   DLIList<BodySM*> all_new_bodysms;
07351   int i,j;
07352   for( i=0; i<from_sm_list.size(); i++ )
07353   {
07354     from_sm_list.reset();
07355     from_sm_list.step(i);
07356     BodySM *body1 = from_sm_list.get_and_step();
07357 
07358     for(j=i+1; j<from_sm_list.size(); j++ )
07359     {
07360       BodySM *body2 = from_sm_list.get_and_step();
07361 
07362       if( body1 == body2 )
07363         continue;
07364 
07365       //copy the bodies
07366       BodySM *body1_copy = gme_ptr->copy_body( body1 );
07367       BodySM *body2_copy = gme_ptr->copy_body( body2 );
07368 
07369       DLIList<BodySM*> tmp_sm_list(1);
07370       tmp_sm_list.append( body2_copy );
07371       DLIList<BodySM*> new_sms;
07372 
07373       CubitStatus result =
07374           engine->intersect(body1_copy, tmp_sm_list, new_sms, true, preview );
07375 
07376       //delete the copies
07377       gqe_ptr->delete_solid_model_entities( body1_copy );
07378       gqe_ptr->delete_solid_model_entities( body2_copy );
07379 
07380       if (!preview)
07381       {
07382         if ( result == CUBIT_FAILURE || new_sms.size() == 0 )
07383         {
07384           RefEntity* ref_ent1 = dynamic_cast<RefEntity*>(body1->topology_entity());
07385           RefEntity* ref_ent2 = dynamic_cast<RefEntity*>(body2->topology_entity());
07386 
07387           PRINT_WARNING("INTERSECTION of %s with %s failed\n",
07388             ref_ent1->entity_name().c_str(),
07389             ref_ent2->entity_name().c_str() );
07390           continue;
07391 
07392         }
07393 
07394         all_new_bodysms += new_sms;
07395       }
07396     }
07397   }
07398 
07399   if (!preview)
07400   {
07401     //now make all the RefEntities
07402     all_new_bodysms.reset();
07403     for( i=all_new_bodysms.size(); i--; )
07404     {
07405       Body *new_body = GeometryQueryTool::instance()->make_Body(all_new_bodysms.get_and_step());
07406       if( new_body )
07407         new_bodies.append( new_body );
07408     }
07409 
07410     if( CubitUndo::get_undo_enabled() )
07411     {
07412       if( all_new_bodysms.size() )
07413         CubitUndo::note_result_bodies( new_bodies );
07414       else
07415         CubitUndo::remove_last_undo();
07416     }
07417 
07418     if( keep_old == CUBIT_FALSE )
07419       fixup_merged_entities( merged_surface_ids, merged_curve_ids);
07420   }
07421 
07422   return CUBIT_SUCCESS;
07423 }
07424 
07425 
07426 
07427 CubitStatus GeometryModifyTool::intersect( Body *tool_body_ptr,
07428                                            DLIList<Body*> &from_bodies,
07429                                            DLIList<Body*> &new_bodies,
07430                                            bool keep_old,
07431                                            bool preview)
07432 {
07433   if(tool_body_ptr == NULL )
07434     return CUBIT_FAILURE;
07435   if(from_bodies.size() == 0 || from_bodies.get() == NULL )
07436     return CUBIT_FAILURE;
07437 
07438   GfxPreview::clear();
07439 
07440   DLIList<Body*> tem_bodies = from_bodies;
07441   tem_bodies.append( tool_body_ptr );
07442   if (!okay_to_modify( tem_bodies, "INTERSECT" ))
07443     return CUBIT_FAILURE;
07444 
07445   DLIList<BodySM*> from_sm_list(tem_bodies.size());
07446   GeometryModifyEngine* engine = common_modify_engine(tem_bodies, from_sm_list);
07447   if ( NULL == engine )
07448   {
07449     PRINT_ERROR("Performing INTERSECTION with volumes containing geometry\n"
07450                 "from different modeling engines is not allowed.\n"
07451                 "Delete uncommon geometry on these volumes before operation.\n\n");
07452     return CUBIT_FAILURE;
07453   }
07454 
07455   BodySM* tool_sm = from_sm_list.pop();
07456 
07457 
07458   //cannot intersect tool with itself
07459   from_sm_list.remove_all_with_value( tool_sm );
07460   if( from_sm_list.size() == 0 )
07461   {
07462     PRINT_ERROR("Cannot intersect volume %d from itself\n",
07463                  tool_body_ptr->ref_volume()->id() );
07464     return CUBIT_FAILURE;
07465   }
07466 
07467   if( !preview && CubitUndo::get_undo_enabled() )
07468   {
07469     if( keep_old )
07470       CubitUndo::save_state();
07471     else
07472     {
07473       DLIList<Body*> bodies;
07474       bodies.append( tool_body_ptr );
07475       bodies += from_bodies;
07476       CubitUndo::save_state_with_cubit_file( bodies );
07477     }
07478   }
07479 
07480   DLIList<int> merged_surface_ids;
07481   DLIList<int> merged_curve_ids;
07482   if( !preview && (keep_old == CUBIT_FALSE) )
07483     get_merged_curve_and_surface_ids( from_bodies, merged_surface_ids, merged_curve_ids );
07484 
07485      // Do the intersect operation
07486   DLIList<BodySM*> new_sms;
07487   CubitStatus result =
07488       engine->intersect(tool_sm, from_sm_list, new_sms, keep_old, preview );
07489 
07490   if (!preview)
07491   {
07492     result = finish_sm_op(tem_bodies, new_sms, new_bodies);
07493 
07494     if( CubitUndo::get_undo_enabled() )
07495     {
07496       if( result == CUBIT_SUCCESS )
07497         CubitUndo::note_result_bodies( new_bodies );
07498       else
07499         CubitUndo::remove_last_undo();
07500     }
07501 
07502     if ( result == CUBIT_FAILURE )
07503     {
07504       PRINT_ERROR("Intersect FAILED\n" );
07505       return CUBIT_FAILURE;
07506     }
07507 
07508     if( keep_old == CUBIT_FALSE )
07509       fixup_merged_entities( merged_surface_ids, merged_curve_ids);
07510   }
07511 
07512   return CUBIT_SUCCESS;
07513 }
07514 
07515 CubitStatus GeometryModifyTool::imprint( DLIList<Body*> &from_body_list,
07516                                          DLIList<Body*> &new_body_list,
07517                                          CubitBoolean keep_old )
07518 {
07519   if( from_body_list.size() == 1 )
07520   {
07521     PRINT_WARNING("Need more than 1 body or volume to imprint.\n");
07522     return CUBIT_FAILURE;
07523   }
07524 
07525    if (get_group_imprint() == CUBIT_FALSE)
07526    {
07527      CubitStatus result = imprint_singly( from_body_list, new_body_list, keep_old );
07528      return result;
07529    }
07530 
07531      // Check the GeometryEngine for each of the Body's; check to
07532      // make sure they're all the same
07533    from_body_list.reset();
07534    if (!okay_to_modify( from_body_list, "IMPRINT" ))
07535      return CUBIT_FAILURE;
07536 
07537      //Check for repeats in each individual list and for overlap
07538      //between the two lists.
07539    from_body_list.uniquify_ordered();
07540 
07541    DLIList<BodySM*> from_sms(from_body_list.size()), new_sms;
07542    GeometryModifyEngine* gePtr1 = common_modify_engine(from_body_list, from_sms);
07543    if ( !gePtr1 )
07544    {
07545       PRINT_ERROR("Performing IMPRINT with volumes containing geometry\n"
07546                   "from different modeling engines is not allowed.\n"
07547                   "Delete uncommon geometry on these volumes before operation.\n\n");
07548       return CUBIT_FAILURE;
07549    }
07550 
07551    if( CubitUndo::get_undo_enabled() )
07552    {
07553      if( keep_old )
07554        CubitUndo::save_state();
07555      else
07556        CubitUndo::save_state_with_cubit_file( from_body_list );
07557    }
07558 
07559    int process_composites = 0;
07560    if(contains_composites(from_body_list))
07561      process_composites = 1;
07562 
07563    if(process_composites)
07564    {
07565       // Push virtual attributes down to solid model topology before
07566       // doing the imprint.
07567       do_attribute_setup();
07568       push_attributes_before_modify(from_sms);
07569       // This must be done after pushing the vg atts because it uses them.
07570       DLIList<TopologyBridge*> tb_list;
07571       CAST_LIST(from_sms, tb_list, TopologyBridge);
07572       push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
07573       push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
07574    }
07575 
07576    CubitStatus result =  gePtr1->imprint(from_sms, new_sms, keep_old);
07577 
07578    int i, j;
07579    if(process_composites)
07580    {
07581      if(result == CUBIT_SUCCESS)
07582      {
07583         // Analyze the results and adjust virtual attributes as necessary.
07584        DLIList<TopologyBridge*> tb_list;
07585        CAST_LIST(new_sms, tb_list, TopologyBridge);
07586         GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, from_body_list);
07587 
07588         // Clean up attributes.
07589         remove_imprint_attributes_after_modify(from_sms, new_sms);
07590 
07591         // Restore the virtual geometry.
07592         restore_vg_after_modify(new_sms, from_body_list, gePtr1);
07593      }
07594      remove_pushed_attributes(new_sms, from_body_list);
07595    }
07596 
07597    if (get_old_names() == CUBIT_FALSE)
07598    {
07599      if (!finish_sm_op(from_body_list, new_sms, new_body_list))
07600        result = CUBIT_FAILURE;
07601 
07602      if( CubitUndo::get_undo_enabled() )
07603      {
07604        if( result == CUBIT_SUCCESS )
07605          CubitUndo::note_result_bodies( new_body_list );
07606        else
07607          CubitUndo::remove_last_undo();
07608      }
07609 
07610      if(process_composites)
07611        do_attribute_cleanup();
07612 
07613      return result;
07614    }
07615 
07616    if(process_composites)
07617      do_attribute_cleanup();
07618 
07619    // If old_names is true, need to make sure things are deleted in
07620    // the correct order so that entities get the same @A type extension
07621    // on their names.
07622 
07623    // Update existing bodies.
07624    from_body_list.reset();
07625    for (i = from_body_list.size(); i--; )
07626    {
07627      Body* body = from_body_list.get();
07628      BodySM* body_sm = body->get_body_sm_ptr();
07629      if (!body_sm)
07630      {
07631        GeometryQueryTool::instance()->destroy_dead_entity(body);
07632        from_body_list.change_to(0);
07633      }
07634      else
07635      {
07636        remove_dead_entity_names(body);
07637        GeometryQueryTool::instance()->make_Body(body_sm);
07638      }
07639      from_body_list.step();
07640    }
07641 
07642       // Construct new bodies
07643    new_sms.reset();
07644    for (j = new_sms.size(); j--; )
07645    {
07646      BodySM* body_sm = new_sms.get_and_step();
07647      Body* body = GeometryQueryTool::instance()->make_Body(body_sm);
07648      new_body_list.append(body);
07649    }
07650    GeometryQueryTool::instance()->cleanout_deactivated_geometry();
07651 
07652    if( CubitUndo::get_undo_enabled() )
07653    {
07654      if( result == CUBIT_SUCCESS )
07655        CubitUndo::note_result_bodies( new_body_list );
07656      else
07657        CubitUndo::remove_last_undo();
07658    }
07659 
07660    return result;
07661 }
07662 
07663 CubitStatus GeometryModifyTool::scale( Body *&body,
07664                                       const CubitVector& point,
07665                                        const CubitVector& factors,
07666                                        bool check_to_transform,
07667                                        bool preview /*=false*/,
07668                                        bool reset_preview /*true*/)
07669 {
07670   if( check_to_transform )
07671     if (!GeometryQueryTool::instance()->okay_to_transform( body ))
07672       return CUBIT_FAILURE;
07673 
07674   DLIList<Body*> body_list;
07675   body_list.append(body);
07676   if (!okay_to_modify( body_list, "NON_UNIFORM_SCALE" ))
07677     return CUBIT_FAILURE;
07678 
07679   if(reset_preview)
07680     GfxPreview::clear();
07681 
07682   if (preview)
07683   {
07684     DLIList<RefEdge*> edges;
07685     body->ref_edges(edges);
07686 
07687     //set up the matrices
07688     CubitTransformMatrix pre_mat, scale_mat, post_mat;
07689     pre_mat.translate(-point);    
07690     scale_mat.scale_about_origin(factors);   
07691     post_mat.translate(point);
07692 
07693     for (int i = 0; i < edges.size(); i++)
07694     {
07695       GMem poly;
07696 
07697       if( CUBIT_SUCCESS == edges[i]->get_graphics(poly) )
07698       {
07699         poly.transform(pre_mat);
07700         poly.transform(scale_mat);
07701         poly.transform(post_mat);
07702         GfxPreview::draw_polyline(poly.point_list(), poly.point_list_size(), CUBIT_BLUE_INDEX);
07703       }
07704       else if( edges[i]->start_vertex() == edges[i]->end_vertex() )
07705       {       
07706         CubitVector tmp_pt = edges[i]->start_vertex()->coordinates();
07707         tmp_pt = pre_mat*tmp_pt;
07708         tmp_pt = scale_mat*tmp_pt;
07709         tmp_pt = post_mat*tmp_pt;          
07710         GfxPreview::draw_point( tmp_pt, CUBIT_BLUE_INDEX);
07711       }      
07712     }
07713     GfxPreview::flush();
07714     return CUBIT_SUCCESS;
07715   }
07716 
07717   do_attribute_setup();
07718 
07719   BodySM* bodysm = body->get_body_sm_ptr();
07720   DLIList<BodySM*> body_sm_list;
07721   body_sm_list.append(bodysm);
07722 
07723   push_attributes_before_modify(body_sm_list);
07724 
07725   GeometryModifyEngine* engine = get_engine( bodysm );
07726   CubitStatus result;
07727   if( !engine )
07728   {
07729     GeometryQueryEngine* tmp_engine = bodysm->get_geometry_query_engine();
07730     result = tmp_engine->translate( bodysm, -point );
07731     result = tmp_engine->scale( bodysm, factors );
07732     result = tmp_engine->translate( bodysm, point );
07733 
07734   }
07735   else
07736   {
07737     GeometryQueryEngine* tmp_engine = bodysm->get_geometry_query_engine();
07738     result = tmp_engine->translate( bodysm, -point );
07739     result = engine->scale( bodysm, factors );
07740     result = tmp_engine->translate( bodysm, point );
07741   }
07742 
07743   // The bodysm pointer may get changed depending on the underlying
07744   // engine.  Make sure to put the most current pointer in the list
07745   // for further processing.
07746   body_sm_list.clean_out();
07747   body_sm_list.append(bodysm);
07748   // The old body will probably have stale data at this point
07749   // so don't send it down for further processing.
07750   body_list.clean_out();
07751 
07752   restore_vg_after_modify( body_sm_list, body_list, engine );
07753   remove_pushed_attributes( body_sm_list, body_list );
07754 
07755   //for non-uniform scaling, topology can change...need to update stuff
07756   if( factors.x() != factors.y() ||
07757       factors.y() != factors.z() ||
07758       factors.z() != factors.x() )
07759     body = GeometryQueryTool::instance()->make_Body(bodysm);
07760 
07761   do_attribute_cleanup();
07762 
07763   if (result)
07764   {
07765 
07766     CubitTransformMatrix pre_mat;
07767     pre_mat.translate(-point);
07768 
07769     CubitTransformMatrix scale_mat;
07770     scale_mat.scale_about_origin(factors);
07771 
07772     CubitTransformMatrix post_mat;
07773     post_mat.translate(point);
07774     GeometryQueryTool::instance()->notify_intermediate_of_transform( body, pre_mat );
07775     GeometryQueryTool::instance()->notify_intermediate_of_transform( body, scale_mat );
07776     GeometryQueryTool::instance()->notify_intermediate_of_transform( body, post_mat );
07777     GeometryQueryTool::instance()->notify_observers_of_transform( body );
07778   }
07779   else
07780     PRINT_ERROR("Scale of %s (%s %d) failed.\n",
07781       body->entity_name().c_str(), body->class_name(), body->id() );
07782 
07783   return result;
07784 }
07785 
07786 
07787 
07788 CubitStatus GeometryModifyTool::imprint_singly( DLIList<Body*> &from_body_list,
07789                                                 DLIList<Body*> &new_body_list,
07790                                                 CubitBoolean keep_old )
07791 {
07792 
07793      // Check the GeometryEngine for each of the Body's; check to
07794      // make sure they're all the same
07795    from_body_list.reset();
07796    if (!okay_to_modify( from_body_list, "IMPRINT" ))
07797      return CUBIT_FAILURE;
07798 
07799      //Check for repeats in each individual list and for overlap
07800      //between the two lists.
07801    from_body_list.uniquify_ordered();
07802 
07803    DLIList<BodySM*> from_sms(from_body_list.size());
07804    GeometryModifyEngine* gePtr1 = common_modify_engine(from_body_list, from_sms);
07805    if ( !gePtr1 )
07806    {
07807       PRINT_ERROR("Performing IMPRINT with volumes containing geometry\n"
07808                   "from different modeling engines is not allowed.\n"
07809                   "Delete uncommon geometry on these volumes before operation.\n\n");
07810       return CUBIT_FAILURE;
07811    }
07812 
07813    CubitBoolean reset_new_ids = CUBIT_FALSE;
07814    if (get_new_ids() == CUBIT_FALSE) {
07815      PRINT_WARNING("New ids must be TRUE when group imprint FALSE; "
07816                    "setting new ids TRUE for this operation only.\n");
07817      set_new_ids(CUBIT_TRUE);
07818      reset_new_ids = CUBIT_TRUE;
07819    }
07820 
07821      // do the imprinting; bounding box should be checked in
07822      // SMEEngine function
07823    new_body_list = from_body_list;
07824    GeometryQueryTool* gqt = GeometryQueryTool::instance();
07825 
07826    if( CubitUndo::get_undo_enabled() )
07827    {
07828      if( keep_old )
07829        CubitUndo::save_state();
07830      else
07831        CubitUndo::save_state_with_cubit_file( from_body_list );
07832    }
07833 
07834    int i;
07835    for (i = 0; i < new_body_list.size(); i++) {
07836      for (int j = 1; j < new_body_list.size()-i; j++) {
07837        new_body_list.reset();
07838        new_body_list.step(i);
07839        Body *body_1 = new_body_list.get();
07840        Body *body_2 = new_body_list.next(j);
07841        Body *newBodyPtr1 = NULL;
07842        Body *newBodyPtr2 = NULL;
07843 
07844        if (body_1 == body_2) {
07845          PRINT_WARNING("Can't imprint a volume with itself.\n");
07846 
07847          if (reset_new_ids == CUBIT_TRUE) set_new_ids(CUBIT_FALSE);
07848 
07849          return CUBIT_FAILURE;
07850        }
07851 
07852        BodySM *new_sm_1, *new_sm_2;
07853        CubitStatus status = gePtr1->imprint(body_1->get_body_sm_ptr(),
07854                                             body_2->get_body_sm_ptr(),
07855                                             new_sm_1, new_sm_2,
07856                                             keep_old);
07857 
07858        if ( status != CUBIT_FAILURE &&
07859             (new_sm_1 != NULL ||
07860              new_sm_2 != NULL) )
07861        {
07862          from_body_list.reset();
07863          from_body_list.step(i);
07864 
07865            //put the new ones in the new list and
07866            //remove the olds ones.
07867          if ( new_sm_1 != NULL )
07868          {
07869            if (!body_1->get_body_sm_ptr())
07870              gqt->destroy_dead_entity(body_1);
07871            newBodyPtr1 = gqt->make_Body(new_sm_1);
07872            new_body_list.change_to(newBodyPtr1);
07873            from_body_list.change_to(0);
07874          }
07875          else
07876            gqt->make_Body(body_1->get_body_sm_ptr());
07877 
07878          new_body_list.step(j);
07879          from_body_list.step(j);
07880          if ( new_sm_2 != NULL )
07881          {
07882            if (!body_2->get_body_sm_ptr())
07883              gqt->destroy_dead_entity(body_2);
07884            newBodyPtr2 = gqt->make_Body(new_sm_2);
07885            new_body_list.change_to(newBodyPtr2);
07886            from_body_list.change_to(NULL);
07887          }
07888          else
07889            gqt->make_Body(body_2->get_body_sm_ptr());
07890        }
07891        gqt->cleanout_deactivated_geometry();
07892      }
07893    }
07894 
07895    from_body_list.remove_all_with_value(NULL);
07896    Body *temp_body;
07897    for (i = from_body_list.size(); i > 0; i--)
07898    {
07899      temp_body = from_body_list.get_and_step();
07900      while (new_body_list.move_to(temp_body)) new_body_list.remove();
07901    }
07902 
07903    if( CubitUndo::get_undo_enabled() )
07904    {
07905      if( new_body_list.size() )
07906        CubitUndo::note_result_bodies( new_body_list );
07907      else
07908        CubitUndo::remove_last_undo();
07909    }
07910 
07911    PRINT_INFO("\n");
07912    if( DEBUG_FLAG( 153 ) )
07913    {
07914      PRINT_INFO( "  New Body(ies) created:");
07915      new_body_list.reset();
07916      for (i = 0; i < new_body_list.size(); i++)
07917      {
07918        if (i != 0) PRINT_INFO( ",");
07919        PRINT_INFO( " %d", new_body_list.get_and_step()->id());
07920      }
07921      PRINT_INFO("\n");
07922      PRINT_INFO( "  Original Body(ies) retained:");
07923      from_body_list.reset();
07924      for (i = 0; i < from_body_list.size(); i++)
07925      {
07926        if (i != 0) PRINT_INFO( ",");
07927        PRINT_INFO( " %d", from_body_list.get_and_step()->id());
07928      }
07929      PRINT_INFO("\n");
07930    }
07931 
07932    PRINT_INFO( "  New Volume(s) created:");
07933    new_body_list.reset();
07934    DLIList<RefVolume*> new_vol_list;
07935    for (i = 0; i < new_body_list.size(); i++)
07936    {
07937      DLIList<RefVolume*> t2;
07938      new_body_list.get_and_step()->ref_volumes( t2 );
07939      new_vol_list += t2;
07940    }
07941 
07942    for( i = 0; i < new_vol_list.size(); i++ )
07943    {
07944      if (i != 0) PRINT_INFO( ",");
07945      PRINT_INFO( " %d", new_vol_list.get_and_step()->id());
07946    }
07947    PRINT_INFO("\n");
07948 
07949    PRINT_INFO( "  Original Volume(s) retained:");
07950    from_body_list.reset();
07951    DLIList<RefVolume*> from_vol_list;
07952    for (i = 0; i < from_body_list.size(); i++)
07953    {
07954      DLIList<RefVolume*> t2;
07955      from_body_list.get_and_step()->ref_volumes( t2 );
07956      from_vol_list += t2;
07957    }
07958 
07959    for( i = 0; i < from_vol_list.size(); i++ )
07960    {
07961      if (i != 0) PRINT_INFO( ",");
07962      PRINT_INFO( " %d", from_vol_list.get_and_step()->id());
07963    }
07964    PRINT_INFO("\n");
07965 
07966    if (reset_new_ids) set_new_ids(CUBIT_FALSE);
07967 
07968    return CUBIT_SUCCESS;
07969 }
07970 
07971 
07972 CubitStatus GeometryModifyTool::imprint( DLIList<Body*> &body_list,
07973                                          DLIList<RefEdge*> &ref_edge_list,
07974                                          DLIList<Body*>& new_body_list,
07975                                          CubitBoolean keep_old_body,
07976                                          CubitBoolean show_messages)
07977 {
07978   // Check the GeometryEngine for each of the bodies; check to
07979   // make sure they're all the same
07980   body_list.reset();
07981   int i;
07982 
07983   if (!okay_to_modify( body_list, "IMPRINT" ))
07984     return CUBIT_FAILURE;
07985 
07986   const int count = body_list.size() + ref_edge_list.size();
07987   DLIList<TopologyEntity*> entity_list(count);
07988   DLIList<TopologyBridge*> bridge_list(count);
07989   CAST_LIST_TO_PARENT(body_list, entity_list);
07990   ref_edge_list.reset();
07991   for (i = ref_edge_list.size(); i--;)
07992     entity_list.append(ref_edge_list.get_and_step());
07993 
07994   GeometryModifyEngine* gePtr1 = common_modify_engine(entity_list, bridge_list);
07995 
07996   DLIList<BodySM*> body_sm_list(body_list.size());
07997   DLIList<Curve*> curve_list(ref_edge_list.size());
07998   CAST_LIST(bridge_list, body_sm_list, BodySM);
07999   CAST_LIST(bridge_list, curve_list, Curve);
08000 
08001   if ( !gePtr1 ||
08002       body_sm_list.size() != body_list.size() ||
08003       curve_list.size() != ref_edge_list.size() )
08004   {
08005     PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
08006                 "different modeling engines is not allowed.\n"
08007                 "Delete uncommon geometry on these volumes before operation.\n\n");
08008     return CUBIT_FAILURE;
08009   }
08010 
08011   if( CubitUndo::get_undo_enabled() )
08012   {
08013     if( keep_old_body )
08014       CubitUndo::save_state();
08015     else
08016       CubitUndo::save_state_with_cubit_file( body_list );
08017   }
08018 
08019   int process_composites = 0;
08020   if(contains_composites(body_list))
08021     process_composites = 1;
08022 
08023   if(process_composites)
08024   {
08025     // Turn certain attributes on.
08026     do_attribute_setup();
08027     // Push virtual attributes down to solid model topology before
08028     // doing the imprint.
08029     push_attributes_before_modify(body_sm_list);
08030     // Put "ORIGINAL" attributes on the bodies being imprinted and
08031     // the curves as these originally existed.
08032     DLIList<TopologyBridge*> tb_list;
08033     CAST_LIST(body_sm_list, tb_list, TopologyBridge);
08034     push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
08035     tb_list.clean_out();
08036     CAST_LIST(curve_list, tb_list, TopologyBridge);
08037     push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
08038   }
08039 
08040   DLIList<BodySM*> new_sm_list;
08041   // The bridges doing the imprinting often get split during the process but
08042   // because of the way we are making copies, the IMPRINTER attribute doesn't
08043   // get propagated to them.  temporary_bridges will be filled in with any
08044   // additional IMPRINTER bridges we need to consider below when deciding whether to
08045   // keep composite attributes.
08046   DLIList<TopologyBridge*> temporary_bridges;
08047   CubitStatus status = gePtr1->imprint( body_sm_list, curve_list,
08048             new_sm_list, temporary_bridges, keep_old_body, show_messages);
08049 
08050   temporary_bridges.uniquify_ordered();
08051 
08052   if(status == CUBIT_FAILURE)
08053   {
08054     if(process_composites)
08055     {
08056       remove_pushed_attributes(new_sm_list, body_list);
08057       do_attribute_cleanup();
08058     }
08059 
08060     while(temporary_bridges.size())
08061     {
08062       TopologyBridge* bridge = temporary_bridges.pop();
08063       bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
08064     }
08065 
08066     return status;
08067   }
08068   else
08069   {
08070     if(process_composites)
08071     {
08072       DLIList<TopologyBridge*> tb_list;
08073       // Analyze the results and adjust virtual attributes as necessary.
08074       CAST_LIST(new_sm_list, tb_list, TopologyBridge);
08075       // The bridges coming back in temporary_bridges may not have IMPRINTER
08076       // attributes on them becuase of the way they were generated below.  Make
08077       // sure they get IMPRINTER attributes.
08078       push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
08079       tb_list += temporary_bridges;
08080       GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, body_list);
08081 
08082       // Clean up attributes.
08083       remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
08084 
08085       // Restore the virtual geometry.
08086       restore_vg_after_modify(new_sm_list, body_list, gePtr1);
08087       remove_pushed_attributes(new_sm_list, body_list);
08088     }
08089   }
08090 
08091   while(temporary_bridges.size())
08092   {
08093     TopologyBridge* bridge = temporary_bridges.pop();
08094     bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
08095   }
08096 
08097   status = finish_sm_op(body_list, new_sm_list, new_body_list);
08098 
08099   if(process_composites)
08100     do_attribute_cleanup();
08101 
08102    if( CubitUndo::get_undo_enabled() )
08103    {
08104      if( status == CUBIT_SUCCESS )
08105        CubitUndo::note_result_bodies( new_body_list );
08106      else
08107        CubitUndo::remove_last_undo();
08108    }
08109 
08110    return status;
08111 }
08112 
08113 CubitStatus GeometryModifyTool::imprint( DLIList<RefFace*> &ref_face_list,
08114                                          DLIList<RefEdge*> &ref_edge_list,
08115                                          DLIList<Body*>& new_body_list,
08116                                          CubitBoolean keep_old_body )
08117 {
08118   for(int j=0;j<ref_edge_list.size();j++)
08119   {
08120     RefEdge* edge=ref_edge_list[j];
08121     if(edge->get_arc_length()<=edge->get_geometry_query_engine()->get_sme_resabs_tolerance())
08122     {
08123 
08124       PRINT_ERROR( "Curve %d has zero length.\n To imprint curve as a hard point use the vertex of the curve.\n",edge->id() );
08125       return CUBIT_FAILURE;
08126 
08127     }
08128   }
08129 
08130   //get the owning bodies of the faces and edges
08131   DLIList<Body*> body_list;
08132   int j;
08133   for(j=ref_face_list.size(); j--;)
08134     ref_face_list.get_and_step()->bodies( body_list );
08135   for(j=ref_edge_list.size(); j--;)
08136     ref_edge_list.get_and_step()->bodies( body_list );
08137   body_list.uniquify_ordered();
08138   if (!okay_to_modify( body_list, "IMPRINT" ))
08139     return CUBIT_FAILURE;
08140 
08141   DLIList<TopologyEntity*> temp_list, temp_list_2, body_me_list;
08142   CAST_LIST_TO_PARENT(ref_face_list, temp_list);
08143   CAST_LIST_TO_PARENT(ref_edge_list, temp_list_2);
08144   temp_list += temp_list_2;
08145   ModelQueryEngine::instance()->query_model(temp_list, DagType::body_type(), body_me_list );
08146 
08147   DLIList<Surface*> surf_list(ref_face_list.size());
08148   DLIList<Curve*> curve_list(ref_edge_list.size());
08149   GeometryModifyEngine* gePtr1 = common_modify_engine( ref_face_list,ref_edge_list,surf_list,
08150                              curve_list,true);
08151   if ( !gePtr1 )
08152   {
08153     PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
08154             "different modeling engines is not allowed.\n"
08155             "Delete uncommon geometry on these volumes before operation.\n\n");
08156     return CUBIT_FAILURE;
08157   }
08158 
08159   if( CubitUndo::get_undo_enabled() )
08160   {
08161     if( keep_old_body )
08162       CubitUndo::save_state();
08163     else
08164       CubitUndo::save_state_with_cubit_file( ref_face_list );
08165   }
08166 
08167   int process_composites = 0;
08168   if(contains_composites(body_list))
08169     process_composites = 1;
08170 
08171   int i;
08172   DLIList<BodySM*> body_sm_list;
08173   if(process_composites)
08174   {
08175     // Turn certain attributes on.
08176     do_attribute_setup();
08177     for(i=body_list.size(); i--;)
08178       body_sm_list.append_unique(body_list.get_and_step()->get_body_sm_ptr());
08179     // Push virtual attributes down to solid model topology before
08180     // doing the imprint.
08181     push_attributes_before_modify(body_sm_list);
08182     // Put "ORIGINAL" attributes on the bodies being imprinted and
08183     // the curves as these originally existed.
08184     DLIList<TopologyBridge*> tmp_tb_list;
08185     CAST_LIST(surf_list, tmp_tb_list, TopologyBridge);
08186     push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
08187   }
08188 
08189   DLIList<BodySM*> new_sm_list;
08190   // The bridges doing the imprinting often get split during the process but
08191   // because of the way we are making copies, the IMPRINTER attribute doesn't
08192   // get propagated to them.  temporary_bridges will be filled in with any
08193   // additional IMPRINTER bridges we need to consider below when deciding whether to
08194   // keep composite attributes.
08195   DLIList<TopologyBridge*> temporary_bridges;
08196   CubitStatus status = gePtr1->imprint( surf_list, curve_list, temporary_bridges,
08197                                          new_sm_list, keep_old_body );
08198   temporary_bridges.uniquify_ordered();
08199 
08200   if(process_composites)
08201   {
08202     // Analyze the results and adjust virtual attributes as necessary.
08203     DLIList<TopologyBridge*> tb_list;
08204     CAST_LIST(new_sm_list, tb_list, TopologyBridge);
08205     // The bridges coming back in temporary_bridges may not have IMPRINTER
08206     // attributes on them becuase of the way they were generated below.  Make
08207     // sure they get IMPRINTER attributes.
08208     push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
08209     tb_list += temporary_bridges;
08210     GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, body_list);
08211 
08212     // Clean up attributes.
08213     remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
08214 
08215     restore_vg_after_modify(body_sm_list, body_list, gePtr1);
08216     remove_pushed_attributes(body_sm_list, body_list);
08217   }
08218 
08219   while(temporary_bridges.size())
08220   {
08221     TopologyBridge* bridge = temporary_bridges.pop();
08222     bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
08223   }
08224 
08225   CubitStatus status2 = finish_sm_op(body_list, new_sm_list, new_body_list);
08226 
08227   if(process_composites)
08228     do_attribute_cleanup();
08229 
08230   if( CubitUndo::get_undo_enabled() )
08231    {
08232      if( status == CUBIT_SUCCESS )
08233        CubitUndo::note_result_bodies( new_body_list );
08234      else
08235        CubitUndo::remove_last_undo();
08236    }
08237 
08238    if( status == CUBIT_SUCCESS && status2 == CUBIT_SUCCESS)
08239      return status;
08240 
08241    else
08242      return CUBIT_FAILURE;
08243 }
08244 
08245 CubitStatus GeometryModifyTool::imprint( DLIList<Surface*> &surface_list,
08246                                          DLIList<DLIList<Curve*>*> &curve_lists_list,
08247                                          Body*& /*new_body*/,
08248                                          CubitBoolean keep_old_body,
08249                                          CubitBoolean expand)
08250 {
08251   int i;
08252   DLIList<Curve*> *curve_list_ptr;
08253 
08254   // Check to see if any curves exist - if none, just exit
08255   int have_curves = 0;
08256   for( i=curve_lists_list.size(); i--; )
08257   {
08258     curve_list_ptr = curve_lists_list.get_and_step();
08259     for(int j=0;j<curve_list_ptr->size();j++)
08260     {
08261       Curve* curve=(*curve_list_ptr)[j];
08262       if(curve->get_arc_length()<=curve->get_geometry_query_engine()->get_sme_resabs_tolerance())
08263       {
08264         RefEdge* edge = dynamic_cast<RefEdge*>(curve->topology_entity());
08265         if(edge)
08266         {
08267           PRINT_ERROR( "Curve %d has zero length.\n To imprint as a hard point use the vertex of the curve.\n",edge->id() );
08268           return CUBIT_FAILURE;
08269         }
08270         else
08271         {
08272           return CUBIT_FAILURE;
08273         }
08274       }
08275       else
08276       {
08277         have_curves++;
08278         break;
08279       }
08280     }
08281   }
08282   if( !have_curves )
08283     return CUBIT_SUCCESS;
08284 
08285   // Get parent bodies
08286   DLIList<Body*> old_body_list;
08287   surface_list.reset();
08288   for( i=surface_list.size(); i--; )
08289   {
08290     Surface *surf_ptr = surface_list.get_and_step();
08291     RefEntity* ref_ent = dynamic_cast<RefEntity*>(surf_ptr->topology_entity());
08292     RefFace *ref_face_ptr = CAST_TO( ref_ent, RefFace );
08293 
08294     if( ref_face_ptr )
08295     {
08296       DLIList<Body*> body_list;
08297       ref_face_ptr->bodies( body_list );
08298       old_body_list.merge_unique( body_list );
08299     }
08300   }
08301 
08302   if( old_body_list.size() > 1 )
08303   {
08304     PRINT_ERROR( "This operation requires all surfaces to be from the same volume\n" );
08305     // Note: this restriction could be pretty easily lifted by sorting the
08306     //       input lists and calling the GeometryModifyEngine for each body
08307     //       separately, or having engines handle this.
08308     return CUBIT_FAILURE;
08309   }
08310 
08311 
08312   // In order to support imprinting on composite surfaces we will
08313   // get any surfaces underlying the surfaces passed in.  For now
08314   // we will only do this if a single surface is coming in but
08315   // it could be extended for multiple surfaces as well.
08316   DLIList<Surface*> new_surface_list;
08317   if(surface_list.size() == 1)
08318   {
08319     GeometryQueryEngine *gqe = surface_list.get()->get_geometry_query_engine();
08320     DLIList<TopologyBridge*> tbs;
08321     gqe->get_underlying_surfaces(surface_list.get(), tbs);
08322     if(tbs.size() > 0)
08323     {
08324       for(int k=tbs.size(); k--;)
08325         new_surface_list.append(dynamic_cast<Surface*>(tbs.get_and_step()));
08326     }
08327     else
08328       new_surface_list.append(surface_list.get());
08329   }
08330   else
08331     new_surface_list = surface_list;
08332 
08333   // Check engines - must all be the same
08334   GeometryModifyEngine* gme;
08335   new_surface_list.reset();
08336   gme = get_engine( new_surface_list.get() );
08337   for( i=new_surface_list.size(); i--; )
08338   {
08339     Surface *surf_ptr = new_surface_list.get_and_step();
08340     GeometryModifyEngine* gme2 = get_engine( surf_ptr );
08341     if( gme != gme2 )
08342     {
08343       PRINT_ERROR( "All surfaces being imprinted must be from the same geometry engine\n" );
08344       return CUBIT_FAILURE;
08345     }
08346   }
08347 
08348   int j;
08349   for( i=curve_lists_list.size(); i--; )
08350   {
08351     curve_list_ptr = curve_lists_list.get_and_step();
08352     for( j=curve_list_ptr->size(); j--; )
08353     {
08354       Curve *curve_ptr = curve_list_ptr->get_and_step();
08355       GeometryModifyEngine* gme2 = get_engine( curve_ptr );
08356       if( gme != gme2 )
08357       {
08358         PRINT_ERROR( "Curves used to imprint must be from same geometry engine as Surface\n" );
08359         return CUBIT_FAILURE;
08360       }
08361     }
08362   }
08363 
08364    if( CubitUndo::get_undo_enabled() )
08365    {
08366      if( keep_old_body )
08367        CubitUndo::save_state();
08368      else
08369        CubitUndo::save_state_with_cubit_file( old_body_list );
08370    }
08371 
08372   int process_composites = 0;
08373   if(contains_composites(old_body_list))
08374     process_composites = 1;
08375 
08376   BodySM* new_body_sm = 0;
08377   DLIList<BodySM*> body_sm_list;
08378 
08379   DLIList<TopologyBridge*> tb_list;
08380   if(process_composites)
08381   {
08382     do_attribute_setup();
08383     for(i=old_body_list.size(); i--;)
08384       body_sm_list.append_unique(old_body_list.get_and_step()->get_body_sm_ptr());
08385     push_attributes_before_modify(body_sm_list);
08386  //   push_imprint_attributes_before_modify(body_sm_list);
08387     DLIList<TopologyBridge*> tmp_tb_list;
08388     CAST_LIST(new_surface_list, tmp_tb_list, TopologyBridge);
08389     push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
08390 
08391     for(i=curve_lists_list.size(); i>0; i--)
08392     {
08393       DLIList<Curve*> *cur_list = curve_lists_list.get_and_step();
08394       for(j=cur_list->size(); j>0; j--)
08395       {
08396         Curve *cur_curve = cur_list->get_and_step();
08397         tb_list.append(cur_curve);
08398       }
08399     }
08400     push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
08401   }
08402 
08403   CubitStatus status = gme->imprint( new_surface_list, curve_lists_list,
08404     new_body_sm, keep_old_body, expand);
08405 
08406   DLIList<Body*> new_body_list;
08407   DLIList<BodySM*> new_sm_list;
08408   new_sm_list.append( new_body_sm );
08409 
08410   if(process_composites)
08411   {
08412     // Analyze the results and adjust virtual attributes as necessary.
08413        DLIList<TopologyBridge*> tmp_tb_list;
08414        CAST_LIST(new_sm_list, tmp_tb_list, TopologyBridge);
08415        tb_list += tmp_tb_list;
08416     GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, old_body_list);
08417 
08418     // Clean up attributes.
08419     remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
08420 
08421     restore_vg_after_modify(body_sm_list, old_body_list, gme);
08422     remove_pushed_attributes(body_sm_list, old_body_list);
08423   }
08424 
08425   CubitStatus status2 = finish_sm_op(old_body_list, new_sm_list, new_body_list);
08426 
08427   if(process_composites)
08428     do_attribute_cleanup();
08429 
08430   if( CubitUndo::get_undo_enabled() )
08431   {
08432     if( status == CUBIT_SUCCESS )
08433       CubitUndo::note_result_bodies( new_body_list );
08434     else
08435       CubitUndo::remove_last_undo();
08436   }
08437 
08438   if( status == CUBIT_SUCCESS && status2 == CUBIT_SUCCESS)
08439      return status;
08440 
08441    else
08442      return CUBIT_FAILURE;
08443 }
08444 
08445 CubitStatus GeometryModifyTool::imprint( DLIList<Body*> &body_list,
08446                                          DLIList<CubitVector> &vector_list,
08447                                          DLIList<Body*>& new_body_list,
08448                                          CubitBoolean keep_old_body,
08449                                          CubitBoolean merge )
08450 {
08451   // Check the GeometryEngine for each of the RefEdges; check to
08452   // make sure they're all the same
08453   body_list.reset();
08454 
08455   if (!okay_to_modify( body_list, "IMPRINT" ))
08456     return CUBIT_FAILURE;
08457 
08458   DLIList<BodySM*> body_sm_list(body_list.size()), new_sm_list;
08459   GeometryModifyEngine* gePtr1 = common_modify_engine(body_list, body_sm_list);
08460   if ( !gePtr1 )
08461   {
08462     PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
08463                 "different modeling engines is not allowed.\n"
08464                 "Delete uncommon geometry on these volumes before operation.\n\n");
08465     return CUBIT_FAILURE;
08466   }
08467 
08468   if( CubitUndo::get_undo_enabled() )
08469   {
08470     if( keep_old_body )
08471       CubitUndo::save_state();
08472     else
08473       CubitUndo::save_state_with_cubit_file( body_list );
08474   }
08475 
08476   int process_composites = 0;
08477   if(contains_composites(body_list))
08478     process_composites = 1;
08479 
08480   int i;
08481   DLIList<TopologyBridge*> temporary_bridges;
08482   if(process_composites)
08483   {
08484     // Turn certain attributes on.
08485     do_attribute_setup();
08486     // Push virtual attributes down to solid model topology before
08487     // doing the imprint.
08488     push_attributes_before_modify(body_sm_list);
08489     // Create temporary bridges for the vector positions.  We do
08490     // this so that we can put an IMPRINTER attribute on them
08491     // and use them later for deciding whether to keep composite
08492     // attributes or not.
08493     for(i=vector_list.size(); i>0; i--)
08494     {
08495       CubitVector vec = vector_list.get_and_step();
08496       TBPoint *pt = gePtr1->make_Point(vec);
08497       temporary_bridges.append(pt);
08498     }
08499     push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
08500     DLIList<TopologyBridge*> tmp_tb_list;
08501     CAST_LIST(body_sm_list, tmp_tb_list, TopologyBridge);
08502     // Put "ORIGINAL" attributes on the bridges that originally existed.
08503     push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
08504   }
08505 
08506   CubitStatus status = gePtr1->imprint( body_sm_list, vector_list,new_sm_list,
08507     keep_old_body);
08508 
08509   temporary_bridges.uniquify_ordered();
08510 
08511   if(process_composites)
08512   {
08513     // Analyze the results and adjust virtual attributes as necessary.
08514     DLIList<TopologyBridge*> tb_list;
08515     CAST_LIST(new_sm_list, tb_list, TopologyBridge);
08516     tb_list += temporary_bridges;
08517     GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, body_list);
08518 
08519     while(temporary_bridges.size())
08520     {
08521       TopologyBridge* bridge = temporary_bridges.pop();
08522       bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
08523     }
08524 
08525     // Clean up attributes.
08526     remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
08527 
08528     // Restore the virtual geometry.
08529     restore_vg_after_modify(new_sm_list, body_list, gePtr1);
08530     remove_pushed_attributes(new_sm_list, body_list);
08531   }
08532 
08533   CubitStatus status2 = finish_sm_op(body_list, new_sm_list, new_body_list);
08534 
08535   if(process_composites)
08536     do_attribute_cleanup();
08537 
08538    if( merge )
08539    {
08540      DLIList<Body*> bodies_to_merge;
08541      int i;
08542      for( i=new_body_list.size(); i--; )
08543      {
08544        Body *tmp_body = new_body_list.get_and_step();
08545        DLIList<RefEdge*> ref_edge_list;
08546        tmp_body->ref_edges( ref_edge_list );
08547 
08548        int j;
08549        for( j=ref_edge_list.size(); j--; )
08550        {
08551          RefEdge *tmp_edge = ref_edge_list.get_and_step();
08552          DLIList<Body*> body_list;
08553          tmp_edge->bodies( body_list );
08554          bodies_to_merge.merge_unique( body_list );
08555        }
08556      }
08557      MergeTool::instance()->merge_bodies( bodies_to_merge );
08558    }
08559 
08560    if( CubitUndo::get_undo_enabled() )
08561    {
08562      if( status == CUBIT_SUCCESS )
08563        CubitUndo::note_result_bodies( new_body_list );
08564      else
08565        CubitUndo::remove_last_undo();
08566    }
08567 
08568    if( status == CUBIT_SUCCESS && status2 == CUBIT_SUCCESS)
08569      return status;
08570 
08571    else
08572      return CUBIT_FAILURE;
08573 }
08574 CubitStatus GeometryModifyTool::project_edges( DLIList<RefFace*> &ref_face_list,
08575                                                DLIList<RefEdge*> &ref_edge_list_in,
08576                                                DLIList<RefEdge*> &ref_edge_list_new,
08577                                                CubitBoolean trim_projected)
08578 {
08579   int i, j;
08580 
08581    // Check the GeometryEngine for each of the RefEdges; check to
08582    // make sure they're all the same
08583   DLIList<Surface*> surface_list(ref_face_list.size());
08584   DLIList<Curve*> curve_list_in(ref_edge_list_in.size()), curve_list_new;
08585   GeometryModifyEngine* gme = common_modify_engine( ref_face_list,
08586                                                     ref_edge_list_in,
08587                                                     surface_list,
08588                                                     curve_list_in );
08589 
08590   if ( !gme ) {
08591     PRINT_ERROR("In GeometryTool::create_blend\n"
08592                 "       Curves have different modify engines.\n");
08593     return CUBIT_FAILURE;
08594   }
08595 
08596    CubitStatus status = gme->
08597      project_edges( surface_list, curve_list_in, curve_list_new);
08598 
08599   if( CubitUndo::get_undo_enabled() && status == CUBIT_SUCCESS )
08600     CubitUndo::save_state();
08601 
08602 
08603    curve_list_new.reset();
08604 
08605    if(trim_projected){
08606      DLIList<Curve*> tmp_curves, all_new_curves;
08607      Curve* tmp_curve;
08608      Surface* tmp_surface;
08609 
08610      for(i = 0; i< surface_list.size(); i++){
08611        tmp_curves.clean_out();
08612        tmp_surface = surface_list.get_and_step();
08613        for(j=0; j<curve_list_new.size(); j++){
08614          tmp_curve = curve_list_new.get_and_step();
08615          status = gme->curve_surface_intersection( tmp_surface, tmp_curve, tmp_curves);
08616        }
08617        all_new_curves += tmp_curves;
08618 
08619      }
08620 
08621      if(!all_new_curves.size()){
08622        if(!curve_list_new.size()){
08623          PRINT_ERROR("Projection resulted in no curves.\n");
08624          return CUBIT_FAILURE;
08625        }
08626        else{
08627          PRINT_WARNING("No curve remained after trimming operation.  \n \tCurve projection may lie completely outside of trimmed surface.\n");
08628        }
08629      }
08630 
08631        //fix this...
08632        //can we just cleanout this list or do we need to delete the entities in it.
08633      for( i = 0; i< curve_list_new.size(); i++ )
08634      {
08635        Curve *tmp_curve = curve_list_new.get_and_step();
08636        gme->get_gqe()->delete_solid_model_entities( tmp_curve );
08637      }
08638 
08639      curve_list_new.clean_out();
08640      curve_list_new = all_new_curves;
08641 
08642      if( CubitUndo::get_undo_enabled() && status == CUBIT_SUCCESS )
08643        CubitUndo::save_state();
08644    }
08645 
08646 
08647 
08648    curve_list_new.reset();
08649    for (i = curve_list_new.size(); i--; )
08650    {
08651      Curve* curve = curve_list_new.get_and_step();
08652      RefEdge* new_edge = GeometryQueryTool::instance()->make_free_RefEdge(curve);
08653      PRINT_INFO("Created Curve %d\n", new_edge->id());
08654      ref_edge_list_new.append(new_edge);
08655      if( CubitUndo::get_undo_enabled() && new_edge )
08656        CubitUndo::note_result_entity( new_edge );
08657    }
08658 
08659    if( CubitUndo::get_undo_enabled() )
08660    {
08661      if( ref_edge_list_new.size() == 0 )
08662        CubitUndo::remove_last_undo();
08663    }
08664 
08665    return status;
08666 }
08667 
08668 CubitStatus
08669 GeometryModifyTool::imprint_projected_edges(DLIList<RefFace*> &ref_face_list,
08670                                             DLIList<RefEdge*> &ref_edge_list_in,
08671                                             DLIList<Body*>& new_body_list,
08672                                             CubitBoolean keep_old_body,
08673                                             CubitBoolean keep_free_edges)
08674 {
08675 
08676    DLIList<Surface*> surface_list(ref_face_list.size());
08677    DLIList<Curve*> curve_list(ref_edge_list_in.size());
08678    GeometryModifyEngine* gme = common_modify_engine( ref_face_list,
08679                                                      ref_edge_list_in,
08680                                                      surface_list,
08681                                                      curve_list );
08682    if ( !gme )
08683    {
08684       PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
08685                   "different modeling engines is not allowed.\n"
08686                   "Delete uncommon geometry on these volumes before operation.\n\n");
08687       return CUBIT_FAILURE;
08688    }
08689 
08690    DLIList<TopologyEntity*> query_output, query_input(ref_face_list.size());
08691    CAST_LIST_TO_PARENT(ref_face_list, query_input);
08692    ModelQueryEngine::instance()->query_model(query_input, DagType::body_type(), query_output);
08693    DLIList<Body*> body_list(query_output.size());
08694    CAST_LIST(query_output, body_list, Body);
08695    DLIList<BodySM*> new_sm_list;
08696    DLIList<Curve*> kept_free_edges;
08697 
08698    if( CubitUndo::get_undo_enabled() )
08699    {
08700      if( keep_old_body )
08701        CubitUndo::save_state();
08702      else
08703        CubitUndo::save_state_with_cubit_file( ref_face_list );
08704    }
08705 
08706    CubitStatus status = gme->imprint_projected_edges( surface_list, curve_list,
08707                                                       new_sm_list, kept_free_edges,
08708                                                       keep_old_body, keep_free_edges);
08709 
08710    if (!finish_sm_op(body_list, new_sm_list, new_body_list))
08711      status = CUBIT_FAILURE;
08712 
08713    DLIList<RefEdge*> kept_ref_edges;
08714    if( keep_free_edges )
08715    {
08716      for( int i=kept_free_edges.size(); i--; )
08717      {
08718        RefEdge *tmp_edge = GeometryQueryTool::instance()->make_free_RefEdge( kept_free_edges.get_and_step());
08719        if( tmp_edge )
08720          kept_ref_edges.append(tmp_edge );
08721      }
08722    }
08723 
08724    if( CubitUndo::get_undo_enabled() )
08725    {
08726      if( status == CUBIT_FAILURE )
08727        CubitUndo::remove_last_undo();
08728      else
08729      {
08730        CubitUndo::note_result_bodies( new_body_list );
08731        if( keep_free_edges )
08732        {
08733          DLIList<RefEntity*> ref_ents;
08734          for( int i=kept_ref_edges.size(); i--; )
08735            ref_ents.append( kept_ref_edges.get_and_step() );
08736          CubitUndo::note_result_entities( ref_ents );
08737        }
08738      }
08739    }
08740 
08741    return status;
08742 }
08743 
08744 CubitStatus
08745 GeometryModifyTool::imprint_projected_edges(DLIList<RefFace*> &ref_face_list,
08746                                             DLIList<Body*> &body_list,
08747                                             DLIList<RefEdge*> &ref_edge_list_in,
08748                                             DLIList<Body*>& new_body_list,
08749                                             CubitBoolean keep_old_body,
08750                                             CubitBoolean keep_free_edges)
08751 {
08752 
08753    DLIList<Surface*> surface_list(ref_face_list.size());
08754    DLIList<Curve*>     curve_list(ref_edge_list_in.size());
08755    DLIList<BodySM*>  body_sm_list(body_list.size()), new_sm_list;
08756    GeometryModifyEngine* gme = common_modify_engine(ref_face_list,
08757                                                     ref_edge_list_in,
08758                                                     surface_list,
08759                                                     curve_list);
08760    if (!gme || gme != common_modify_engine(body_list, body_sm_list))
08761    {
08762       PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
08763                   "different modeling engines is not allowed.\n"
08764                   "Delete uncommon geometry on these volumes before operation.\n\n");
08765       return CUBIT_FAILURE;
08766    }
08767 
08768      // Get RefFace bodies
08769    DLIList<TopologyEntity*> query_output, query_input(ref_face_list.size());
08770    CAST_LIST_TO_PARENT(ref_face_list, query_input);
08771    ModelQueryEngine::instance()->
08772      query_model( query_input, DagType::body_type(), query_output );
08773    DLIList<Body*> face_body_list;
08774    CAST_LIST(query_output, face_body_list, Body);
08775 
08776    CubitStatus status = gme->imprint_projected_edges( surface_list,
08777                                                       body_sm_list,
08778                                                       curve_list,
08779                                                       new_sm_list,
08780                                                       keep_old_body,
08781                                                       keep_free_edges);
08782    face_body_list += body_list;
08783    if (!finish_sm_op(face_body_list, new_sm_list, new_body_list))
08784      status = CUBIT_FAILURE;
08785 
08786    return status;
08787 
08788 }
08789 
08790 
08791 RefEntity* GeometryModifyTool::copy_refentity( RefEntity *old_entity )
08792 {
08793    RefEntity *new_entity = NULL;
08794 
08795    if( old_entity == NULL )
08796        return (RefEntity*) NULL;
08797 
08798    if( CAST_TO( old_entity, RefVolume ) )
08799        return (RefEntity*) NULL;
08800 
08801    RefFace *old_face = CAST_TO( old_entity, RefFace );
08802    if( old_face )
08803    {
08804       RefFace *new_face = instance()->make_RefFace( old_face );
08805       new_entity = CAST_TO( new_face, RefEntity );
08806    }
08807 
08808    RefEdge *old_edge = CAST_TO( old_entity, RefEdge );
08809    if( old_edge )
08810    {
08811       RefEdge *new_edge = instance()->make_RefEdge( old_edge );
08812       new_entity = CAST_TO( new_edge, RefEntity );
08813    }
08814 
08815    RefVertex *old_vert = CAST_TO( old_entity, RefVertex );
08816    if( old_vert )
08817    {
08818       RefVertex *new_vert = instance()->make_RefVertex( old_vert->coordinates() );
08819       new_entity = CAST_TO( new_vert, RefEntity );
08820    }
08821 
08822    return new_entity;
08823 }
08824 
08825 //  Calls solid modeling engine to webcut with a sheet body.
08826 CubitStatus GeometryModifyTool::webcut_with_sheet( DLIList<Body*> &webcut_body_list,
08827                                                    Body *sheet_body,
08828                                                    DLIList<Body*> &new_bodies,
08829                                                    DLIList<Body*> &neighboring_bodies,
08830                                                    ImprintType imprint_type,
08831                                                    CubitBoolean merge,
08832                                                    CubitBoolean preview)
08833 {
08834    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
08835      return CUBIT_FAILURE;
08836 
08837    GfxPreview::clear();
08838 
08839    //remove any bodies with bbox that does not intersect tool body bbox
08840    CubitBox tool_bounding_box = sheet_body->bounding_box();
08841    remove_bodies_outside_bounding_box( webcut_body_list, tool_bounding_box );
08842 
08843    if( webcut_body_list.size() == 0 )
08844    {
08845      PRINT_INFO("Tool does not intersect any bodies/volumes.\n");
08846      return CUBIT_FAILURE;
08847    }
08848 
08849    DLIList<Body*> original_body_list = webcut_body_list;
08850    webcut_body_list.append(sheet_body);
08851    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
08852    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
08853    if ( !gme )
08854    {
08855       PRINT_ERROR("Performing WEBCUTS with volumes containing geometry from\n"
08856                   "different modeling engines is not allowed.\n"
08857                   "Delete uncommon geometry on these volumes before operation.\n\n");
08858       return CUBIT_FAILURE;
08859    }
08860    BodySM* tool_sm = body_sm_list.pop();
08861 
08862    DLIList<int> merged_surface_ids;
08863    DLIList<int> merged_curve_ids;
08864    DLIList<BodySM*> neighbor_imprint_list;
08865    DLIList<Body*> bodies_to_modify;
08866 
08867    if (!preview)
08868    {
08869      if( CubitUndo::get_undo_enabled() )
08870      {
08871        DLIList<Body*> bodies_to_save;
08872        bodies_to_save += webcut_body_list;
08873        bodies_to_save += neighboring_bodies;
08874        CubitUndo::save_state_with_cubit_file( bodies_to_save );
08875      }
08876 
08877      int i;
08878      for( i=neighboring_bodies.size(); i--; )
08879      {
08880        Body *neighbor_body = neighboring_bodies.get_and_step();
08881        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
08882        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
08883 
08884        if( gme == neighbor_gme )
08885          neighbor_imprint_list.append( tmp_body );
08886      }
08887 
08888      do_attribute_setup();
08889      DLIList<BodySM*> bodies_sm_to_modify;
08890      bodies_sm_to_modify += body_sm_list;
08891      bodies_sm_to_modify += neighbor_imprint_list;
08892      push_attributes_before_modify( bodies_sm_to_modify );
08893      bodies_to_modify += webcut_body_list;
08894      bodies_to_modify += neighboring_bodies;
08895      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
08896    }
08897 
08898    CubitStatus stat = gme->webcut (
08899        body_sm_list, tool_sm, neighbor_imprint_list,
08900        new_sms, imprint_type, preview  );
08901 
08902    if (!preview)
08903    {
08904      restore_vg_after_modify(new_sms, bodies_to_modify, gme);
08905      remove_pushed_attributes(new_sms, bodies_to_modify );
08906    }
08907 
08908    if( stat == CUBIT_FAILURE )
08909    {
08910      do_attribute_cleanup();
08911 
08912      if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
08913      {
08914        if( stat == CUBIT_SUCCESS )
08915          CubitUndo::note_result_bodies( new_bodies );
08916        else
08917          CubitUndo::remove_last_undo();
08918      }
08919      return CUBIT_FAILURE;
08920    }
08921 
08922    // finish up if not a preview
08923    if (!preview)
08924    {
08925      stat = finish_webcut( webcut_body_list, new_sms, merge, stat, new_bodies,
08926                            &merged_surface_ids, &merged_curve_ids );
08927       // leave webcut_body_list as we found it -- remove appended tool body
08928      webcut_body_list.pop();
08929 
08930      do_attribute_cleanup();
08931 
08932      if( CubitUndo::get_undo_enabled() )
08933      {
08934        if( stat == CUBIT_SUCCESS )
08935          CubitUndo::note_result_bodies( new_bodies );
08936        else
08937          CubitUndo::remove_last_undo();
08938      }
08939    }
08940 
08941 
08942    return stat;
08943 }
08944 //  Calls solid modeling engine to webcut with a sheet body.
08945 CubitStatus GeometryModifyTool::webcut_with_extended_sheet( DLIList<Body*> &webcut_body_list,
08946                                                            DLIList<RefFace*> &ref_face_list,
08947                                                            DLIList<Body*> &new_bodies,
08948                                                            DLIList<Body*> &neighboring_bodies,
08949                                                            int &num_cut,
08950                                                            ImprintType imprint_type,
08951                                                            CubitBoolean merge,
08952                                                            CubitBoolean preview)
08953 {
08954    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
08955      return CUBIT_FAILURE;
08956 
08957    GfxPreview::clear();
08958 
08959    DLIList<RefEntity*> ref_entity_list;
08960    CAST_LIST( ref_face_list, ref_entity_list, RefEntity );
08961    if( !same_modify_engine( ref_entity_list ) )
08962    {
08963      PRINT_ERROR( "Extending surfaces from different geometry engines is\n"
08964        "       not allowed.\n\n" );
08965      return CUBIT_FAILURE;
08966    }
08967 
08968    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
08969    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
08970 
08971    if( !gme )
08972    {
08973      PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from\n"
08974                   "different modeling engines is not allowed.\n"
08975                   "Delete uncommon geometry on these volumes before operation.\n\n");
08976       return CUBIT_FAILURE;
08977    }
08978 
08979    const char* modeler =
08980           ref_face_list.get()->get_geometry_query_engine()->modeler_type();
08981    if (strncmp("virtual", modeler, 7) == 0)
08982    {
08983      PRINT_ERROR("Cannot extend virtual surfaces.\n"
08984                  "Remove virtual layer before operation.\n");
08985      return CUBIT_FAILURE;
08986    }
08987 
08988    Surface* surf_ptr = 0;
08989    TopologyBridge* bridge = ref_face_list.get()->bridge_manager()->topology_bridge(gme->get_gqe());
08990    surf_ptr = dynamic_cast<Surface*>(bridge);
08991 
08992    if ( !surf_ptr )
08993    {
08994       PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from a\n"
08995                   "different modeling engine than the extended surfaces is\n"
08996                   "not allowed.\n"
08997                   "Delete uncommon geometry on these volumes before operation.\n\n");
08998       return CUBIT_FAILURE;
08999    }
09000 
09001    GeometryQueryEngine *gqe = gme->get_gqe();
09002 
09003    int i;
09004    RefFace *ref_face_ptr;
09005    DLIList<Surface*> surf_list;
09006    for( i=ref_face_list.size(); i--; )
09007    {
09008      ref_face_ptr = ref_face_list.get_and_step();
09009      bridge = ref_face_ptr->bridge_manager()->topology_bridge(gqe);
09010      surf_ptr = dynamic_cast<Surface*>(bridge);
09011      surf_list.append( surf_ptr );
09012    }
09013 
09014    DLIList<int> merged_surface_ids;
09015    DLIList<int> merged_curve_ids;
09016    DLIList<BodySM*> neighbor_imprint_list;
09017    DLIList<Body*> bodies_to_modify;
09018 
09019    if (!preview)
09020    {
09021      if( CubitUndo::get_undo_enabled() )
09022      {
09023        DLIList<Body*> bodies_to_save;
09024        bodies_to_save += webcut_body_list;
09025        bodies_to_save += neighboring_bodies;
09026        CubitUndo::save_state_with_cubit_file( bodies_to_save );
09027      }
09028 
09029      int i;
09030      for( i=neighboring_bodies.size(); i--; )
09031      {
09032        Body *neighbor_body = neighboring_bodies.get_and_step();
09033        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
09034        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
09035 
09036        if( gme == neighbor_gme )
09037          neighbor_imprint_list.append( tmp_body );
09038      }
09039 
09040      do_attribute_setup();
09041      DLIList<BodySM*> bodies_sm_to_modify;
09042      bodies_sm_to_modify += body_sm_list;
09043      bodies_sm_to_modify += neighbor_imprint_list;
09044      push_attributes_before_modify( bodies_sm_to_modify );
09045      bodies_to_modify += webcut_body_list;
09046      bodies_to_modify += neighboring_bodies;
09047      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
09048    }
09049 
09050    CubitStatus stat = gme->webcut_with_extended_sheet( body_sm_list,
09051      surf_list, neighbor_imprint_list, new_sms, num_cut, imprint_type,
09052      preview );
09053 
09054    if (!preview)
09055    {
09056      restore_vg_after_modify(new_sms, bodies_to_modify, gme);
09057      remove_pushed_attributes(new_sms, bodies_to_modify);
09058      stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
09059                           &merged_surface_ids, &merged_curve_ids );
09060      do_attribute_cleanup();
09061 
09062      if( CubitUndo::get_undo_enabled() )
09063      {
09064        if( stat == CUBIT_SUCCESS )
09065          CubitUndo::note_result_bodies( new_bodies );
09066        else
09067          CubitUndo::remove_last_undo();
09068      }
09069    }
09070 
09071    return stat;
09072 }
09073 
09074 
09075 CubitStatus GeometryModifyTool::webcut_with_sweep_surfaces_rotated(
09076                             DLIList<Body*> &webcut_body_list,
09077                             DLIList<RefFace*> &tool_faces,
09078                             CubitVector &point,
09079                             CubitVector &sweep_axis,
09080                             double angle,
09081                             RefFace* stop_surf,
09082                             bool up_to_next,
09083                             DLIList<Body*> &new_bodies,
09084                             DLIList<Body*> &neighboring_bodies,
09085                             ImprintType imprint_type,
09086                             CubitBoolean merge,
09087                             CubitBoolean preview)
09088 {
09089 
09090    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
09091      return CUBIT_FAILURE;
09092 
09093    GfxPreview::clear();
09094 
09095    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
09096    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
09097    DLIList<Surface*> surfaces_to_sweep;
09098    if (gme)
09099    {
09100      GeometryModifyEngine* surf_gme = common_modify_engine( tool_faces, surfaces_to_sweep );
09101      if( gme != surf_gme )
09102        PRINT_ERROR("All geometry not from the same modeling engine.\n");
09103    }
09104 
09105    Surface *stop_surface = NULL;
09106    if( stop_surf )
09107    {
09108      GeometryModifyEngine *tmp_gme = get_engine(stop_surf);
09109 
09110      if( gme != tmp_gme )
09111      {
09112        PRINT_ERROR("Stop surface %d is not of same modeling engine as other input geometry.\n",
09113                     stop_surf->id() );
09114        return CUBIT_FAILURE;
09115      }
09116 
09117      stop_surface = stop_surf->get_surface_ptr();
09118    }
09119 
09120    DLIList<int> merged_surface_ids;
09121    DLIList<int> merged_curve_ids;
09122    DLIList<BodySM*> neighbor_imprint_list;
09123    DLIList<Body*> bodies_to_modify;
09124 
09125    if (!preview)
09126    {
09127      if( CubitUndo::get_undo_enabled() )
09128      {
09129        DLIList<Body*> bodies_to_save;
09130        bodies_to_save += webcut_body_list;
09131        bodies_to_save += neighboring_bodies;
09132        CubitUndo::save_state_with_cubit_file( bodies_to_save );
09133      }
09134 
09135      int i;
09136      for( i=neighboring_bodies.size(); i--; )
09137      {
09138        Body *neighbor_body = neighboring_bodies.get_and_step();
09139        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
09140        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
09141 
09142        if( gme == neighbor_gme )
09143          neighbor_imprint_list.append( tmp_body );
09144      }
09145 
09146      do_attribute_setup();
09147      DLIList<BodySM*> bodies_sm_to_modify;
09148      bodies_sm_to_modify += body_sm_list;
09149      bodies_sm_to_modify += neighbor_imprint_list;
09150      push_attributes_before_modify( bodies_sm_to_modify );
09151      bodies_to_modify += webcut_body_list;
09152      bodies_to_modify += neighboring_bodies;
09153      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
09154    }
09155 
09156    BodySM* cutting_tool_ptr = NULL;
09157    CubitStatus stat = prepare_surface_sweep(body_sm_list,surfaces_to_sweep,
09158                            sweep_axis,false,false,false,
09159                            up_to_next,stop_surface, NULL, cutting_tool_ptr, &point, &angle);
09160    if(stat == CUBIT_SUCCESS )
09161    {
09162      stat = gme->webcut( body_sm_list, cutting_tool_ptr, neighbor_imprint_list,
09163                          new_sms, imprint_type, preview );
09164 
09165      // Delete the BodySM that was created to be used as a tool
09166      gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
09167    }
09168 
09169    else
09170    {
09171      PRINT_ERROR("Can't create a swept surface for webcut.\n");
09172      return CUBIT_FAILURE;
09173    }
09174 
09175    // if not previewing do the rest of the creation
09176    if (!preview)
09177    {
09178      restore_vg_after_modify(new_sms, bodies_to_modify, gme);
09179      remove_pushed_attributes(new_sms, bodies_to_modify);
09180      stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
09181                           &merged_surface_ids, &merged_curve_ids );
09182      do_attribute_cleanup();
09183 
09184      if( CubitUndo::get_undo_enabled() )
09185      {
09186        if( stat == CUBIT_SUCCESS )
09187          CubitUndo::note_result_bodies( new_bodies );
09188        else
09189          CubitUndo::remove_last_undo();
09190      }
09191    }
09192 
09193    return stat;
09194 }
09195 
09196 CubitStatus GeometryModifyTool::webcut_with_sweep_curves_rotated(
09197                             DLIList<Body*> &webcut_body_list,
09198                             DLIList<RefEdge*> &tool_curves,
09199                             CubitVector &point,
09200                             CubitVector &sweep_axis,
09201                             double angle,
09202                             RefFace* stop_surf,
09203                             DLIList<Body*> &new_bodies,
09204                             DLIList<Body*> &neighboring_bodies,
09205                             ImprintType imprint_type,
09206                             CubitBoolean merge,
09207                             CubitBoolean preview)
09208 {
09209 
09210    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
09211      return CUBIT_FAILURE;
09212 
09213    GfxPreview::clear();
09214 
09215    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
09216    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
09217    DLIList<Curve*> curves_to_sweep;
09218    if (gme)
09219    {
09220      DLIList<RefFace*> dummy1;
09221      DLIList<Surface*> dummy2;
09222      GeometryModifyEngine* surf_gme = common_modify_engine( dummy1, tool_curves,
09223                                                             dummy2, curves_to_sweep );
09224      if( gme != surf_gme )
09225        PRINT_ERROR("All geometry not from the same modeling engine.\n");
09226    }
09227 
09228    Surface *stop_surface = NULL;
09229    if( stop_surf )
09230    {
09231      GeometryModifyEngine *tmp_gme = get_engine(stop_surf);
09232 
09233      if( gme != tmp_gme )
09234      {
09235        PRINT_ERROR("Stop surface %d is not of same modeling engine as other input geometry.\n",
09236                     stop_surf->id() );
09237        return CUBIT_FAILURE;
09238      }
09239 
09240      stop_surface = stop_surf->get_surface_ptr();
09241    }
09242 
09243    DLIList<int> merged_surface_ids;
09244    DLIList<int> merged_curve_ids;
09245    DLIList<BodySM*> neighbor_imprint_list;
09246    DLIList<Body*> bodies_to_modify;
09247 
09248    if (!preview)
09249    {
09250      if( CubitUndo::get_undo_enabled() )
09251      {
09252        DLIList<Body*> bodies_to_save;
09253        bodies_to_save += webcut_body_list;
09254        bodies_to_save += neighboring_bodies;
09255        CubitUndo::save_state_with_cubit_file( bodies_to_save );
09256      }
09257 
09258      int i;
09259      for( i=neighboring_bodies.size(); i--; )
09260      {
09261        Body *neighbor_body = neighboring_bodies.get_and_step();
09262        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
09263        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
09264 
09265        if( gme == neighbor_gme )
09266          neighbor_imprint_list.append( tmp_body );
09267      }
09268 
09269      do_attribute_setup();
09270      DLIList<BodySM*> bodies_sm_to_modify;
09271      bodies_sm_to_modify += body_sm_list;
09272      bodies_sm_to_modify += neighbor_imprint_list;
09273      push_attributes_before_modify( bodies_sm_to_modify );
09274      bodies_to_modify += webcut_body_list;
09275      bodies_to_modify += neighboring_bodies;
09276      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
09277    }
09278 
09279    //sweep the curves.
09280    DLIList<GeometryEntity*> ref_ent_list;
09281    for(int i = 0; i < curves_to_sweep.size(); i++)
09282      ref_ent_list.append((GeometryEntity*)(curves_to_sweep.get_and_step()));
09283 
09284    DLIList<BodySM*> swept_bodies;
09285    CubitStatus stat = gme->sweep_rotational(ref_ent_list,swept_bodies,point,
09286                                       sweep_axis,angle,0, 0.0, 0,false,false,
09287                                       false,stop_surface);
09288    if(stat == CUBIT_FAILURE  && swept_bodies.size() == 0)
09289      return stat;
09290 
09291    //stitch faces together
09292    BodySM* cutting_tool_ptr = NULL;
09293    DLIList<BodySM*> cutting_tools;
09294    stat = gme->stitch(swept_bodies, cutting_tools, CUBIT_FALSE, 1E-6);
09295 
09296    if(cutting_tools.size() > 1 || cutting_tools.size() == 0)
09297      {
09298        //delete all swept faces
09299        for(int i = 0; i < cutting_tools.size(); i++)
09300          gme->get_gqe()->delete_solid_model_entities(cutting_tools.get_and_step()) ;
09301        return stat;
09302      }
09303    else
09304    {
09305      cutting_tool_ptr = cutting_tools.get();
09306      stat = gme->webcut( body_sm_list, cutting_tool_ptr, neighbor_imprint_list,
09307                          new_sms, imprint_type, preview);
09308 
09309      // Delete the BodySM that was created to be used as a tool
09310      gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
09311    }
09312 
09313    if (!preview)
09314    {
09315      restore_vg_after_modify(new_sms, bodies_to_modify, gme);
09316      remove_pushed_attributes(new_sms, bodies_to_modify);
09317      stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
09318                           &merged_surface_ids, &merged_curve_ids );
09319      do_attribute_cleanup();
09320 
09321      if( CubitUndo::get_undo_enabled() )
09322      {
09323        if( stat == CUBIT_SUCCESS )
09324          CubitUndo::note_result_bodies( new_bodies );
09325        else
09326          CubitUndo::remove_last_undo();
09327      }
09328    }
09329 
09330    return stat;
09331 }
09332 
09333 CubitStatus GeometryModifyTool::webcut_with_sweep_curves(
09334                             DLIList<Body*> &webcut_body_list,
09335                             DLIList<RefEdge*> &tool_curves,
09336                             const CubitVector sweep_vector,
09337                             bool through_all,
09338                             RefFace *stop_surf,
09339                             RefEdge* edge_to_sweep_along,
09340                             DLIList<Body*> &new_bodies,
09341                             DLIList<Body*> &neighboring_bodies,
09342                             ImprintType imprint_type,
09343                             CubitBoolean merge,
09344                             CubitBoolean preview)
09345 {
09346    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
09347      return CUBIT_FAILURE;
09348 
09349    GfxPreview::clear();
09350 
09351    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
09352    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
09353    DLIList<Curve*> curves_to_sweep;
09354    if (gme)
09355    {
09356      DLIList<RefFace*> dummy1;
09357      DLIList<Surface*> dummy2;
09358      GeometryModifyEngine* surf_gme = common_modify_engine( dummy1, tool_curves,
09359                                                             dummy2, curves_to_sweep );
09360      if( gme != surf_gme ){
09361        PRINT_ERROR("All geometry not from the same modeling engine.\n");
09362        return CUBIT_FAILURE;
09363      }
09364    }
09365    else{
09366      PRINT_ERROR("All volumes not from the same modeling engine.\n");
09367      return CUBIT_FAILURE;
09368    }
09369 
09370    Surface *stop_surface = NULL;
09371    if( stop_surf )
09372    {
09373      GeometryModifyEngine *tmp_gme = get_engine(stop_surf);
09374 
09375      if( gme != tmp_gme )
09376      {
09377        PRINT_ERROR("Stop surface %d is not of same modeling engine as other input geometry.\n",
09378                     stop_surf->id() );
09379        return CUBIT_FAILURE;
09380      }
09381 
09382      stop_surface = stop_surf->get_surface_ptr();
09383    }
09384 
09385    Curve *curve_to_sweep_along = NULL;
09386    if( edge_to_sweep_along )
09387    {
09388      GeometryModifyEngine *tmp_gme = get_engine(edge_to_sweep_along);
09389 
09390      if( gme != tmp_gme )
09391      {
09392        PRINT_ERROR("Curve %d does is not of same modeling as other input geometry.\n",
09393                     edge_to_sweep_along->id() );
09394        return CUBIT_FAILURE;
09395      }
09396 
09397      curve_to_sweep_along = edge_to_sweep_along->get_curve_ptr();
09398    }
09399 
09400    DLIList<int> merged_surface_ids;
09401    DLIList<int> merged_curve_ids;
09402    DLIList<BodySM*> neighbor_imprint_list;
09403    DLIList<Body*> bodies_to_modify;
09404 
09405    if (!preview)
09406    {
09407      if( CubitUndo::get_undo_enabled() )
09408      {
09409        DLIList<Body*> bodies_to_save;
09410        bodies_to_save += webcut_body_list;
09411        bodies_to_save += neighboring_bodies;
09412        CubitUndo::save_state_with_cubit_file( bodies_to_save );
09413      }
09414 
09415      int i;
09416      for( i=neighboring_bodies.size(); i--; )
09417      {
09418        Body *neighbor_body = neighboring_bodies.get_and_step();
09419        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
09420        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
09421 
09422        if( gme == neighbor_gme )
09423          neighbor_imprint_list.append( tmp_body );
09424      }
09425 
09426      do_attribute_setup();
09427      DLIList<BodySM*> bodies_sm_to_modify;
09428      bodies_sm_to_modify += body_sm_list;
09429      bodies_sm_to_modify += neighbor_imprint_list;
09430      push_attributes_before_modify( bodies_sm_to_modify );
09431      bodies_to_modify += webcut_body_list;
09432      bodies_to_modify += neighboring_bodies;
09433      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
09434    }
09435 
09436    CubitVector tmp_sweep_vector = sweep_vector;
09437     //get model bbox info...will scale sweep vector by its diagonal
09438     //so that we go far enough
09439     if( through_all || stop_surf )
09440       {
09441         CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box();
09442         tmp_sweep_vector.normalize();
09443         tmp_sweep_vector*=(2*bounding_box.diagonal().length());
09444       }
09445 
09446     DLIList<GeometryEntity*> ref_ent_list;
09447     for(int i = 0; i < curves_to_sweep.size(); i++)
09448       ref_ent_list.append((GeometryEntity*)(curves_to_sweep.get_and_step()));
09449     DLIList<BodySM*> swept_bodies;
09450     CubitStatus stat;
09451 
09452     if( curve_to_sweep_along )
09453     {
09454       DLIList<Curve*> curves_to_sweep_along;
09455       curves_to_sweep_along.append(curve_to_sweep_along);
09456       stat = gme->sweep_along_curve(ref_ent_list, swept_bodies,
09457                                curves_to_sweep_along,0.0,0,false,stop_surface);
09458 
09459       if (!stat && swept_bodies.size() == 0)
09460         return stat;
09461     }
09462 
09463     else
09464     {
09465       stat = gme->sweep_translational(ref_ent_list, swept_bodies,
09466                              tmp_sweep_vector,0.0,0, false, false, stop_surface);
09467 
09468       if (!stat && swept_bodies.size() == 0)
09469         return stat;
09470     }
09471 
09472     //stitch faces together
09473     BodySM* cutting_tool_ptr = NULL;
09474     DLIList<BodySM*> cutting_tools;
09475     stat = gme->stitch(swept_bodies, cutting_tools, CUBIT_FALSE, 1E-6);
09476 
09477     if(cutting_tools.size() > 1 || cutting_tools.size() == 0)
09478     {
09479         //delete all swept faces
09480         for(int i = 0; i < cutting_tools.size(); i++)
09481           gme->get_gqe()->delete_solid_model_entities(cutting_tools.get_and_step()) ;
09482         return CUBIT_FAILURE;
09483     }
09484     else
09485     {
09486         cutting_tool_ptr = cutting_tools.get();
09487         stat = gme->webcut( body_sm_list, cutting_tool_ptr, neighbor_imprint_list,
09488                             new_sms, imprint_type, preview );
09489 
09490         // Delete the BodySM that was created to be used as a tool
09491         gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
09492     }
09493 
09494    if (!preview)
09495    {
09496      restore_vg_after_modify(new_sms, bodies_to_modify, gme);
09497      remove_pushed_attributes(new_sms, bodies_to_modify);
09498      stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
09499                           &merged_surface_ids, &merged_curve_ids );
09500      do_attribute_cleanup();
09501 
09502      if( CubitUndo::get_undo_enabled() )
09503      {
09504        if( stat == CUBIT_SUCCESS )
09505          CubitUndo::note_result_bodies( new_bodies );
09506        else
09507          CubitUndo::remove_last_undo();
09508      }
09509    }
09510 
09511    return stat;
09512 }
09513 
09514 CubitStatus GeometryModifyTool::webcut_with_sweep_surfaces(
09515                             DLIList<Body*> &webcut_body_list,
09516                             DLIList<RefFace*> &tool_faces,
09517                             const CubitVector sweep_vector,
09518                             bool sweep_perp,
09519                             bool through_all,
09520                             bool outward,
09521                             bool up_to_next,
09522                             RefFace* stop_surf,
09523                             RefEdge* edge_to_sweep_along,
09524                             DLIList<Body*> &new_bodies,
09525                             DLIList<Body*> &neighboring_bodies,
09526                             ImprintType imprint_type,
09527                             CubitBoolean merge,
09528                             CubitBoolean preview)
09529 {
09530    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
09531      return CUBIT_FAILURE;
09532 
09533    GfxPreview::clear();
09534 
09535    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
09536    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
09537    DLIList<Surface*> surfaces_to_sweep;
09538    if (gme)
09539    {
09540      GeometryModifyEngine* surf_gme = common_modify_engine( tool_faces, surfaces_to_sweep );
09541      if( gme != surf_gme ){
09542        PRINT_ERROR("All geometry not from the same modeling engine.\n");
09543        return CUBIT_FAILURE;
09544      }
09545    }
09546    else{
09547      PRINT_ERROR("All volumes not from the same modeling engine.\n");
09548      return CUBIT_FAILURE;
09549    }
09550 
09551    Surface *stop_surface = NULL;
09552    if( stop_surf )
09553    {
09554      GeometryModifyEngine *tmp_gme = get_engine(stop_surf);
09555 
09556      if( gme != tmp_gme )
09557      {
09558        PRINT_ERROR("Stop surface %d is not of same modeling engine as other input geometry.\n",
09559                     stop_surf->id() );
09560        return CUBIT_FAILURE;
09561      }
09562 
09563      stop_surface = stop_surf->get_surface_ptr();
09564    }
09565 
09566    Curve *curve_to_sweep_along = NULL;
09567    if( edge_to_sweep_along )
09568    {
09569      GeometryModifyEngine *tmp_gme = get_engine(edge_to_sweep_along);
09570 
09571      if( gme != tmp_gme )
09572      {
09573        PRINT_ERROR("Curve %d does is not of same modeling as other input geometry.\n",
09574                     edge_to_sweep_along->id() );
09575        return CUBIT_FAILURE;
09576      }
09577 
09578      //make sure that the curve is not part of the surface(s) being swept
09579      DLIList<RefFace*> faces_of_edge;
09580      edge_to_sweep_along->ref_faces( faces_of_edge );
09581 
09582      int kk;
09583      for( kk=faces_of_edge.size(); kk--; )
09584      {
09585        if( tool_faces.is_in_list( faces_of_edge.get_and_step() ) )
09586        {
09587          faces_of_edge.back();
09588          PRINT_ERROR("Cannot perform sweep.  Curve %d is in Surface %d\n",
09589                       edge_to_sweep_along->id(), faces_of_edge.get()->id() );
09590          return CUBIT_FAILURE;
09591        }
09592      }
09593 
09594      curve_to_sweep_along = edge_to_sweep_along->get_curve_ptr();
09595    }
09596 
09597    DLIList<BodySM*> neighbor_imprint_list;
09598    DLIList<int> merged_surface_ids;
09599    DLIList<int> merged_curve_ids;
09600    DLIList<Body*> bodies_to_modify;
09601 
09602    if (!preview)
09603    {
09604      if( CubitUndo::get_undo_enabled() )
09605      {
09606        DLIList<Body*> bodies_to_save;
09607        bodies_to_save += webcut_body_list;
09608        bodies_to_save += neighboring_bodies;
09609        CubitUndo::save_state_with_cubit_file( bodies_to_save );
09610      }
09611 
09612      int i;
09613      for( i=neighboring_bodies.size(); i--; )
09614      {
09615        Body *neighbor_body = neighboring_bodies.get_and_step();
09616        BodySM *tmp_body = neighbor_body->get_body_sm_ptr();
09617        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
09618 
09619        if( gme == neighbor_gme )
09620          neighbor_imprint_list.append( tmp_body );
09621      }
09622 
09623      do_attribute_setup();
09624      DLIList<BodySM*> bodies_sm_to_modify;
09625      bodies_sm_to_modify += body_sm_list;
09626      bodies_sm_to_modify += neighbor_imprint_list;
09627      push_attributes_before_modify( bodies_sm_to_modify );
09628      bodies_to_modify += webcut_body_list;
09629      bodies_to_modify += neighboring_bodies;
09630      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
09631    }
09632 
09633    BodySM* cutting_tool_ptr = NULL;
09634    CubitStatus stat = prepare_surface_sweep(
09635       body_sm_list, surfaces_to_sweep, sweep_vector, sweep_perp, through_all, outward,
09636       up_to_next, stop_surface, curve_to_sweep_along, cutting_tool_ptr );
09637    if (stat == CUBIT_SUCCESS)
09638    {
09639       stat = gme->webcut( body_sm_list, cutting_tool_ptr, neighbor_imprint_list,
09640                           new_sms, imprint_type, preview );
09641 
09642       // Delete the BodySM that was created to be used as a tool
09643       gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
09644    }
09645 
09646    if (!preview)
09647    {
09648      restore_vg_after_modify(new_sms, bodies_to_modify, gme);
09649      remove_pushed_attributes(new_sms, bodies_to_modify);
09650      stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
09651                           &merged_surface_ids, &merged_curve_ids );
09652      do_attribute_cleanup();
09653 
09654      if( CubitUndo::get_undo_enabled() )
09655      {
09656        if( stat  == CUBIT_SUCCESS )
09657          CubitUndo::note_result_bodies( new_bodies );
09658        else
09659          CubitUndo::remove_last_undo();
09660      }
09661    }
09662 
09663    return stat;
09664 }
09665 
09666 CubitStatus GeometryModifyTool::split_free_curve(RefEdge *ref_edge,
09667                                                   DLIList<CubitVector> &split_locations,
09668                                                   DLIList<RefEdge*> &new_ref_edges )
09669 {
09670   TopologyBridge* bridge = 0;
09671   GeometryModifyEngine* gme_ptr = get_engine(ref_edge, &bridge);
09672   Curve *curve = dynamic_cast<Curve*>(bridge);
09673 
09674   if( CubitUndo::get_undo_enabled() )
09675   {
09676     DLIList<RefEdge*> tmp_ents(1);
09677     tmp_ents.append( ref_edge );
09678     CubitUndo::save_state_with_cubit_file( tmp_ents );
09679   }
09680 
09681   DLIList<Curve*> new_curves;
09682   if(split_locations.size() == 1)
09683     gme_ptr->split_curve(curve, (split_locations.get()), new_curves);
09684   else
09685     gme_ptr->split_free_curve( curve, split_locations, new_curves );
09686 
09687   if (!new_curves.size())
09688   {
09689     if( CubitUndo::get_undo_enabled() )
09690       CubitUndo::remove_last_undo();
09691     return CUBIT_FAILURE;
09692   }
09693 
09694   GeometryQueryTool::instance()->delete_RefEdge( ref_edge );
09695 
09696   int i;
09697   for( i=0; i<new_curves.size(); i++ )
09698   {
09699     Curve *new_curve = new_curves.get_and_step();
09700     RefEdge* new_edge = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
09701     if(new_edge)
09702       new_ref_edges.append(new_edge);
09703     if( CubitUndo::get_undo_enabled() )
09704       CubitUndo::note_result_entity( new_edge );
09705   }
09706 
09707   return CUBIT_SUCCESS;
09708 }
09709 
09710 //-------------------------------------------------------------------------
09711 // Purpose       : split a multiple volume body into several bodies
09712 //                 each containing a single volume.
09713 //
09714 // Special Notes :
09715 //
09716 // Creator       : David White
09717 //
09718 // Creation Date : 09/26/97
09719 //-------------------------------------------------------------------------
09720 CubitStatus GeometryModifyTool::split_body( Body *body_ptr,
09721                                             DLIList<Body*> &new_bodies ) const
09722 {
09723   int i;
09724   DLIList<RefVolume*> ref_vols;
09725   body_ptr->ref_volumes(ref_vols);
09726   if ( ref_vols.size() < 2 )
09727   {
09728     //no need to split...
09729     new_bodies.append(body_ptr);
09730     return CUBIT_SUCCESS;
09731   }
09732 
09733   DLIList<Body*> b_list;
09734   b_list.append(body_ptr);
09735   if (!okay_to_modify( b_list, "SPLIT" ))
09736     return CUBIT_FAILURE;
09737 
09738   // Call the owning GeometryModifyEngine to split the body
09739   // so that there is one volume per body.
09740   BodySM* bodysm_ptr = body_ptr->get_body_sm_ptr();
09741   GeometryModifyEngine* engine_ptr = get_engine(bodysm_ptr);
09742   if (!engine_ptr) {
09743     PRINT_ERROR("There is no modify engine available for this volume."
09744       " Volume cannot be split.\n");
09745     return CUBIT_FAILURE;
09746   }
09747 
09748   if( CubitUndo::get_undo_enabled() )
09749   {
09750     DLIList<Body*> bodies(1);
09751     bodies.append( body_ptr );
09752     CubitUndo::save_state_with_cubit_file( bodies );
09753   }
09754 
09755   DLIList<BodySM*> new_sm_list;
09756   CubitStatus stat = engine_ptr->split_body( bodysm_ptr, new_sm_list );
09757   if ( new_sm_list.size() == 0 )
09758   {
09759     PRINT_ERROR("failed in splitting volumes, orginal was lost.\n");
09760     GeometryQueryTool::instance()->destroy_dead_entity(body_ptr);
09761     return CUBIT_FAILURE;
09762   }
09763 
09764   bodysm_ptr = body_ptr->get_body_sm_ptr();
09765   if (bodysm_ptr)
09766   {
09767     remove_dead_entity_names(body_ptr);
09768     body_ptr = GeometryQueryTool::instance()->make_Body(bodysm_ptr);
09769   }
09770   else
09771   {
09772     GeometryQueryTool::instance()->destroy_dead_entity(body_ptr);
09773   }
09774 
09775   new_sm_list.reset();
09776   for (i = new_sm_list.size(); i--; )
09777   {
09778     bodysm_ptr = new_sm_list.get_and_step();
09779     Body* body = GeometryQueryTool::instance()->make_Body(bodysm_ptr);
09780     new_bodies.append(body);
09781   }
09782 
09783   if ( !GeometryModifyTool::instance()->get_new_ids())
09784   {
09785     //Now reuse the body ids.
09786     DLIList<RefVolume*> new_ref_vols;
09787     for ( int ii = new_bodies.size(); ii > 0; ii-- )
09788     {
09789       Body *temp_body = new_bodies.get_and_step();
09790       new_ref_vols.clean_out();
09791       temp_body->ref_volumes(new_ref_vols);
09792       int vol_id = new_ref_vols.get()->id();
09793       if ( temp_body->id() != vol_id )
09794       {
09795         //Check to see if this id is being used by
09796         //some other body.
09797         if ( RefEntityFactory::instance()->get_body(vol_id) == NULL )
09798         {
09799           temp_body->set_id(vol_id);
09800         }
09801         //if it is in use, then we shouldn't mess around with it...
09802       }
09803     }
09804   }
09805 
09806   if( CubitUndo::get_undo_enabled() )
09807     CubitUndo::note_result_bodies( new_bodies );
09808 
09809   GeometryQueryTool::instance()->cleanout_deactivated_geometry();
09810   return stat;
09811 }
09812 
09813 //-------------------------------------------------------------------------
09814 // Purpose       : Separate surfaces from a sheet body into separate bodies.
09815 //                 Connected surfaces will remain united but be placed in
09816 //                 a new body.
09817 //
09818 // Special Notes :
09819 //
09820 // Creator       : Steve Storm
09821 //
09822 // Creation Date : 02/23/2008
09823 //-------------------------------------------------------------------------
09824 CubitStatus
09825 GeometryModifyTool::separate_surfaces( DLIList<RefFace*> &ref_face_list,
09826                                        DLIList<Body*> &new_bodies )
09827 {
09828   int i;
09829   RefFace *ref_face_ptr;
09830 
09831   for( i=ref_face_list.size(); i--; )
09832   {
09833     ref_face_ptr = ref_face_list.get();
09834 
09835     // Check for no body
09836     DLIList<Body*> body_list;
09837     ref_face_ptr->bodies( body_list );
09838     if( body_list.size()==0 )
09839     {
09840       PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
09841         "       It cannot be separated.\n", ref_face_ptr->id() );
09842       return CUBIT_FAILURE;
09843     }
09844   }
09845 
09846   // Check for virtual geometry
09847   DLIList<RefEntity*> ref_ent_list;
09848   CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
09849   if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
09850   {
09851     PRINT_ERROR("SEPARATING surfaces containing virtual geometry is not\n"
09852       "       allowed. Delete virtual geometry on these surfaces\n"
09853       "       before operation.\n" );
09854     return CUBIT_FAILURE;
09855   }
09856 
09857   // Prep for undo
09858   DLIList<Body*> body_list;
09859   for( i=ref_face_list.size(); i--; )
09860     ref_face_list.get_and_step()->bodies( body_list );
09861   body_list.uniquify_ordered();
09862 
09863   if( CubitUndo::get_undo_enabled() )
09864     CubitUndo::save_state_with_cubit_file( body_list );
09865 
09866   // Handle surfaces from different modify engines.  Copy the input list since
09867   // we will be pulling RefFaces out of it.
09868   DLIList<RefFace*> copied_ref_face_list = ref_face_list;
09869 
09870   // Keep track of errors and success
09871   int error_occurred = 0;
09872   int successful_case = 0;
09873 
09874   GeometryModifyEngine *gme_ptr;
09875   while( copied_ref_face_list.size() )
09876   {
09877     // Need to send in Surfaces
09878     DLIList<Surface*> surface_list;
09879     DLIList<RefFace*> gme_face_list;
09880 
09881     gme_ptr = pull_common_surfs( copied_ref_face_list, gme_face_list,
09882                                  surface_list );
09883     if( !gme_ptr )
09884       return CUBIT_FAILURE;
09885 
09886     // Get the owning bodies of the faces...needed for finish_sm_op
09887     DLIList<Body*> gme_body_list;
09888     for( i=gme_face_list.size(); i--; )
09889       gme_face_list.get_and_step()->bodies( gme_body_list );
09890     gme_body_list.uniquify_ordered();
09891 
09892     DLIList<BodySM*> new_sm_list;
09893     DLIList<Body*> new_body_list;
09894     if( gme_ptr->separate_surfaces( surface_list, new_sm_list ) == CUBIT_FAILURE ||
09895         finish_sm_op(gme_body_list, new_sm_list, new_body_list ) == CUBIT_FAILURE )
09896     {
09897       error_occurred++;
09898       continue;
09899     }
09900 
09901     new_bodies += new_body_list;
09902     successful_case++;
09903   }
09904 
09905   if( error_occurred && !successful_case )
09906     return CUBIT_FAILURE;
09907 
09908   // Following is copied from split_body - to keep same behavior. When all
09909   // surfaces are separated from a given body, separate_surfaces just separates
09910   // the body. Without the code below we get new body ids.
09911   if ( !GeometryModifyTool::instance()->get_new_ids())
09912   {
09913     //Now reuse the body ids.
09914     DLIList<RefVolume*> new_ref_vols;
09915     for ( int ii = new_bodies.size(); ii > 0; ii-- )
09916     {
09917       Body *temp_body = new_bodies.get_and_step();
09918       new_ref_vols.clean_out();
09919       temp_body->ref_volumes(new_ref_vols);
09920       int vol_id = new_ref_vols.get()->id();
09921       if ( temp_body->id() != vol_id )
09922       {
09923         //Check to see if this id is being used by
09924         //some other body.
09925         if ( RefEntityFactory::instance()->get_body(vol_id) == NULL )
09926         {
09927           temp_body->set_id(vol_id);
09928         }
09929         //if it is in use, then we shouldn't mess around with it...
09930       }
09931     }
09932   }
09933 
09934   if( CubitUndo::get_undo_enabled() )
09935     CubitUndo::note_result_bodies( new_bodies );
09936 
09937   return CUBIT_SUCCESS;
09938 }
09939 
09940 //-------------------------------------------------------------------------
09941 // Purpose       : Reverse a body
09942 //
09943 // Special Notes : Moved from Body
09944 //
09945 // Creator       : Jason Kraftcheck
09946 //
09947 // Creation Date :
09948 //-------------------------------------------------------------------------
09949 CubitStatus GeometryModifyTool::reverse( DLIList<Body*> &body_list )
09950 {
09951    DLIList<Body*> reversed_bodies;
09952    int i;
09953    for( i=body_list.size(); i--; )
09954    {
09955      Body *body = body_list.get_and_step();
09956      BodySM* body_sm = body->get_body_sm_ptr();
09957      GeometryModifyEngine* gme = get_engine( body_sm );
09958      if (!gme) {
09959         PRINT_ERROR("Body %d does not have a modify engine.\n", body->id());
09960         continue;
09961      }
09962 
09963      CubitStatus stat = gme->reverse_body( body_sm );
09964 
09965      if ( CUBIT_SUCCESS != stat )
09966      {
09967        PRINT_ERROR("Reverse failed.\n");
09968        continue;
09969      }
09970      else
09971      {
09972        reversed_bodies.append( body );
09973        GeometryQueryTool::instance()->make_Body( body_sm );
09974        AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, body));
09975        PRINT_INFO("Reversed body %d.\n", body->id());
09976        continue;
09977      }
09978    }
09979 
09980    if( CubitUndo::get_undo_enabled() )
09981    {
09982      CubitString undo_command("reverse body ");
09983      for( i=reversed_bodies.size(); i--; )
09984      {
09985        undo_command += CubitString::number(reversed_bodies.get_and_step()->id());
09986        undo_command += " ";
09987      }
09988      CubitUndo::set_undo_by_command( undo_command );
09989    }
09990 
09991    return CUBIT_SUCCESS;
09992 }
09993 
09994 //===============================================================================
09995 // Function   : reverse
09996 // Member Type: PUBLIC
09997 // Description: Reverse given surfaces (flip normals)
09998 // Author     : Steve Storm (CAT)
09999 // Date       : 4/3/2007
10000 //===============================================================================
10001 CubitStatus GeometryModifyTool::reverse( DLIList<RefFace*> &ref_face_list )
10002 {
10003   // Check for virtual geometry
10004   DLIList<RefEntity*> ref_ent_list;
10005   CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
10006   if( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
10007   {
10008     PRINT_ERROR("REVERSING surfaces containing virtual geometry is not\n"
10009       "       allowed. Delete virtual geometry on surfaces before\n"
10010       "       operation.\n" );
10011     return CUBIT_FAILURE;
10012   }
10013 
10014   // Get the owning bodies of the faces
10015   int i;
10016   DLIList<Body*> body_list;
10017   for( i=ref_face_list.size(); i--; )
10018     ref_face_list.get_and_step()->bodies( body_list );
10019   body_list.uniquify_ordered();
10020 
10021   // Handle surfaces from different modify engines.  Copy the input list since
10022   // we will be pulling RefFaces out of it.
10023   DLIList<RefFace*> copied_ref_face_list = ref_face_list;
10024 
10025   // Keep track of overall errors and successes
10026   int error_occurred = 0;
10027   int successful_case = 0;
10028   GeometryModifyEngine *gme_ptr;
10029 
10030   while( copied_ref_face_list.size() )
10031   {
10032     // Need to send in Surfaces
10033     DLIList<Surface*> surface_list;
10034     DLIList<RefFace*> common_face_list;
10035 
10036     gme_ptr = pull_common_surfs( copied_ref_face_list, common_face_list,
10037                                  surface_list );
10038     if( !gme_ptr )
10039       return CUBIT_FAILURE;
10040 
10041     if( gme_ptr->flip_normals( surface_list ) == CUBIT_FAILURE )
10042       error_occurred = 1;
10043     else
10044       successful_case = 1;
10045   }
10046 
10047   if( error_occurred && !successful_case )
10048     return CUBIT_FAILURE;
10049 
10050   // Update the impacted bodies
10051   Body *body_ptr;
10052   BodySM* body_sm_ptr;
10053   DLIList<BodySM*> new_sm_list;
10054   for( i=body_list.size(); i--; )
10055   {
10056     body_ptr = body_list.get_and_step();
10057     body_sm_ptr = body_ptr->get_body_sm_ptr();
10058     new_sm_list.append( body_sm_ptr );
10059   }
10060 
10061   DLIList<Body*> new_body_list;
10062   CubitStatus status = finish_sm_op(body_list, new_sm_list, new_body_list );
10063 
10064   if( CUBIT_FAILURE == status )
10065     return CUBIT_FAILURE;
10066   
10067   for( int k=0; k< ref_face_list.size(); k++ )
10068     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, ref_face_list.get_and_step() ));  
10069 
10070   return CUBIT_SUCCESS;
10071 }
10072 
10073 //-------------------------------------------------------------------------
10074 // Purpose       : split a periodic surface.
10075 //
10076 // Special Notes :
10077 //
10078 // Creator       : David White
10079 //
10080 // Creation Date : 09/26/97
10081 //-------------------------------------------------------------------------
10082 
10083 CubitStatus GeometryModifyTool::split_periodic(Body *body_ptr,
10084                                                Body *&new_body_ptr )
10085 {
10086    DLIList<Body*> b_list(1);
10087    b_list.append(body_ptr);
10088    if (!okay_to_modify( b_list, "SPLIT" ))
10089      return CUBIT_FAILURE;
10090 
10091    BodySM* body_sm = body_ptr->get_body_sm_ptr();
10092    GeometryModifyEngine* gme = get_engine(body_sm);
10093    if (!gme) {
10094       PRINT_ERROR("Volume %d does not have a modify engine.\n", body_ptr->id());
10095       return CUBIT_FAILURE;
10096    }
10097 
10098    BodySM* new_sm = 0;
10099 
10100    if (CubitUndo::get_undo_enabled())
10101      CubitUndo::save_state_with_cubit_file(b_list);
10102 
10103    DLIList<BodySM*> body_sms;
10104    body_sms.append(body_sm);
10105 
10106    do_attribute_setup();
10107    push_attributes_before_modify(body_sms);
10108 
10109    // Call the default GeometryModifyEngine to create a new TBPoint
10110    CubitStatus stat = gme->split_periodic( body_sm, new_sm );
10111 
10112    DLIList<BodySM*> new_bodysm_list;
10113    if(new_sm)
10114      new_bodysm_list.append(new_sm);
10115    DLIList<Body*> old_body_list;
10116    old_body_list.append(body_ptr);
10117    restore_vg_after_modify(new_bodysm_list, old_body_list, gme);
10118    remove_pushed_attributes(new_bodysm_list, old_body_list);
10119    do_attribute_cleanup();
10120 
10121    update_body(body_ptr);
10122 
10123    new_body_ptr = 0;
10124    if (new_sm)
10125      new_body_ptr = GeometryQueryTool::instance()->make_Body(new_sm);
10126 
10127    if (new_body_ptr)
10128    {
10129      if (CubitUndo::get_undo_enabled())
10130        CubitUndo::note_result_body(new_body_ptr);
10131    }
10132    else
10133    {
10134      if (CubitUndo::get_undo_enabled())
10135        CubitUndo::remove_last_undo();
10136    }
10137 
10138    GeometryQueryTool::instance()->cleanout_deactivated_geometry();
10139 
10140    return stat;
10141 }
10142 
10143 //===============================================================================
10144 // Function   : split_surface
10145 // Member Type: PUBLIC
10146 // Description: Split a single surface into one or more pieces
10147 // Author     : Steve Storm (CAT)
10148 // Date       : 07/04
10149 //===============================================================================
10150 CubitStatus
10151 GeometryModifyTool::split_surface( RefFace *ref_face_ptr,
10152                                    DLIList<CubitVector*> &locations,
10153                                    DLIList<DLIList<CubitVector*>*> &vec_lists,
10154                                    CubitBoolean preview_flg,
10155                                    CubitBoolean create_ref_edges_flg,
10156                                    CubitBoolean clear_previous_previews )
10157 {
10158   // Check for virtual geometry
10159   DLIList<RefFace*> ref_face_list;
10160   ref_face_list.append( ref_face_ptr );
10161 
10162   DLIList<Body*> b_list;
10163   Body* body = ref_face_ptr->body();
10164   if (body)
10165       b_list.append(body);
10166   else
10167   {
10168       PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
10169           "      It cannot be split.\n", ref_face_ptr->id() );
10170       return CUBIT_FAILURE;
10171   }
10172 
10173   if (!okay_to_modify( b_list, "SPLIT_SURFACE" ))
10174     return CUBIT_FAILURE;
10175 
10176   int i;
10177   DLIList<Body*> old_body_list;
10178   for( i=ref_face_list.size(); i--; )
10179   {
10180     ref_face_ptr = ref_face_list.get_and_step();
10181 
10182     DLIList<Body*> body_list;
10183     ref_face_ptr->bodies( body_list );
10184     old_body_list.merge_unique( body_list );
10185   }
10186 
10187   //bad geom with no body -- dont try to imprint this...
10188   //quick and dirty fix by (aga@cat|1/7/04)
10189   if( old_body_list.size() < 1 )
10190   {
10191     PRINT_ERROR( "Surface %d is not contained within a parent body\n."
10192       "      It cannot be split.\n", ref_face_ptr->id() );
10193     return CUBIT_FAILURE;
10194   }
10195 
10196   SplitSurfaceTool sst;
10197   if( preview_flg == CUBIT_TRUE )
10198     return sst.preview( ref_face_ptr, locations, vec_lists, create_ref_edges_flg,
10199                         clear_previous_previews );
10200   else
10201     return sst.split_surface( ref_face_ptr, vec_lists );
10202 }
10203 
10204 //===============================================================================
10205 // Function   : split_surface
10206 // Member Type: PUBLIC
10207 // Description: Split multiple surfaces
10208 // Author     : Greg Schebler (CAT)
10209 // Date       : 06/08
10210 //===============================================================================
10211 
10212 CubitStatus
10213 GeometryModifyTool::split_surface( DLIList<RefFace*> &ref_face_list,
10214                                   DLIList<CubitVector*> &locations,
10215                                   DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
10216                                   CubitBoolean preview_flg,
10217                                   CubitBoolean create_ref_edges_flg,
10218                                   CubitBoolean clear_previous_previews )
10219 {
10220    // Check for virtual geometry
10221    DLIList<Body*> b_list;
10222    int gg;
10223    for( gg = ref_face_list.size() ; gg > 0 ; gg--)
10224    {
10225       RefFace* ref_face_ptr = ref_face_list.get_and_step();
10226       Body* body = ref_face_ptr->body();
10227       if (body)
10228          b_list.append(body);
10229       else
10230       {
10231          PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
10232             "      It cannot be split.\n", ref_face_ptr->id() );
10233          return CUBIT_FAILURE;
10234       }
10235    }
10236    if (!okay_to_modify( b_list, "SPLIT_SURFACE" ))
10237       return CUBIT_FAILURE;
10238 
10239    int ii;
10240 
10241    for( ii = ref_face_list.size(); ii > 0 ; ii--)
10242    {
10243       DLIList<Body*> old_body_list;
10244       RefFace* ref_face_ptr = ref_face_list.get_and_step();
10245 
10246       DLIList<Body*> body_list;
10247       ref_face_ptr->bodies( body_list );
10248       old_body_list.merge_unique( body_list );
10249 
10250       if( old_body_list.size() < 1 )
10251       {
10252          PRINT_ERROR( "Surface %d is not contained within a parent body\n."
10253             "      It cannot be split.\n", ref_face_ptr->id() );
10254          return CUBIT_FAILURE;
10255       }
10256    }
10257 
10258    SplitSurfaceTool sst;
10259    if( preview_flg == CUBIT_TRUE )
10260       return sst.preview( ref_face_list, locations, list_of_vec_lists, create_ref_edges_flg,
10261       clear_previous_previews );
10262    else
10263       return sst.split_surface( ref_face_list, list_of_vec_lists );
10264 }
10265 
10266 //===============================================================================
10267 // Function   : split_surfaces_extend
10268 // Member Type: PUBLIC
10269 // Description: Split surfaces by extending hardline curves on the surface
10270 // Author     : Steve Storm (CAT)
10271 // Date       : 10/07
10272 //===============================================================================
10273 CubitStatus
10274 GeometryModifyTool::split_surfaces_extend( DLIList<RefFace*> &ref_face_list,
10275                                            DLIList<RefVertex*> &ref_vertex_list,
10276                                            CubitBoolean preview_flg,
10277                                            CubitBoolean create_ref_edges_flg )
10278 {
10279   int i;
10280   RefFace *ref_face_ptr;
10281 
10282   for( i=ref_face_list.size(); i--; )
10283   {
10284     ref_face_ptr = ref_face_list.get();
10285 
10286     // Check for no body
10287     DLIList<Body*> body_list;
10288     ref_face_ptr->bodies( body_list );
10289     if( body_list.size()==0 )
10290     {
10291       PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
10292         "       It cannot be split.\n", ref_face_ptr->id() );
10293       return CUBIT_FAILURE;
10294     }
10295   }
10296 
10297   // Check for virtual geometry
10298   DLIList<RefEntity*> ref_ent_list;
10299   CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
10300   if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
10301   {
10302     PRINT_ERROR("SPLITTING surfaces containing virtual geometry is not\n"
10303       "       allowed. Delete virtual geometry on these surfaces\n"
10304       "       before operation.\n" );
10305     return CUBIT_FAILURE;
10306   }
10307 
10308   // Make sure all surfaces are from same geometry engine
10309   if ( !same_modify_engine(ref_ent_list, CUBIT_TRUE) )
10310   {
10311     PRINT_ERROR("Performing SPLIT with surfaces containing geometry from\n"
10312       "different modeling engines is not allowed.\n"
10313       "Delete uncommon geometry on these surfaces before operation.\n\n");
10314     return CUBIT_FAILURE;
10315   }
10316 
10317   SplitSurfaceTool sst;
10318   return sst.split_surfaces_extend( ref_face_list, ref_vertex_list,
10319     preview_flg, create_ref_edges_flg );
10320 }
10321 
10322 //===============================================================================
10323 // Function   : split_surfaces
10324 // Member Type: PUBLIC
10325 // Description: Split a chain of surfaces into one or more pieces
10326 // Author     : Steve Storm (CAT)
10327 // Date       : 01/04
10328 //===============================================================================
10329 CubitStatus
10330 GeometryModifyTool::split_surfaces( DLIList<RefFace*> &ref_face_list,
10331                                     int num_segs,
10332                                     double fraction,
10333                                     double distance,
10334                                     RefEdge *from_curve_ptr,
10335                                     DLIList<RefVertex*> &corner_vertex_list,
10336                                     DLIList<RefVertex*> &through_vertex_list,
10337                                     RefEdge *curve_dir_ptr,
10338                                     CubitBoolean preview_flg,
10339                                     CubitBoolean create_ref_edges_flg )
10340 {
10341   // Get parent bodies - all surfs must be from same body
10342   int i;
10343   DLIList<Body*> old_body_list;
10344   RefFace *ref_face_ptr;
10345   ref_face_list.reset();
10346   for( i=ref_face_list.size(); i--; )
10347   {
10348     ref_face_ptr = ref_face_list.get_and_step();
10349 
10350     DLIList<Body*> body_list;
10351     ref_face_ptr->bodies( body_list );
10352     old_body_list.merge_unique( body_list );
10353   }
10354 
10355   if( old_body_list.size() > 1 )
10356   {
10357     PRINT_ERROR( "This operation requires all surfaces to be from the same volume\n" );
10358     // Note: this restriction could be pretty easily lifted by sorting the
10359     //       input lists and calling the SplitSurfaceTool separately for each set of
10360     //       surfaces on each body.
10361     return CUBIT_FAILURE;
10362   }
10363 
10364   //bad geom with no body -- dont try to imprint this...
10365   //quick and dirty fix by (aga@cat|1/7/04)
10366   if( old_body_list.size() < 1 )
10367   {
10368     PRINT_ERROR( "A surface is not contained within a parent body.\n"
10369       "       It cannot be split.\n");
10370     return CUBIT_FAILURE;
10371   }
10372 
10373   // Check for virtual geometry
10374   DLIList<RefEntity*> ref_ent_list;
10375   CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
10376   if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
10377   {
10378     PRINT_ERROR("SPLITTING surfaces containing virtual geometry is not\n"
10379       "       allowed. Delete virtual geometry on these surfaces\n"
10380       "       before operation.\n" );
10381     return CUBIT_FAILURE;
10382   }
10383 
10384   // Make sure all surfaces are from same geometry engine
10385   if ( !same_modify_engine(ref_ent_list, CUBIT_TRUE) )
10386   {
10387     PRINT_ERROR("Performing SPLIT with surfaces containing geometry from\n"
10388       "different modeling engines is not allowed.\n"
10389       "Delete uncommon geometry on these surfaces before operation.\n\n");
10390     return CUBIT_FAILURE;
10391   }
10392 
10393   SplitSurfaceTool split_tool;
10394   return split_tool.split_surfaces( ref_face_list, num_segs, fraction,
10395     distance, from_curve_ptr, corner_vertex_list, through_vertex_list,
10396     curve_dir_ptr, preview_flg, create_ref_edges_flg );
10397 }
10398 
10399 //===============================================================================
10400 // Function   : split_surfaces_offset
10401 // Member Type: PUBLIC
10402 // Description: Split a list of surface offset from a curve
10403 // Author     : Sam Showman (CAT)
10404 // Date       : 05/05
10405 //===============================================================================
10406 CubitStatus
10407 GeometryModifyTool::split_surfaces_offset(DLIList<RefFace*> &ref_face_list,
10408                                           DLIList<RefEdge*> &edge_list,
10409                                           int num_segs,
10410                                           double distance,
10411                                           CubitBoolean partition_flg,
10412                                           CubitBoolean blunt_flg,
10413                                           CubitBoolean preview_flg,
10414                                           CubitBoolean create_ref_edges_flg)
10415 {
10416   int i;
10417   DLIList<Body*> old_body_list;
10418   RefFace *ref_face_ptr;
10419   ref_face_list.reset();
10420   for( i=ref_face_list.size(); i--; )
10421   {
10422     ref_face_ptr = ref_face_list.get_and_step();
10423 
10424     DLIList<Body*> body_list;
10425     ref_face_ptr->bodies( body_list );
10426     old_body_list.merge_unique( body_list );
10427   }
10428 
10429   //check for geometry with no body
10430   if( old_body_list.size() < 1 )
10431   {
10432     PRINT_ERROR( "A surface is not contained within a parent body.\n"
10433       "       It cannot be split.\n");
10434     return CUBIT_FAILURE;
10435   }
10436 
10437   // Check for virtual geometry
10438   DLIList<RefEntity*> ref_ent_list;
10439   CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
10440   if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
10441   {
10442     PRINT_ERROR("SPLITTING surfaces containing virtual geometry is not\n"
10443       "       allowed. Delete virtual geometry on these surfaces\n"
10444       "       before operation.\n" );
10445     return CUBIT_FAILURE;
10446   }
10447 
10448   // Make sure all surfaces are from same geometry engine
10449   // Make sure all curves are from same geometry engine
10450   CAST_LIST_TO_PARENT(edge_list, ref_ent_list);
10451   if ( !same_modify_engine(ref_ent_list, CUBIT_TRUE) )
10452   {
10453     PRINT_ERROR("Performing SPLIT with geometry from\n"
10454       "different modeling engines is not allowed.\n");
10455     return CUBIT_FAILURE;
10456   }
10457 
10458   OffsetSplitTool split_tool;
10459   return split_tool.split_surfaces_offset(
10460       ref_face_list,
10461       edge_list,
10462       num_segs,
10463       distance,
10464       partition_flg,
10465       blunt_flg,
10466       preview_flg,
10467       create_ref_edges_flg);
10468 }
10469 
10470 //===============================================================================
10471 // Function   : auto_mid_surface
10472 // Member Type: PUBLIC
10473 // Description: Automatically midsurface a volume
10474 // Author     : Sam Showman (CAT)
10475 // Date       : 12/07
10476 //===============================================================================
10477 CubitStatus
10478 GeometryModifyTool::auto_mid_surface(DLIList<Body*> &body_list_in,
10479                                      DLIList<Body*> &body_list_out,
10480                                      DLIList<Body*> &old_bodies_midsurfaced,
10481                                      DLIList<double> &thickness_list,
10482                                      double lower_tol,
10483                                      double upper_tol,
10484                                      CubitBoolean delete_midsurfaced,
10485 
10486                                      CubitBoolean preview)
10487 {
10488     // Check for virtual geometry
10489     DLIList<RefEntity*> ref_ent_list;
10490     CAST_LIST_TO_PARENT(body_list_in, ref_ent_list);
10491     if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
10492     {
10493         PRINT_ERROR("Midsurfacing volumes containing virtual geometry is not\n"
10494             "       allowed. Delete virtual geometry on these surfaces\n"
10495             "       before operation.\n" );
10496         return CUBIT_FAILURE;
10497     }
10498 
10499     // Make sure all surfaces are from same geometry engine
10500     if ( !same_modify_engine(ref_ent_list, CUBIT_TRUE) )
10501     {
10502         PRINT_ERROR("Performing Midsurface with geometry from\n"
10503             "different modeling engines is not allowed.\n");
10504         return CUBIT_FAILURE;
10505     }
10506 
10507     AutoMidsurfaceTool mid_tool;
10508     DLIList<BodySM*> bodysm_list_out;
10509 
10510     if (CubitUndo::get_undo_enabled() && delete_midsurfaced && !preview)
10511         CubitUndo::save_state_with_cubit_file(body_list_in);
10512 
10513     CubitStatus result = mid_tool.midsurface(
10514         body_list_in,
10515         bodysm_list_out,
10516         old_bodies_midsurfaced,
10517         thickness_list,
10518         lower_tol,
10519         upper_tol,
10520         delete_midsurfaced,
10521         preview);
10522 
10523 
10524     if (result == CUBIT_SUCCESS &&
10525         bodysm_list_out.size() > 0 &&
10526         !preview)
10527     {
10528         if(CubitUndo::get_undo_enabled())
10529             CubitUndo::save_state();
10530 
10531         for( int i=0; i<bodysm_list_out.size(); i++ )
10532         {
10533             body_list_out.append(GeometryQueryTool::instance()->make_Body(bodysm_list_out[i]));
10534         }
10535 
10536         if( CubitUndo::get_undo_enabled() )
10537         {
10538             if( body_list_out.size() )
10539                 CubitUndo::note_result_bodies( body_list_out );
10540             else
10541                 CubitUndo::remove_last_undo();
10542         }
10543     }
10544 
10545     return result;
10546 }
10547 
10548 //-------------------------------------------------------------------------
10549 // Purpose       : clean RefEntity
10550 //
10551 // Special Notes :
10552 //
10553 // Creator       : Lingyun Pan (CAT)
10554 //
10555 // Creation Date : 07/15/01
10556 //-------------------------------------------------------------------------
10557 
10558 CubitStatus
10559 GeometryModifyTool::regularize_refentity(RefEntity *old_entity_ptr, Body *&new_body_ptr)
10560 {
10561   BasicTopologyEntity* bte_ptr = dynamic_cast<BasicTopologyEntity*>(old_entity_ptr);
10562   if (!bte_ptr)
10563   {
10564     PRINT_ERROR("Invalid entity passed to regularize_refentity(..)\n");
10565     return CUBIT_FAILURE;
10566   }
10567 
10568   DLIList<Body*> body_list;
10569   bte_ptr->bodies(body_list);
10570 
10571   //ignore free entities
10572   if( body_list.size() == 0 )
10573   {
10574     PRINT_ERROR("%s %d is a free entity.  Cannot regularize it.\n", old_entity_ptr->class_name(),
10575                                                                     old_entity_ptr->id() );
10576     new_body_ptr = NULL;
10577     return CUBIT_FAILURE;
10578   }
10579 
10580   if (!okay_to_modify( body_list, "REGULARIZE" ))
10581     return CUBIT_FAILURE;
10582 
10583   DLIList<TopologyBridge*> bridge_list;
10584   // For curves we can try to handle composite curves.
10585   if(dynamic_cast<RefEdge*>(old_entity_ptr))
10586   {
10587     TopologyBridge *first_bridge = bte_ptr->bridge_manager()->topology_bridge();
10588     GeometryQueryEngine *gqe = first_bridge->get_geometry_query_engine();
10589     gqe->get_underlying_bridges(first_bridge, bridge_list);
10590     if(bridge_list.size() == 0)
10591       bridge_list.append(first_bridge);
10592   }
10593   else
10594   {
10595     bte_ptr->bridge_manager()->get_bridge_list(bridge_list);
10596   }
10597 
10598   //bte_ptr->bridge_manager()->get_bridge_list(bridge_list);
10599   bridge_list.reset();
10600 
10601   DLIList<BodySM*> new_sm_list;
10602   DLIList<Body*> new_body_list;
10603   CubitStatus stat = CUBIT_SUCCESS;
10604 
10605   do_attribute_setup();
10606 
10607   GeometryModifyEngine *save_gme = NULL;
10608   for (int i = bridge_list.size(); i--; )
10609   {
10610     TopologyBridge* bridge = bridge_list.get_and_step();
10611     GeometryEntity* geom_ptr = dynamic_cast<GeometryEntity*>(bridge);
10612     GeometryModifyEngine* gme = get_engine(geom_ptr);
10613     if(!save_gme)
10614       save_gme = gme;
10615     if (!gme) continue;
10616 
10617     DLIList<BodySM*> body_sm_list;
10618     geom_ptr->bodysms(body_sm_list);
10619     push_attributes_before_modify(body_sm_list);
10620 
10621     BodySM *new_body_sm = NULL;
10622     if (!gme->regularize_entity( geom_ptr, new_body_sm ))
10623       stat = CUBIT_FAILURE;
10624 
10625     if (new_body_sm)
10626       new_sm_list.append(new_body_sm);
10627   }
10628 
10629   new_sm_list.uniquify_ordered();
10630 
10631   // This is bad in that it assumes all of the gmes will be the
10632   // same but I don't know that we truly support the other case
10633   // anyway.
10634   if(new_sm_list.size())
10635   {
10636     restore_vg_after_modify(new_sm_list, body_list, save_gme);
10637     remove_pushed_attributes(new_sm_list, body_list);
10638   }
10639 
10640   if (!finish_sm_op(body_list, new_sm_list, new_body_list))
10641     stat = CUBIT_FAILURE;
10642 
10643   do_attribute_cleanup();
10644 
10645   new_body_ptr = new_body_list.size() ? new_body_list.get() : 0;
10646   return stat;
10647 }
10648 
10649 CubitStatus GeometryModifyTool::test_regularize_refentity(RefEntity *old_entity_ptr)
10650 {
10651    DLIList<RefEntity*> tmp_ref_ent_list(1);
10652    tmp_ref_ent_list.append( old_entity_ptr );
10653    if( GeometryQueryTool::instance()->contains_intermediate_geometry(tmp_ref_ent_list) )
10654    {
10655      return CUBIT_FAILURE;
10656    }
10657 
10658    BasicTopologyEntity* bte_ptr = dynamic_cast<BasicTopologyEntity*>(old_entity_ptr);
10659    if (!bte_ptr)
10660    {
10661      return CUBIT_FAILURE;
10662    }
10663 
10664    DLIList<TopologyBridge*> bridge_list;
10665    bte_ptr->bridge_manager()->get_bridge_list(bridge_list);
10666    bridge_list.reset();
10667 
10668    CubitStatus stat = CUBIT_SUCCESS;
10669 
10670    for (int i = bridge_list.size(); i--; )
10671    {
10672      TopologyBridge* bridge = bridge_list.get_and_step();
10673      GeometryEntity* geom_ptr = dynamic_cast<GeometryEntity*>(bridge);
10674      GeometryModifyEngine* gme = get_engine(geom_ptr);
10675      if (!gme) continue;
10676 
10677      if (!gme->test_regularize_entity( geom_ptr ))
10678        stat = CUBIT_FAILURE;
10679    }
10680 
10681    return stat;
10682 }
10683 
10684 //-------------------------------------------------------------------------
10685 // Purpose       : split a multiple volume body into several bodies
10686 //                 each containing a single volume.
10687 //
10688 // Special Notes :
10689 //
10690 // Creator       : David White
10691 //
10692 // Creation Date : 09/26/97
10693 //-------------------------------------------------------------------------
10694 
10695 CubitStatus GeometryModifyTool::regularize_body(Body *body_ptr,
10696                                                 Body *&new_body )
10697 {
10698    DLIList<Body*> b_list;
10699    b_list.append(body_ptr);
10700    if (!okay_to_modify( b_list, "REGULARIZE" ))
10701      return CUBIT_FAILURE;   
10702 
10703    BodySM* body_sm = body_ptr->get_body_sm_ptr(), *new_sm = 0;
10704    GeometryModifyEngine* gme = get_engine(body_sm);
10705    if (!gme) {
10706      PRINT_ERROR("Volume does not have a modify engine.\n" );
10707      return CUBIT_FAILURE;
10708   }
10709 
10710    do_attribute_setup();
10711    DLIList<BodySM*> body_sm_list, new_bodysm_list;
10712    body_sm_list.append(body_sm);
10713    push_attributes_before_modify(body_sm_list);
10714 
10715    CubitStatus stat = gme->regularize_body( body_sm, new_sm );
10716    if ( new_sm == NULL )
10717    {
10718       PRINT_ERROR("REGULARIZATION failure.\n");
10719       return CUBIT_FAILURE;
10720    }
10721 
10722    // remove mesh from modified body
10723    AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_ENTITY_MODIFIED, body_ptr));
10724 
10725    new_bodysm_list.append(new_sm);
10726    restore_vg_after_modify(new_bodysm_list, b_list, gme);
10727    remove_pushed_attributes(new_bodysm_list, b_list);
10728 
10729    body_sm = body_ptr->get_body_sm_ptr();
10730    update_body(body_ptr);
10731 
10732    new_body = GeometryQueryTool::instance()->make_Body(new_sm);
10733    GeometryQueryTool::instance()->cleanout_deactivated_geometry();
10734 
10735    do_attribute_cleanup();
10736 
10737    return stat;
10738 }
10739 
10740 CubitStatus
10741 GeometryModifyTool::create_solid_bodies_from_surfs( DLIList<RefFace*> &ref_face_list,
10742                                             DLIList<Body*> &new_bodies,
10743                                             CubitBoolean keep_old,
10744                                             CubitBoolean heal,
10745                                             CubitBoolean sheet ) const
10746 {
10747     //First check to make sure the data is all here.
10748   for ( int ii = ref_face_list.size(); ii > 0; ii-- )
10749   {
10750     RefFace *ref_face = ref_face_list.get_and_step();
10751     DLIList<Body*> bodies;
10752     ref_face->bodies(bodies);
10753     if ( bodies.size() > 1 )
10754     {
10755       PRINT_ERROR("Can't create a volume with %s (surface %d) is attached to more\n"
10756                   "than one volume, or if the attached body is not a sheet body.\n",
10757                   ref_face->entity_name().c_str(),
10758                   ref_face->id());
10759       return CUBIT_FAILURE;
10760     }
10761     else if ( bodies.size() == 1 )
10762     {
10763       if (!bodies.get()->is_sheet_body())
10764       {
10765         PRINT_ERROR("Can't create a volume with %s (surface %d), it is\n"
10766                     "attached to a body that is not a sheet body.\n",
10767                     ref_face->entity_name().c_str(),
10768                     ref_face->id());
10769         return CUBIT_FAILURE;
10770       }
10771     }
10772   }
10773 
10774   DLIList<TopologyEntity*> entity_list(ref_face_list.size());
10775   DLIList<TopologyBridge*> bridge_list(ref_face_list.size());
10776   DLIList<Surface*>       surface_list(ref_face_list.size());
10777   GeometryModifyEngine* gme;
10778 
10779   CAST_LIST_TO_PARENT(ref_face_list, entity_list);
10780   gme = common_modify_engine(entity_list, bridge_list);
10781   CAST_LIST(bridge_list, surface_list, Surface);
10782 
10783   if (!gme) {
10784     PRINT_ERROR("Surfaces do not share a common modify engine.\n");
10785     return CUBIT_FAILURE;
10786   }
10787 
10788   DLIList<TopologyEntity*> query_output, query_input(ref_face_list.size());
10789   DLIList<Body*> body_list;
10790 
10791   CAST_LIST_TO_PARENT(ref_face_list, query_input);
10792   ModelQueryEngine::instance()->
10793     query_model( query_input, DagType::body_type(), query_output );
10794   CAST_LIST( query_output, body_list, Body );
10795 
10796   int i;
10797   DLIList<RefFace*> free_face_list;
10798   for ( i=ref_face_list.size(); i--; )
10799   {
10800     RefFace* ref_face = ref_face_list.get_and_step();
10801     query_output.clean_out();
10802     ModelQueryEngine::instance()->
10803       query_model( *ref_face, DagType::body_type(), query_output );
10804     if (!query_output.size())
10805       free_face_list.append(ref_face);
10806   }
10807 
10808   if (CubitUndo::get_undo_enabled())
10809     CubitUndo::save_state_with_cubit_file(ref_face_list);
10810 
10811   //get all the bodysm's
10812   DLIList<BodySM*> old_body_sm_list;
10813   for( i=body_list.size(); i--; )
10814   {
10815     Body *tmp_body = body_list.get_and_step();
10816     TopologyBridge *tb = tmp_body->bridge_manager()->topology_bridge();
10817     BodySM *tmp_body_sm = CAST_TO(tb, BodySM);
10818     if( tmp_body_sm )
10819       old_body_sm_list.append( tmp_body_sm );
10820   }
10821 
10822   // TODO: do I need a clear and a flush here? --KGM
10823   GeometryModifyTool::instance()->do_attribute_setup();
10824   GeometryModifyTool::instance()->push_attributes_before_modify(old_body_sm_list);
10825 
10826   DLIList<BodySM*> new_bodies_sm;
10827   CubitStatus stat = gme->create_solid_bodies_from_surfs( surface_list, new_bodies_sm, keep_old, heal, sheet );
10828   DLIList<BodySM*> body_sm_list;
10829   for ( i=new_bodies_sm.size(); i--; )
10830     body_sm_list.append( new_bodies_sm.get_and_step() );
10831 
10832   GeometryModifyTool::instance()->restore_vg_after_modify(new_bodies_sm, body_list, gme);
10833   GeometryModifyTool::instance()->remove_pushed_attributes(new_bodies_sm, body_list);
10834 
10835   if (!finish_sm_op( body_list, body_sm_list, new_bodies))
10836   {
10837     stat = CUBIT_FAILURE;
10838     if (CubitUndo::get_undo_enabled())
10839       CubitUndo::remove_last_undo();
10840   }
10841   else
10842   {
10843     if (CubitUndo::get_undo_enabled())
10844       CubitUndo::note_result_bodies(new_bodies);
10845   }
10846 
10847   GeometryModifyTool::instance()->do_attribute_cleanup();
10848 
10849   DLIList<int> id_list (free_face_list.size());
10850   while (free_face_list.size())
10851   {
10852     RefFace* ref_face = free_face_list.pop();
10853     if (!ref_face->get_surface_ptr())
10854     {
10855       id_list.append(ref_face->id());
10856       GeometryQueryTool::instance()->
10857         destroy_dead_entity( ref_face );
10858     }
10859   }
10860 
10861   GeometryQueryTool::instance()->cleanout_deactivated_geometry();
10862   if (id_list.size())
10863     CubitUtil::list_entity_ids( "Destroyed surface(s) ", id_list );
10864 
10865   //new_body = new_body_list.size() ? new_body_list.get() : 0;
10866   return stat;
10867 }
10868 
10869 //-------------------------------------------------------------------------
10870 // Purpose       : Check for virtual geometry
10871 //
10872 // Special Notes :
10873 //
10874 // Creator       : Jason Kraftcheck
10875 //
10876 // Creation Date : 10/10/03
10877 //-------------------------------------------------------------------------
10878 bool GeometryModifyTool::contains_intermediate_geom( DLIList<Body*>& list ) const
10879 {
10880   DLIList<TopologyBridge*> bridges;
10881   list.reset();
10882   for (int i = list.size(); i--; )
10883     bridges.append(list.get_and_step()->get_body_sm_ptr());
10884   return contains_intermediate_geom(bridges);
10885 }
10886 
10887 //-------------------------------------------------------------------------
10888 // Purpose       : Check for virtual geometry
10889 //
10890 // Special Notes :
10891 //
10892 // Creator       : Jason Kraftcheck
10893 //
10894 // Creation Date : 10/10/03
10895 //-------------------------------------------------------------------------
10896 bool GeometryModifyTool::contains_intermediate_geom(
10897                            DLIList<TopologyBridge*>& bridge_list ) const
10898 {
10899   DLIList<TopologyBridge*> child_list;
10900   while (bridge_list.size())
10901   {
10902     TopologyBridge* bridge = bridge_list.pop();
10903     TBOwner* bridge_owner = bridge->owner();
10904     if (bridge_owner && !dynamic_cast<BridgeManager*>(bridge_owner))
10905       return true;
10906 
10907     child_list.clean_out();
10908     bridge->get_children_virt(child_list);
10909     bridge_list += child_list;
10910   }
10911   return false;
10912 }
10913 
10914 bool GeometryModifyTool::contains_partitions( DLIList<Body*>& list ) const
10915 {
10916   DLIList<TopologyBridge*> bridges;
10917   list.reset();
10918   for (int i = list.size(); i--; )
10919     bridges.append(list.get_and_step()->get_body_sm_ptr());
10920   return contains_partitions(bridges);
10921 }
10922 
10923 bool GeometryModifyTool::contains_composites( DLIList<Body*>& list ) const
10924 {
10925   DLIList<TopologyBridge*> bridges;
10926   list.reset();
10927   for (int i = list.size(); i--; )
10928     bridges.append(list.get_and_step()->get_body_sm_ptr());
10929   return contains_composites(bridges);
10930 }
10931 
10932 bool GeometryModifyTool::contains_composites(
10933                            DLIList<TopologyBridge*>& bridge_list ) const
10934 {
10935   DLIList<TopologyBridge*> child_list;
10936   while (bridge_list.size())
10937   {
10938     TopologyBridge* bridge = bridge_list.pop();
10939     TBOwner* bridge_owner = bridge->owner();
10940     if (bridge_owner && !dynamic_cast<BridgeManager*>(bridge_owner) &&
10941       GeometryQueryTool::instance()->ige_is_composite(bridge_owner))
10942       return true;
10943 
10944     child_list.clean_out();
10945     bridge->get_children_virt(child_list);
10946     bridge_list += child_list;
10947   }
10948   return false;
10949 }
10950 
10951 bool GeometryModifyTool::contains_partitions(
10952                            DLIList<TopologyBridge*>& bridge_list ) const
10953 {
10954   DLIList<TopologyBridge*> child_list;
10955   while (bridge_list.size())
10956   {
10957     TopologyBridge* bridge = bridge_list.pop();
10958     TBOwner* bridge_owner = bridge->owner();
10959     if (bridge_owner && !dynamic_cast<BridgeManager*>(bridge_owner) &&
10960       GeometryQueryTool::instance()->ige_is_partition(bridge_owner))
10961       return true;
10962 
10963     child_list.clean_out();
10964     bridge->get_children_virt(child_list);
10965     bridge_list += child_list;
10966   }
10967   return false;
10968 }
10969 
10970 
10971 CubitBoolean GeometryModifyTool::same_modify_engine(DLIList<TopologyEntity*> &topo_list) const
10972 {
10973   GeometryModifyEngine *gePtr1 = get_engine(topo_list.get_and_step());
10974   GeometryModifyEngine *gePtr2;
10975   for( int i = 1; i < topo_list.size(); i++)
10976   {
10977     gePtr2 = get_engine(topo_list.get_and_step());
10978     if(gePtr1 != gePtr2)
10979     {
10980       return CUBIT_FALSE;
10981     }
10982   }
10983   return CUBIT_TRUE;
10984 }
10985 
10986 CubitBoolean GeometryModifyTool::same_modify_engine(DLIList<RefEntity*> &ref_entity_list,
10987                             CubitBoolean check_children) const
10988 {
10989 
10990   DLIList<RefEntity*> complete_entity_list;
10991 
10992   //Check the check_children option and check all the children if necessary
10993   if (check_children)
10994   {
10995     //Make a complete list of all the RefEntitys and their children
10996     DLIList<RefEntity*> temp = ref_entity_list;
10997     RefEntity* ref_entity_ptr;
10998     int i;
10999     for (i = 0; i < ref_entity_list.size(); i++)
11000     {
11001       ref_entity_ptr = ref_entity_list.get_and_step();
11002       complete_entity_list.clean_out();
11003       ref_entity_ptr->get_all_child_ref_entities(complete_entity_list);
11004       temp += complete_entity_list;
11005     }
11006     complete_entity_list.clean_out();
11007     complete_entity_list.merge_unique(temp);
11008   }
11009   else
11010     complete_entity_list = ref_entity_list;
11011 
11012   //Now make sure all the RefEntitys are from the same geometry engine
11013   DLIList<TopologyEntity*> te_list;
11014   CAST_LIST(complete_entity_list, te_list, TopologyEntity);
11015   return same_modify_engine(te_list);
11016 
11017 }
11018 
11019 CubitStatus
11020 GeometryModifyTool::trim_curve( RefEdge* trim_curve,
11021                                 const CubitVector& trim_vector,
11022                                 const CubitVector& keep_vector )
11023 {
11024   // Use geometry engine to find intersections
11025   TopologyBridge* bridge = 0;
11026   GeometryModifyEngine* gme_ptr = get_engine(trim_curve, &bridge);
11027   Curve *new_curve = 0, *curve = dynamic_cast<Curve*>(bridge);
11028 
11029   if (!gme_ptr || !curve)
11030     return CUBIT_FAILURE;
11031 
11032   if( CubitUndo::get_undo_enabled() )
11033   {
11034     DLIList<RefEdge*> tmp_ents(1);
11035     tmp_ents.append( trim_curve );
11036     CubitUndo::save_state_with_cubit_file( tmp_ents );
11037   }
11038 
11039   new_curve = gme_ptr->trim_curve( curve, trim_vector, keep_vector );
11040   if (!new_curve)
11041   {
11042     if( CubitUndo::get_undo_enabled() )
11043       CubitUndo::remove_last_undo();
11044     return CUBIT_FAILURE;
11045   }
11046 
11047   GeometryQueryTool::instance()->destroy_dead_entity( trim_curve );
11048 
11049   RefEdge* new_edge = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
11050 
11051   if( CubitUndo::get_undo_enabled() )
11052     CubitUndo::note_result_entity( new_edge );
11053 
11054   PRINT_INFO("Created curve %d\n", new_edge->id());
11055 
11056   return CUBIT_SUCCESS;
11057 }
11058 
11059 CubitStatus
11060 GeometryModifyTool::surface_intersection( RefFace *ref_face1,
11061                                           RefFace *ref_face2,
11062                                           DLIList<RefEdge*> &ref_edge_list )
11063 {
11064   DLIList<TopologyEntity*> entity_list(2);
11065   DLIList<TopologyBridge*> bridge_list(2);
11066   entity_list.append(ref_face1);
11067   entity_list.append(ref_face2);
11068   GeometryModifyEngine* gme = common_modify_engine(entity_list, bridge_list);
11069   if (!gme)
11070   {
11071     PRINT_ERROR("Surfaces %d and %d do not share a common solid modeller.\n",
11072       ref_face1->id(), ref_face2->id() );
11073     return CUBIT_FAILURE;
11074   }
11075 
11076   bridge_list.reset();
11077   Surface* surf0 = dynamic_cast<Surface*>(bridge_list.get_and_step());
11078   Surface* surf1 = dynamic_cast<Surface*>(bridge_list.get());
11079 
11080   GeometryQueryEngine* gqe = surf0->get_geometry_query_engine();
11081   // Note the user can set the following value through
11082   //  set geometry accuracy <val>
11083   double resabs = gqe->get_sme_resabs_tolerance();
11084 
11085   DLIList<Curve*> curve_list;
11086   CubitStatus status = gme->surface_intersection( surf0, surf1, curve_list, resabs );
11087 
11088   if( status == CUBIT_FAILURE )
11089     return CUBIT_FAILURE;
11090 
11091   if( CubitUndo::get_undo_enabled() && curve_list.size() )
11092     CubitUndo::save_state();
11093 
11094   int i;
11095   Curve *curve_ptr;
11096   RefEdge *ref_edge_ptr;
11097   curve_list.reset();
11098   for( i=curve_list.size(); i--; )
11099   {
11100     curve_ptr = curve_list.get_and_step();
11101     ref_edge_ptr = GeometryQueryTool::instance()->
11102       make_free_RefEdge( curve_ptr );
11103     if( ref_edge_ptr )
11104       ref_edge_list.append( ref_edge_ptr );
11105     else
11106       delete curve_ptr;
11107   }
11108 
11109   if( CubitUndo::get_undo_enabled() )
11110   {
11111     DLIList<RefEntity*> tmp_list;
11112     for( i=ref_edge_list.size(); i--; )
11113       tmp_list.append( ref_edge_list.get_and_step() );
11114     CubitUndo::note_result_entities( tmp_list );
11115   }
11116 
11117   return CUBIT_SUCCESS;
11118 }
11119 
11120 
11121 RefEdge*
11122 GeometryModifyTool::create_arc(const CubitVector& position,
11123                                double radius,
11124                                double start_angle,
11125                                double end_angle,
11126                                CubitVector plane,
11127                                CubitBoolean preview)
11128 {
11129   if(0 == gmeList.size())
11130   {
11131     PRINT_WARNING("No active geometry engine.\n");
11132     return NULL;
11133   }
11134 
11135   if( radius <= GEOMETRY_RESABS )
11136   {
11137     PRINT_ERROR("Values must be positive\n");
11138     return NULL;
11139   }
11140 
11141   if(preview)
11142   {
11143     gmeList.get()->create_arc(position,radius,start_angle,end_angle, plane, preview);
11144     return NULL;
11145   }
11146 
11147   if( CubitUndo::get_undo_enabled() )
11148     CubitUndo::save_state();
11149 
11150   Curve* curve = gmeList.get()->create_arc(position,radius,start_angle,end_angle, plane,preview);
11151   if (!curve)
11152   {
11153     if( CubitUndo::get_undo_enabled() )
11154       CubitUndo::remove_last_undo();
11155     return 0;
11156   }
11157 
11158   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
11159   PRINT_INFO("Created curve %d\n", result->id());
11160 
11161   if( CubitUndo::get_undo_enabled() )
11162     CubitUndo::note_result_entity( result );
11163   return result;
11164 }
11165 
11166 
11167 
11168 
11169 RefEdge*
11170 GeometryModifyTool::create_arc_three( RefVertex* ref_vertex1,
11171                                       RefVertex* ref_vertex2,
11172                                       RefVertex* ref_vertex3,
11173                                       CubitBoolean full,
11174                                       CubitBoolean preview )
11175 {
11176   DLIList<TopologyEntity*> entity_list(3);
11177   DLIList<TopologyBridge*> bridge_list(3);
11178   entity_list.append(ref_vertex1);
11179   entity_list.append(ref_vertex2);
11180   entity_list.append(ref_vertex3);
11181   GeometryModifyEngine* gme = common_modify_engine(entity_list, bridge_list);
11182   if (!gme)
11183   {
11184     PRINT_ERROR("Vertices do not share a common solid modeller.\n");
11185     return 0;
11186   }
11187 
11188   if(preview)
11189   {
11190     bridge_list.reset();
11191     TBPoint* point0 = dynamic_cast<TBPoint*>(bridge_list.next(0));
11192     TBPoint* point1 = dynamic_cast<TBPoint*>(bridge_list.next(1));
11193     TBPoint* point2 = dynamic_cast<TBPoint*>(bridge_list.next(2));
11194     gme->create_arc_three( point0, point1, point2, full,preview );
11195     return NULL;
11196   }
11197 
11198   //if we can reuse vertices, we decide here
11199   bool need_new_start_point = false;
11200   bool need_new_end_point = false;
11201   if( full )
11202   {
11203     need_new_start_point = ref_vertex1->get_parents() > 0;
11204     if (need_new_start_point)
11205     {
11206       bridge_list.reset();
11207       TBPoint *start_point = gme->make_Point( ref_vertex1->coordinates() );
11208       bridge_list.change_to( start_point );
11209     }
11210   }
11211   else
11212   {
11213     need_new_start_point = ref_vertex1->get_parents() > 0;
11214     need_new_end_point = ref_vertex3->get_parents() > 0;
11215 
11216     if (need_new_start_point)
11217     {
11218       bridge_list.reset();
11219       TBPoint *start_point = gme->make_Point( ref_vertex1->coordinates() );
11220       bridge_list.change_to( start_point );
11221     }
11222     if (need_new_end_point)
11223     {
11224       bridge_list.reset();
11225       bridge_list.last();
11226       TBPoint *end_point = gme->make_Point( ref_vertex3->coordinates());
11227       bridge_list.change_to( end_point );
11228     }
11229   }
11230 
11231   if( CubitUndo::get_undo_enabled() )
11232   {
11233     DLIList<RefVertex*> vertices_to_save;
11234     if( !need_new_start_point )
11235       vertices_to_save.append( ref_vertex1 );
11236     if( !need_new_end_point )
11237       vertices_to_save.append( ref_vertex3 );
11238 
11239     if( vertices_to_save.size() )
11240       CubitUndo::save_state_with_cubit_file( vertices_to_save, true );
11241     else
11242       CubitUndo::save_state();
11243   }
11244 
11245   bridge_list.reset();
11246   TBPoint* point0 = dynamic_cast<TBPoint*>(bridge_list.next(0));
11247   TBPoint* point1 = dynamic_cast<TBPoint*>(bridge_list.next(1));
11248   TBPoint* point2 = dynamic_cast<TBPoint*>(bridge_list.next(2));
11249   Curve* curve = gme->create_arc_three( point0, point1, point2, full,preview );
11250   if (!curve)
11251   {
11252     if( CubitUndo::get_undo_enabled() )
11253       CubitUndo::remove_last_undo();
11254     return 0;
11255   }
11256 
11257   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
11258   PRINT_INFO("Created curve %d\n", result->id());
11259 
11260   if( CubitUndo::get_undo_enabled() )
11261     CubitUndo::note_result_entity( result );
11262   return result;
11263 
11264 }
11265 
11266 RefEdge*
11267 GeometryModifyTool::create_arc_three( RefEdge* ref_edge1,
11268                                       RefEdge* ref_edge2,
11269                                       RefEdge* ref_edge3,
11270                                       CubitBoolean full,
11271                                       CubitBoolean preview )
11272 {
11273   DLIList<TopologyEntity*> entity_list(3);
11274   DLIList<TopologyBridge*> bridge_list(3);
11275   entity_list.append(ref_edge1);
11276   entity_list.append(ref_edge2);
11277   entity_list.append(ref_edge3);
11278   GeometryModifyEngine* gme = common_modify_engine(entity_list, bridge_list);
11279   if (!gme)
11280   {
11281     PRINT_ERROR("The input curves must be associated with a common solid modeller.\n");
11282     return NULL;
11283   }
11284 
11285   bridge_list.reset();
11286   Curve* curve0 = dynamic_cast<Curve*>(bridge_list.next(0));
11287   Curve* curve1 = dynamic_cast<Curve*>(bridge_list.next(1));
11288   Curve* curve2 = dynamic_cast<Curve*>(bridge_list.next(2));
11289   Curve* curve = gme->create_arc_three( curve0, curve1, curve2, full,preview );
11290   if (!curve)
11291     return 0;
11292 
11293   if( CubitUndo::get_undo_enabled() )
11294     CubitUndo::save_state();
11295 
11296   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
11297 
11298   if( CubitUndo::get_undo_enabled() )
11299     CubitUndo::note_result_entity( result );
11300 
11301   PRINT_INFO("Created curve %d\n", result->id());
11302   return result;
11303 }
11304 RefEdge*
11305 GeometryModifyTool::create_arc_radius( RefVertex* ref_vertex1,
11306                                             RefVertex* ref_vertex2,
11307                                             const CubitVector &normal,
11308                                             double radius,
11309                                             CubitBoolean other_arc,
11310                                             CubitBoolean full,
11311                                             CubitBoolean preview)
11312 {
11313   DLIList<TopologyEntity*> entity_list(2);
11314   DLIList<TopologyBridge*> bridge_list(2);
11315   entity_list.append(ref_vertex1);
11316   entity_list.append(ref_vertex2);
11317   GeometryModifyEngine* gme = common_modify_engine(entity_list, bridge_list);
11318   if (!gme)
11319   {
11320     PRINT_ERROR("Vertices do not share a common modify engine.\n");
11321     return 0;
11322   }
11323 
11324 
11325 
11326   CubitVector start = ref_vertex1->coordinates(); // Position on arc
11327   CubitVector end = ref_vertex2->coordinates(); // Position on arc
11328 
11329   CubitVector center_vec=end-start;
11330 
11331   CubitVector perp_vec=normal*center_vec;
11332   center_vec*=0.5;
11333   double b=radius*radius-center_vec.length_squared();
11334   if(b>=0)
11335   {
11336     b=sqrt(b);
11337   }
11338   else
11339   {
11340     PRINT_ERROR("Radius must be greater than half the distance between the end vertices.\n");
11341     return 0;
11342   }
11343   if(other_arc)
11344     b*=-1;
11345 
11346 
11347   perp_vec.normalize();
11348   perp_vec*=b;
11349 
11350 
11351   center_vec=center_vec+perp_vec;
11352 
11353   CubitVector center=start+center_vec;
11354 
11355   if(preview)
11356   {
11357     bridge_list.reset();
11358     TBPoint* point1 = dynamic_cast<TBPoint*>(bridge_list.next(0));
11359     TBPoint* point2 = dynamic_cast<TBPoint*>(bridge_list.next(1));
11360      gme->create_arc_radius(center,point1, point2,
11361       normal, radius, full,preview );
11362      return NULL;
11363   }
11364   else
11365   {
11366 
11367     //if we can reuse vertices, we decide here
11368     bool need_new_start_point=false, need_new_end_point=false;
11369     if( full )
11370     {
11371       need_new_start_point = ref_vertex1->get_parents() > 0;
11372       if (need_new_start_point)
11373       {
11374         bridge_list.reset();
11375         TBPoint *start_point = gme->make_Point( ref_vertex1->coordinates() );
11376         bridge_list.change_to( start_point );
11377       }
11378     }
11379     else
11380     {
11381       need_new_start_point = ref_vertex1->get_parents() > 0;
11382       need_new_end_point = ref_vertex2->get_parents() > 0;
11383 
11384       if (need_new_start_point)
11385       {
11386         bridge_list.reset();
11387         TBPoint *start_point = gme->make_Point( ref_vertex1->coordinates() );
11388         bridge_list.change_to( start_point );
11389       }
11390       if (need_new_end_point)
11391       {
11392         bridge_list.last();
11393         TBPoint *end_point = gme->make_Point( ref_vertex2->coordinates());
11394         bridge_list.change_to( end_point );
11395       }
11396     }
11397 
11398     if( CubitUndo::get_undo_enabled() )
11399     {
11400       DLIList<RefVertex*> vertices_to_save;
11401       if( !need_new_start_point )
11402         vertices_to_save.append( ref_vertex1 );
11403       if( !need_new_end_point )
11404         vertices_to_save.append( ref_vertex2 );
11405 
11406       if( vertices_to_save.size() )
11407         CubitUndo::save_state_with_cubit_file( vertices_to_save, true );
11408       else
11409         CubitUndo::save_state();
11410     }
11411 
11412     bridge_list.reset();
11413     TBPoint* point1 = dynamic_cast<TBPoint*>(bridge_list.next(0));
11414     TBPoint* point2 = dynamic_cast<TBPoint*>(bridge_list.next(1));
11415     Curve* curve = gme->create_arc_radius(center,point1, point2,
11416       normal, radius, full,preview );
11417     if (!curve)
11418     {
11419       if( CubitUndo::get_undo_enabled() )
11420         CubitUndo::remove_last_undo();
11421       return 0;
11422     }
11423 
11424     RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
11425     PRINT_INFO("Created curve %d\n", result->id());
11426 
11427     if( CubitUndo::get_undo_enabled() )
11428       CubitUndo::note_result_entity( result );
11429 
11430     return result;
11431   }
11432   return 0;
11433 }
11434 
11435 RefEdge*
11436 GeometryModifyTool::create_arc_center_edge( RefVertex* ref_vertex1,
11437                                             RefVertex* ref_vertex2,
11438                                             RefVertex* ref_vertex3,
11439                                             const CubitVector &normal,
11440                                             double radius,
11441                                             CubitBoolean full,
11442                                             CubitBoolean preview )
11443 {
11444   DLIList<TopologyEntity*> entity_list(3);
11445   DLIList<TopologyBridge*> bridge_list(3);
11446   entity_list.append(ref_vertex1);
11447   entity_list.append(ref_vertex2);
11448   entity_list.append(ref_vertex3);
11449   GeometryModifyEngine* gme = common_modify_engine(entity_list, bridge_list);
11450   if (!gme)
11451   {
11452     PRINT_ERROR("Vertices do not share a common modify engine.\n");
11453     return 0;
11454   }
11455 
11456   if(preview)
11457   {
11458     TBPoint* point0 = dynamic_cast<TBPoint*>(bridge_list.next(0));
11459     TBPoint* point1 = dynamic_cast<TBPoint*>(bridge_list.next(1));
11460     TBPoint* point2 = dynamic_cast<TBPoint*>(bridge_list.next(2));
11461     gme->create_arc_center_edge( point0, point1, point2,
11462       normal, radius, full,preview );
11463     return NULL;
11464 
11465   }
11466 
11467   //if we can reuse vertices, we decide here
11468   bool need_new_start_point=false, need_new_end_point=false;
11469   if( full )
11470   {
11471     need_new_start_point = ref_vertex2->get_parents() > 0;
11472     if (need_new_start_point)
11473     {
11474       bridge_list.reset();
11475       bridge_list.step(1);
11476       TBPoint *start_point = gme->make_Point( ref_vertex2->coordinates() );
11477       bridge_list.change_to( start_point );
11478     }
11479   }
11480   else
11481   {
11482     need_new_start_point = ref_vertex2->get_parents() > 0;
11483     need_new_end_point = ref_vertex3->get_parents() > 0;
11484 
11485     if (need_new_start_point)
11486     {
11487       bridge_list.reset();
11488       bridge_list.step();
11489       TBPoint *start_point = gme->make_Point( ref_vertex2->coordinates() );
11490       bridge_list.change_to( start_point );
11491     }
11492     if (need_new_end_point)
11493     {
11494       bridge_list.last();
11495       TBPoint *end_point = gme->make_Point( ref_vertex3->coordinates());
11496       bridge_list.change_to( end_point );
11497     }
11498   }
11499 
11500   if( CubitUndo::get_undo_enabled() )
11501   {
11502     DLIList<RefVertex*> vertices_to_save;
11503     if( !need_new_start_point )
11504       vertices_to_save.append( ref_vertex2 );
11505     if( !need_new_end_point )
11506       vertices_to_save.append( ref_vertex3 );
11507 
11508     if( vertices_to_save.size() )
11509       CubitUndo::save_state_with_cubit_file( vertices_to_save, true );
11510     else
11511       CubitUndo::save_state();
11512   }
11513 
11514   bridge_list.reset();
11515   TBPoint* point0 = dynamic_cast<TBPoint*>(bridge_list.next(0));
11516   TBPoint* point1 = dynamic_cast<TBPoint*>(bridge_list.next(1));
11517   TBPoint* point2 = dynamic_cast<TBPoint*>(bridge_list.next(2));
11518   Curve* curve = gme->create_arc_center_edge( point0, point1, point2,
11519     normal, radius, full );
11520   if (!curve)
11521   {
11522     if( CubitUndo::get_undo_enabled() )
11523       CubitUndo::remove_last_undo();
11524     return 0;
11525   }
11526 
11527   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
11528   PRINT_INFO("Created curve %d\n", result->id());
11529 
11530   if( CubitUndo::get_undo_enabled() )
11531     CubitUndo::note_result_entity( result );
11532 
11533   return result;
11534 
11535 }
11536 
11537 CubitStatus
11538 GeometryModifyTool::create_curve_combine( DLIList<RefEdge*>& ref_edge_list,
11539                                     RefEdge *&new_ref_edge_ptr )
11540 {
11541   DLIList<TopologyBridge*> bridge_list(ref_edge_list.size());
11542   CubitStatus result = CUBIT_FAILURE;
11543 
11544   int count = ref_edge_list.size();
11545   if (count == 0)
11546   {
11547     PRINT_ERROR("No edges to combine.\n");
11548     return result;
11549   }
11550 
11551   DLIList<TopologyEntity*> entity_list(count);
11552   CAST_LIST_TO_PARENT( ref_edge_list, entity_list );
11553   GeometryModifyEngine* gme = common_modify_engine(entity_list, bridge_list);
11554   if (!gme)
11555   {
11556     PRINT_ERROR("Edges do not share a common modify engine.\n");
11557     return result;
11558   }
11559 
11560   Curve* new_curve_ptr;
11561   DLIList<Curve*> curve_list(count);
11562   CAST_LIST( bridge_list, curve_list, Curve );
11563   result = gme->create_curve_combine(curve_list, new_curve_ptr);
11564   if (new_curve_ptr)
11565       new_ref_edge_ptr = CAST_TO(new_curve_ptr->topology_entity(), RefEdge);
11566 
11567 
11568   return result;
11569 }
11570 
11571 //-------------------------------------------------------------------------
11572 // Purpose       : Find a common geometry engine
11573 //
11574 // Special Notes :
11575 //
11576 // Creator       : Jason Kraftcheck
11577 //
11578 // Creation Date : 02/28/00
11579 //-------------------------------------------------------------------------
11580 GeometryModifyEngine*
11581 GeometryModifyTool::common_modify_engine( DLIList<TopologyEntity*>& topology_list,
11582                                           DLIList<TopologyBridge*>& engine_bridges,
11583                                           CubitBoolean allow_composites ) const
11584 {
11585   GeometryModifyEngine* gme_ptr = 0;
11586   if(allow_composites)
11587   {
11588     int i;
11589     engine_bridges.clean_out();
11590     for(i=topology_list.size(); i--;)
11591     {
11592       TopologyEntity* topo_ptr = topology_list.get_and_step();
11593       if (!topo_ptr)
11594         return (GeometryModifyEngine*)NULL;
11595       TopologyBridge *first_bridge = topo_ptr->bridge_manager()->topology_bridge();
11596       GeometryQueryEngine *gqe = first_bridge->get_geometry_query_engine();
11597       DLIList<TopologyBridge*> underlying_bridge_list;
11598       gqe->get_underlying_bridges(first_bridge, underlying_bridge_list);
11599       if(underlying_bridge_list.size() == 0)
11600         underlying_bridge_list.append(first_bridge);
11601       int k;
11602       for(k=underlying_bridge_list.size(); k--;)
11603       {
11604         TopologyBridge *bridge_ptr = underlying_bridge_list.get_and_step();
11605         engine_bridges.append( bridge_ptr );
11606         GeometryModifyEngine *cur_gme = get_engine(bridge_ptr);
11607         if(!gme_ptr)
11608           gme_ptr = cur_gme;
11609         else
11610         {
11611           if(gme_ptr != cur_gme)
11612           {
11613             gme_ptr = NULL;
11614             k=0;
11615             i=0;
11616           }
11617         }
11618       }
11619     }
11620   }
11621   else
11622   {
11623     topology_list.reset();
11624 
11625     TopologyEntity* topo_ptr = topology_list.get_and_step();
11626     if (!topo_ptr)
11627       return (GeometryModifyEngine*)NULL;
11628     DLIList<TopologyBridge*> first_bridge_list;
11629     topo_ptr->bridge_manager()->get_bridge_list( first_bridge_list );
11630 
11631     first_bridge_list.reset();
11632     for( int i = first_bridge_list.size(); i > 0; i-- )
11633     {
11634       TopologyBridge* bridge_ptr = first_bridge_list.get_and_step();
11635       engine_bridges.clean_out();
11636       engine_bridges.append( bridge_ptr );
11637       gme_ptr = get_engine(bridge_ptr);
11638 
11639       if( !gme_ptr )
11640       return (GeometryModifyEngine*)NULL;
11641 
11642       topology_list.reset();
11643       topology_list.step(); //skip first entry
11644       for( int j = topology_list.size(); j > 1; j-- )
11645       {
11646         topo_ptr = topology_list.get_and_step();
11647         bridge_ptr = topo_ptr->bridge_manager()->topology_bridge(gme_ptr->get_gqe());
11648         if( bridge_ptr ) engine_bridges.append( bridge_ptr );
11649         else break;
11650       }
11651 
11652       if( engine_bridges.size() == topology_list.size() )
11653         break;
11654 
11655       gme_ptr = 0;
11656     }
11657   }
11658   if( !gme_ptr )
11659   {
11660     engine_bridges.clean_out();
11661     PRINT_ERROR("Entities do not belong to the same geometry engine.\n");
11662   }
11663   return gme_ptr;
11664 }
11665 
11666 //-------------------------------------------------------------------------
11667 // Purpose       : Find common modify engine for Bodies
11668 //
11669 // Special Notes :
11670 //
11671 // Creator       : Jason Kraftcheck
11672 //
11673 // Creation Date : 09/26/03
11674 //-------------------------------------------------------------------------
11675 GeometryModifyEngine*
11676 GeometryModifyTool::common_modify_engine( DLIList<Body*>& input,
11677                                           DLIList<BodySM*>& output) const
11678 {
11679   input.reset();
11680   Body* body_ptr = input.get();
11681   BodySM* body_sm_ptr = body_ptr->get_body_sm_ptr();
11682   GeometryModifyEngine* engine = get_engine(body_sm_ptr);
11683 
11684   for (int i = input.size(); i--; )
11685   {
11686     body_ptr = input.get_and_step();
11687     body_sm_ptr = body_ptr->get_body_sm_ptr();
11688     output.append(body_sm_ptr);
11689 
11690     if (!body_sm_ptr)
11691     {
11692       PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n", body_ptr->id());
11693       output.clean_out();
11694       return 0;
11695     }
11696 
11697     if (get_engine(body_sm_ptr) != engine)
11698     {
11699       output.clean_out();
11700       return 0;
11701     }
11702   }
11703 
11704   return engine;
11705 }
11706 
11707 //-------------------------------------------------------------------------
11708 // Purpose       : Get modify engine common to input RefFaces and RefEdges.
11709 //
11710 // Special Notes : Wrapper around the TopologyEntity/TopologyBridge form.
11711 //
11712 // Creator       : Jason Kraftcheck
11713 //
11714 // Creation Date : 09/26/03
11715 //-------------------------------------------------------------------------
11716 GeometryModifyEngine*
11717 GeometryModifyTool::common_modify_engine( DLIList<RefFace*>& face_list,
11718                                           DLIList<RefEdge*>& edge_list,
11719                                           DLIList<Surface*>& surf_list,
11720                                           DLIList<Curve*>& curv_list,
11721                                           CubitBoolean allow_composites) const
11722 {
11723   int i;
11724   const int count = face_list.size() + edge_list.size();
11725   DLIList<TopologyEntity*> entity_list(count);
11726   DLIList<TopologyBridge*> bridge_list(count);
11727 
11728   face_list.reset();
11729   edge_list.reset();
11730   for (i = face_list.size(); i--; )
11731     entity_list.append(face_list.get_and_step());
11732   for (i = edge_list.size(); i--; )
11733     entity_list.append(edge_list.get_and_step());
11734 
11735   GeometryModifyEngine* engine = common_modify_engine(entity_list, bridge_list, allow_composites);
11736   if (!engine)
11737     return 0;
11738 
11739   entity_list.reset();
11740   CAST_LIST(bridge_list, surf_list, Surface);
11741   CAST_LIST(bridge_list, curv_list, Curve  );
11742   if(allow_composites)
11743   {
11744     if(surf_list.size() >= face_list.size() && curv_list.size() >= edge_list.size())
11745       return engine;
11746     else
11747       return 0;
11748   }
11749   else
11750   {
11751     if (surf_list.size() != face_list.size() || curv_list.size() != edge_list.size())
11752       return 0;
11753     else
11754       return engine;
11755   }
11756 }
11757 
11758 //-------------------------------------------------------------------------
11759 // Purpose       : Get modify engine common to input RefFaces.
11760 //
11761 // Special Notes : Wrapper around the TopologyEntity/TopologyBridge form.
11762 //
11763 // Creator       : Jason Kraftcheck
11764 //
11765 // Creation Date : 11/05/03
11766 //-------------------------------------------------------------------------
11767 GeometryModifyEngine*
11768 GeometryModifyTool::common_modify_engine( DLIList<RefFace*>& face_list,
11769                                           DLIList<Surface*>& surf_list,
11770                                           CubitBoolean allow_composites) const
11771 {
11772   const int size = face_list.size();
11773   DLIList<TopologyEntity*> topo_list(size);
11774   DLIList<TopologyBridge*> geom_list(size);
11775   GeometryModifyEngine* result;
11776 
11777   CAST_LIST_TO_PARENT( face_list, topo_list );
11778   result = common_modify_engine( topo_list, geom_list, allow_composites );
11779 
11780   CAST_LIST( geom_list, surf_list, Surface );
11781   return result;
11782 }
11783 
11784 //-------------------------------------------------------------------------
11785 // Purpose       : Get modify engine common to input RefEdges.
11786 //
11787 // Special Notes : Wrapper around the TopologyEntity/TopologyBridge form.
11788 //
11789 // Creator       : Steve Storm
11790 //
11791 // Creation Date : 03/09/05
11792 //-------------------------------------------------------------------------
11793 GeometryModifyEngine* GeometryModifyTool::common_modify_engine(
11794                                       DLIList<RefEdge*>& edge_list,
11795                                       DLIList<Curve*>& curve_list,
11796                                       CubitBoolean allow_composites) const
11797 {
11798   const int size = edge_list.size();
11799   DLIList<TopologyEntity*> topo_list(size);
11800   DLIList<TopologyBridge*> geom_list(size);
11801   GeometryModifyEngine* result;
11802 
11803   CAST_LIST_TO_PARENT( edge_list, topo_list );
11804   result = common_modify_engine( topo_list, geom_list, allow_composites );
11805 
11806   CAST_LIST( geom_list, curve_list, Curve );
11807   return result;
11808 }
11809 
11810 //-------------------------------------------------------------------------
11811 // Purpose       : Get modify engine common to input RefVertices.
11812 //
11813 // Special Notes : Wrapper around the TopologyEntity/TopologyBridge form.
11814 //
11815 // Creator       : Steve Storm
11816 //
11817 // Creation Date : 03/25/05
11818 //-------------------------------------------------------------------------
11819 GeometryModifyEngine*
11820 GeometryModifyTool::common_modify_engine( DLIList<RefVertex*>& vertex_list,
11821                                           DLIList<TBPoint*>& point_list,
11822                                           CubitBoolean allow_composites) const
11823 {
11824   const int size = vertex_list.size();
11825   DLIList<TopologyEntity*> topo_list(size);
11826   DLIList<TopologyBridge*> geom_list(size);
11827   GeometryModifyEngine* result;
11828 
11829   CAST_LIST_TO_PARENT( vertex_list, topo_list );
11830   result = common_modify_engine( topo_list, geom_list, allow_composites );
11831 
11832   CAST_LIST( geom_list, point_list, TBPoint );
11833   return result;
11834 }
11835 
11836 //-------------------------------------------------------------------------
11837 // Purpose       : Pull RefFaces with a common GeometryModifyEngine out of
11838 //                 the input ref_face_list.  Place their surfaces in the
11839 //                 output surf_list, and return the common modify engine.
11840 //
11841 // Special Notes : the function returns a NULL pointer if a RefFace without
11842 //                 a modify engine is found in the input list.
11843 //
11844 // Creator       : Steve Storm
11845 //
11846 // Creation Date : 03/02/08
11847 //-------------------------------------------------------------------------
11848 GeometryModifyEngine*
11849 GeometryModifyTool::pull_common_surfs( DLIList<RefFace*> &ref_face_list,
11850                                        DLIList<RefFace*> &common_face_list,
11851                                        DLIList<Surface*> &common_surf_list )
11852 {
11853   int i;
11854   RefFace *ref_face_ptr;
11855   Surface *surf_ptr;
11856 
11857   GeometryModifyEngine *gme1 = 0, *gme2 = 0;
11858 
11859   ref_face_list.reset();
11860   for( i=0; i<ref_face_list.size(); i++ )
11861   {
11862     ref_face_ptr = ref_face_list.get();
11863     surf_ptr = ref_face_ptr->get_surface_ptr();
11864 
11865     if( i==0 )
11866     {
11867       common_face_list.append( ref_face_ptr );
11868       common_surf_list.append( surf_ptr );
11869       gme1 = get_engine( surf_ptr );
11870       if (!gme1)
11871       {
11872         PRINT_ERROR("Surface %d does not have a modify engine.\n", ref_face_ptr->id());
11873         return 0;
11874       }
11875       ref_face_list.change_to( NULL );
11876       ref_face_list.step();
11877       continue;
11878     }
11879 
11880     gme2 = get_engine( surf_ptr );
11881     if (!gme2)
11882     {
11883       PRINT_ERROR("Surface %d does not have a modify engine.\n", ref_face_ptr->id());
11884       return 0;
11885     }
11886 
11887     if( gme2 == gme1 )
11888     {
11889       common_face_list.append( ref_face_ptr );
11890       common_surf_list.append( surf_ptr );
11891       ref_face_list.change_to( NULL );
11892     }
11893 
11894     ref_face_list.step();
11895   }
11896 
11897   ref_face_list.remove_all_with_value( NULL );
11898 
11899   return gme1;
11900 }
11901 
11902 // Separates the list of bodies so that there is one body per volume
11903 // after a webcut.  Checks the sepAfterWebcut flag.
11904 CubitStatus GeometryModifyTool::separate_body_after_webcut( DLIList<Body*> &input_list,
11905                                               DLIList<Body*> &output_list) const
11906 {
11907     //First see if we should spearate.
11908   if ( !sepAfterWebcut )
11909   {
11910     output_list = input_list;
11911     return CUBIT_SUCCESS;
11912   }
11913   DLIList<Body*> temp_body_list;
11914   for ( int ii = input_list.size(); ii > 0; ii-- )
11915   {
11916     Body *body_ptr = input_list.get_and_step();
11917     temp_body_list.clean_out();
11918 
11919     bool undo_setting = CubitUndo::get_undo_enabled();
11920     if( undo_setting == true )
11921       CubitUndo::set_undo_enabled( false );
11922 
11923     split_body(body_ptr, temp_body_list);
11924 
11925     if( undo_setting == true )
11926       CubitUndo::set_undo_enabled( true );
11927 
11928     output_list += temp_body_list;
11929   }
11930   return CUBIT_SUCCESS;
11931 }
11932 
11933 GeometryModifyEngine *GeometryModifyTool::get_engine(TopologyBridge *tb_ptr) const
11934 {
11935   int i;
11936   GeometryModifyEngine *gme;
11937   for (i = 0; i < gmeList.size(); i++) {
11938     gme = gmeList.next(i);
11939     if (gme->is_modify_engine(tb_ptr)) return gme;
11940   }
11941   return NULL;
11942 }
11943 
11944 GeometryModifyEngine *GeometryModifyTool::get_engine(TopologyEntity *te_ptr,
11945                                                      TopologyBridge **bridge) const
11946 {
11947   int i;
11948   GeometryModifyEngine *gme = 0;
11949   TopologyBridge* tb_ptr = NULL;
11950   BridgeManager* bm = te_ptr->bridge_manager();
11951   DLIList<TopologyBridge*> bridges(bm->number_of_bridges());
11952   bm->get_bridge_list(bridges);
11953   bridges.reset();
11954   for (i = bridges.size(); !gme && i--; )
11955   {
11956     tb_ptr = bridges.get_and_step();
11957     gme = get_engine(tb_ptr);
11958   }
11959 
11960   if (bridge && gme)
11961     *bridge = tb_ptr;
11962 
11963   return gme;
11964 }
11965 
11966 CubitStatus GeometryModifyTool::get_offset_intersections( RefEdge* ref_edge1, RefEdge* ref_edge2,
11967                                                           DLIList<CubitVector>& intersection_list,
11968                                                           double offset, CubitBoolean ext_first )
11969 {
11970   DLIList<TopologyEntity*> entity_list(2);
11971   DLIList<TopologyBridge*> bridge_list(2);
11972   entity_list.append(ref_edge1);
11973   entity_list.append(ref_edge2);
11974   GeometryModifyEngine* gme_ptr1 = common_modify_engine(entity_list,bridge_list);
11975 
11976   if( gme_ptr1 == 0 )
11977   {
11978       PRINT_ERROR( "Curves %d and %d do not have the same underlying geometry modeling engine\n"
11979                    "      For intersection calculations, they must be the same\n",
11980          ref_edge1->id(), ref_edge2->id() );
11981       return CUBIT_FAILURE;
11982    }
11983 
11984    bridge_list.reset();
11985    Curve* curve0 = dynamic_cast<Curve*>(bridge_list.next(0));
11986    Curve* curve1 = dynamic_cast<Curve*>(bridge_list.next(1));
11987 
11988    return gme_ptr1->get_offset_intersections( curve0, curve1, intersection_list,
11989                                               offset, ext_first );
11990 }
11991 
11992 CubitStatus GeometryModifyTool::get_offset_intersections(RefEdge* ref_edge_ptr,
11993                                                           RefFace* ref_face_ptr,
11994                                                           DLIList<CubitVector> &intersection_list,
11995                                                           double offset,
11996                                                           CubitBoolean ext_surf )
11997 {
11998   // If curve is straight and surface is planar, compute their intersection;
11999   // otherwise use the geometry engine to do it.
12000 
12001   Curve* curve_ptr = ref_edge_ptr->get_curve_ptr();
12002   Surface* surface_ptr = ref_face_ptr->get_surface_ptr();
12003 
12004   if( curve_ptr == NULL )
12005   {
12006       PRINT_ERROR("Unable to retrieve underlying geometric entity of Curve %d\n"
12007       "       This is a bug - please report it\n", ref_edge_ptr->id() );
12008     return CUBIT_FAILURE;
12009   }
12010 
12011   if( surface_ptr == NULL )
12012   {
12013       PRINT_ERROR("Unable to retrieve underlying geometric entity of Surface %d\n"
12014       "       This is a bug - please report it\n", ref_face_ptr->id() );
12015     return CUBIT_FAILURE;
12016   }
12017 
12018   // If straight line and plane, find location right here analytically.
12019   CubitVector pln_origin, pln_normal;
12020   CubitVector crv_origin, crv_direction;
12021   if( ref_face_ptr->get_point_normal( pln_origin, pln_normal ) &&
12022      ref_edge_ptr->get_point_direction( crv_origin, crv_direction ) )
12023   {
12024      double pln_orig[3], pln_norm[3];
12025      pln_orig[0]=pln_origin.x(); pln_orig[1]=pln_origin.y(); pln_orig[2]=pln_origin.z();
12026      pln_norm[0]=pln_normal.x(); pln_norm[1]=pln_normal.y(); pln_norm[2]=pln_normal.z();
12027 
12028      double crv_orig[3], crv_dir[3];
12029      crv_orig[0]=crv_origin.x(); crv_orig[1]=crv_origin.y(); crv_orig[2]=crv_origin.z();
12030      crv_dir[0]=crv_direction.x(); crv_dir[1]=crv_direction.y(); crv_dir[2]=crv_direction.z();
12031 
12032      AnalyticGeometryTool *agt = AnalyticGeometryTool::instance();
12033 
12034      if( agt->is_vec_perp( pln_norm, crv_dir ) )
12035      {
12036         PRINT_ERROR( "Line is parallel to the plane - intersection not possible\n" );
12037         return CUBIT_FAILURE;
12038      }
12039 
12040      double ang = agt->angle_vec_vec( pln_norm, crv_dir );
12041      if( ang > AGT_PI_DIV_2 )
12042         ang = AGT_PI - ang;
12043 
12044      double int_pnt[3];
12045      agt->int_ln_pln( crv_orig, crv_dir, pln_orig, pln_norm, int_pnt );
12046 
12047      // ang2 is angle between line and plane
12048      double ang2 = AGT_PI_DIV_2 - ang;
12049 
12050      double hypotenuse = offset/sin(ang2);
12051 
12052      double final_pnt[3];
12053 
12054      agt->next_pnt( int_pnt, crv_dir, hypotenuse, final_pnt );
12055 
12056      double end1[3], end2[3];
12057      CubitVector start, end;
12058      start = ref_edge_ptr->start_coordinates();
12059      end = ref_edge_ptr->end_coordinates();
12060      end1[0]=start.x(); end1[1]=start.y(); end1[2]=start.z();
12061      end2[0]=end.x(); end2[1]=end.y(); end2[2]=end.z();
12062 
12063      CubitVector curve_position;
12064      if( agt->is_pnt_on_ln_seg( final_pnt, end1, end2 ) )
12065      {
12066         curve_position.x( final_pnt[0] );
12067         curve_position.y( final_pnt[1] );
12068         curve_position.z( final_pnt[2] );
12069      }
12070      else
12071      {
12072         agt->reverse_vec( crv_dir, crv_dir );
12073 
12074         agt->next_pnt( int_pnt, crv_dir, hypotenuse, final_pnt );
12075 
12076         if( agt->is_pnt_on_ln_seg( final_pnt, end1, end2 ) )
12077         {
12078            curve_position.x( final_pnt[0] );
12079            curve_position.y( final_pnt[1] );
12080            curve_position.z( final_pnt[2] );
12081         }
12082         else
12083         {
12084            PRINT_ERROR( "Resultant point does not lie on bounded curve\n" );
12085            return CUBIT_FAILURE;
12086         }
12087      }
12088      intersection_list.append( curve_position );
12089   }
12090   else
12091   {
12092      DLIList<TopologyEntity*> entity_list(2);
12093      DLIList<TopologyBridge*> bridge_list(2);
12094      entity_list.append(ref_edge_ptr);
12095      entity_list.append(ref_face_ptr);
12096      GeometryModifyEngine* gme_ptr1 = common_modify_engine(entity_list,bridge_list);
12097 
12098      if( gme_ptr1 == 0 )
12099      {
12100         PRINT_ERROR( "Curve %d and Surface %d do not have the same underlying geometry modeling engine\n"
12101            "       For intersection calculations, they must be the same\n",
12102            ref_edge_ptr->id(), ref_face_ptr->id() );
12103         return CUBIT_FAILURE;
12104      }
12105 
12106      bridge_list.reset();
12107      curve_ptr = dynamic_cast<Curve*>(bridge_list.next(0));
12108      surface_ptr = dynamic_cast<Surface*>(bridge_list.next(1));
12109 
12110      // Use geometry engine to find intersections
12111      return gme_ptr1->get_offset_intersections( curve_ptr, surface_ptr,
12112                                                 intersection_list, offset, ext_surf );
12113 
12114   }
12115 
12116   return CUBIT_FAILURE;
12117 }
12118 
12119 CubitStatus GeometryModifyTool::get_mid_plane( RefFace *ref_face1,
12120                                                RefFace *ref_face2,
12121                                                Body *body_to_trim_to,
12122                                                DLIList<RefFace*> &mid_plane_surfs ) const
12123 {
12124   if( ref_face1 == ref_face2 )
12125   {
12126     PRINT_ERROR("Cannot create midplane between the same surface.\n"
12127                 "       Surface %d was entered twice\n",  ref_face1->id() );
12128     return CUBIT_FAILURE;
12129   }
12130 
12131   BodySM* body_sm_to_trim_to = body_to_trim_to->get_body_sm_ptr();
12132   GeometryModifyEngine *gme1_ptr = get_engine(body_sm_to_trim_to);
12133   if ( !gme1_ptr )
12134   {
12135     PRINT_ERROR("Geometry can't be modified, no associated modify engine.\n");
12136     return CUBIT_FAILURE;
12137   }
12138 
12139   CubitVector normal_1, normal_2, point_1, point_2, point_3;
12140   CubitPlane plane_1, plane_2;
12141   CubitVector p_mid, n_mid;
12142 
12143   point_1 = ref_face1->center_point();
12144   point_2 = ref_face2->center_point();
12145 
12146   normal_1 = ref_face1->normal_at(point_1);
12147   normal_2 = ref_face2->normal_at(point_2);
12148 
12149   plane_1 = CubitPlane(normal_1,point_1);
12150   plane_2 = CubitPlane(normal_2,point_2);
12151 
12152   if(point_1 == point_2)
12153   {
12154     PRINT_ERROR("Since both surfaces share the same point, the midplane is not well-defined\n");
12155     return CUBIT_FAILURE;
12156   }
12157   else
12158   {
12159     CubitVector temp1 = point_2;
12160     temp1 = plane_1.project(temp1);
12161     temp1 -= point_2;
12162     if ( temp1.length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
12163     {
12164       PRINT_ERROR("Since both planes are the same, the mid-plane is not well-defined.\n");
12165       return CUBIT_FAILURE;
12166     }
12167   }
12168 
12169   if(plane_1.normal()==plane_2.normal() || plane_1.normal()==-plane_2.normal())
12170   {
12171     p_mid = (point_1+point_2)/2;
12172     n_mid = plane_1.normal();
12173   }
12174   else
12175   {
12176 
12177     CubitVector direction_of_line;
12178     plane_1.intersect(plane_2,p_mid,direction_of_line);
12179     direction_of_line.normalize();
12180 
12181     // Find if point_1 and point_2 are on the line of intersection
12182     // If they are, then the mid-plane is not well-defined
12183     CubitVector p1 = point_1-p_mid;
12184     CubitVector p2 = point_2-p_mid;
12185     p1.normalize();
12186     p2.normalize();
12187 
12188     if(p1==direction_of_line || p1==-direction_of_line)
12189     {
12190       PRINT_ERROR("P1 is on the line of intersection.\n");
12191       return CUBIT_FAILURE;
12192     }
12193 
12194     if(p2==direction_of_line || p2==-direction_of_line)
12195     {
12196       PRINT_ERROR("P2 is on the line of intersection.\n");
12197       return CUBIT_FAILURE;
12198     }
12199 
12200     CubitVector v1 = p1 - (p1%direction_of_line)*direction_of_line;
12201     v1.normalize();
12202 
12203     CubitVector v2 = p2 - (p2%direction_of_line)*direction_of_line;
12204     v2.normalize();
12205 
12206     n_mid = v1 - v2;
12207     n_mid.normalize();
12208   }
12209 
12210   CubitPlane mid_plane(n_mid, p_mid);
12211   point_1 = p_mid;
12212     //find three points that will define the infinite plane from the
12213     //mid plane.
12214   CubitVector test1(1,0,0), test1n(-1,0,0),test2(0,1,0);
12215   CubitVector direction1;
12216     //through the point in any direction just not along the
12217     //normal direction.
12218   if(n_mid != test1 && n_mid != test1n )
12219     direction1 = test1 + n_mid;
12220   else
12221     direction1 = test2 + n_mid;
12222 
12223   point_2 = p_mid + direction1;
12224   point_2 = mid_plane.project(point_2);
12225 
12226   direction1 = point_2-point_1;
12227   CubitVector direction2 = direction1*n_mid;
12228   point_3 = point_1 + direction2;
12229 
12230   BodySM* midplane_body_sm = NULL;
12231   CubitStatus ret = gme1_ptr->get_mid_plane(point_1, point_2, point_3,
12232                                             body_sm_to_trim_to, midplane_body_sm );
12233 
12234   if (midplane_body_sm)
12235   {
12236     Body *midplane_body;
12237 
12238     midplane_body = GeometryQueryTool::instance()->make_Body(midplane_body_sm);
12239 
12240     DLIList<RefFace*> ref_faces;
12241     midplane_body->ref_faces( ref_faces );
12242 
12243     //make each surface of the body into its own body
12244     int i;
12245     for( i=0; i<ref_faces.size(); i++ )
12246     {
12247       RefEntity *new_entity_ptr;
12248       new_entity_ptr = GeometryModifyTool::instance()->copy_refentity(ref_faces.get_and_step());
12249       RefFace *ref_face_ptr = CAST_TO(new_entity_ptr, RefFace);
12250       mid_plane_surfs.append( ref_face_ptr );
12251     }
12252     GeometryQueryTool::instance()->delete_Body( midplane_body );
12253   }
12254   else
12255     return CUBIT_FAILURE;
12256 
12257   return ret;
12258 }
12259 
12260 //=============================================================================
12261 // Function   : get_planar_mid_surface
12262 // Member Type: LOCAL
12263 // Description: Calculates a mid-surface between 2 planar surfaces.
12264 // Author     : Philippe Pebay
12265 // Date       : 05/15/06
12266 //=============================================================================
12267 CubitStatus get_planar_mid_surface( RefFace* ref_face1,
12268                     RefFace* ref_face2,
12269                     BodySM* body_sm_to_trim_to,
12270                     BodySM*& midsurface_body_sm,
12271                     GeometryModifyEngine *gme_ptr )
12272 {
12273     CubitVector normal_1, normal_2, point_1, point_2, point_3;
12274     CubitPlane plane_1, plane_2;
12275     CubitVector p_mid, n_mid;
12276 
12277     point_1 = ref_face1->center_point();
12278     point_2 = ref_face2->center_point();
12279 
12280     normal_1 = ref_face1->normal_at(point_1);
12281     normal_2 = ref_face2->normal_at(point_2);
12282 
12283     plane_1 = CubitPlane(normal_1,point_1);
12284     plane_2 = CubitPlane(normal_2,point_2);
12285 
12286     if(point_1 == point_2)
12287     {
12288       PRINT_ERROR( "In GeometryModifyTool:: get_planar_mid_surface\n"
12289            "       Since both surfaces share the same point, the midsurface is not well-defined\n");
12290       return CUBIT_FAILURE;
12291     }
12292     else
12293     {
12294       CubitVector temp1 = point_2;
12295       temp1 = plane_1.project(temp1);
12296       temp1 -= point_2;
12297       if ( temp1.length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
12298     {
12299     PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n"
12300             "       Since both planes are the same, the midsurface is not well-defined.\n");
12301     return CUBIT_FAILURE;
12302     }
12303     }
12304 
12305     if ( ( normal_1.about_equal( normal_2 ) ) || ( (-normal_1).about_equal( normal_2 ) ) )
12306     {
12307       p_mid = (point_1+point_2)/2;
12308       n_mid = plane_1.normal();
12309     }
12310     else
12311     {
12312       CubitVector direction_of_line;
12313       plane_1.intersect(plane_2,p_mid,direction_of_line);
12314       direction_of_line.normalize();
12315 
12316       // Find if point_1 and point_2 are on the line of intersection
12317       // If they are, then the mid-plane is not well-defined
12318       CubitVector p1 = point_1-p_mid;
12319       CubitVector p2 = point_2-p_mid;
12320       p1.normalize();
12321       p2.normalize();
12322 
12323       if(p1==direction_of_line || p1==-direction_of_line)
12324       {
12325     PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n"
12326             "       P1 is on the line of intersection.\n");
12327     return CUBIT_FAILURE;
12328       }
12329 
12330       if(p2==direction_of_line || p2==-direction_of_line)
12331       {
12332     PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n"
12333             "       P2 is on the line of intersection.\n");
12334     return CUBIT_FAILURE;
12335       }
12336 
12337       CubitVector v1 = p1 - (p1%direction_of_line)*direction_of_line;
12338       v1.normalize();
12339 
12340       CubitVector v2 = p2 - (p2%direction_of_line)*direction_of_line;
12341       v2.normalize();
12342 
12343       n_mid = v1 - v2;
12344       n_mid.normalize();
12345     }
12346 
12347     CubitPlane mid_plane(n_mid, p_mid);
12348     point_1 = p_mid;
12349 
12350     //find three points that will define the infinite plane from the
12351     //mid plane.through the point in any direction just not along the
12352     //normal direction
12353     CubitVector Xdir(1,0,0), Ydir(0,1,0);
12354     CubitVector direction1;
12355 
12356     if ( ( ! n_mid.about_equal( Xdir ) ) && ( ! (-n_mid).about_equal( Xdir ) ) )
12357       direction1 = Xdir + n_mid;
12358     else
12359       direction1 = Ydir + n_mid;
12360 
12361     point_2 = p_mid + direction1;
12362     point_2 = mid_plane.project(point_2);
12363 
12364     direction1 = point_2-point_1;
12365     CubitVector direction2 = direction1*n_mid;
12366     point_3 = point_1 + direction2;
12367 
12368     CubitStatus ret = gme_ptr->get_mid_plane(point_1, point_2, point_3,
12369                           body_sm_to_trim_to, midsurface_body_sm );
12370     return ret;
12371 }
12372 
12373 //=============================================================================
12374 // Function   : get_mid_surface
12375 // Member Type: PUBLIC
12376 // Description: Calculates a mid-surface between 2 surfaces (calls appropriate
12377 //              specialized methods if needed).
12378 // Author     : Philippe Pebay
12379 // Date       : 03/07/06
12380 //=============================================================================
12381 CubitStatus GeometryModifyTool::get_mid_surface( RefFace *ref_face1,
12382                                                RefFace *ref_face2,
12383                                                Body *body_to_trim_to,
12384                                                DLIList<RefFace*> &mid_surface_surfs ) const
12385 {
12386   if( ref_face1 == ref_face2 )
12387   {
12388     PRINT_ERROR("Cannot create midplane between the same surface.\n"
12389                 "       Surface %d was entered twice\n",  ref_face1->id() );
12390     return CUBIT_FAILURE;
12391   }
12392 
12393   BodySM *body_sm_to_trim_to = body_to_trim_to->get_body_sm_ptr();
12394   GeometryModifyEngine *gme1_ptr = get_engine(body_sm_to_trim_to);
12395   if ( !gme1_ptr )
12396   {
12397     PRINT_ERROR("In GeometryModifyTool::get_mid_surface\n"
12398         "       Geometry can't be modified, no associated modify engine.\n");
12399     return CUBIT_FAILURE;
12400   }
12401 
12402   bool found_case = false;
12403   CubitStatus ret = CUBIT_SUCCESS;
12404   BodySM* midsurface_body_sm = NULL;
12405 
12406   // Plane to plane case
12407   if ( ( ref_face1->geometry_type() == PLANE_SURFACE_TYPE ) && ( ref_face2->geometry_type() == PLANE_SURFACE_TYPE ) )
12408   {
12409     found_case = true;
12410     ret = get_planar_mid_surface( ref_face1, ref_face2, body_sm_to_trim_to, midsurface_body_sm, gme1_ptr );
12411   }
12412 
12413   // Quadric to quadric cases
12414   if ( ( ( ref_face1->geometry_type() == SPHERE_SURFACE_TYPE ) && ( ref_face2->geometry_type() == SPHERE_SURFACE_TYPE ) )
12415        ||
12416        ( ( ref_face1->geometry_type() == CONE_SURFACE_TYPE ) && ( ref_face2->geometry_type() == CONE_SURFACE_TYPE ) )
12417        ||
12418        ( ( ref_face1->geometry_type() == TORUS_SURFACE_TYPE ) && ( ref_face2->geometry_type() == TORUS_SURFACE_TYPE ) ) )
12419   {
12420     found_case = true;
12421     DLIList<TopologyEntity*> entity_list(2);
12422     DLIList<TopologyBridge*> bridge_list(2);
12423 
12424     entity_list.append(ref_face1);
12425     entity_list.append(ref_face2);
12426     GeometryModifyEngine* gme2_ptr = common_modify_engine(entity_list,bridge_list);
12427 
12428     if( gme2_ptr == 0 )
12429     {
12430       PRINT_ERROR( "In GeometryModifyTool::get_mid_surface\n"
12431            "       Surfaces %d and %d do not have the same underlying geometry modeling engine.\n"
12432            "       For midsurface calculations, they must be the same\n",
12433            ref_face1->id(), ref_face2->id() );
12434       return CUBIT_FAILURE;
12435     }
12436 
12437     if( gme1_ptr != gme2_ptr )
12438     {
12439       PRINT_ERROR( "In GeometryModifyTool::get_mid_surface\n"
12440            "       Body and surfaces do not have the same underlying geometry modeling engine.\n"
12441            "       For midsurface calculations, they must be the same\n");
12442       return CUBIT_FAILURE;
12443     }
12444 
12445     bridge_list.reset();
12446     Surface* surface1_ptr = dynamic_cast<Surface*>(bridge_list.next(0));
12447     Surface* surface2_ptr = dynamic_cast<Surface*>(bridge_list.next(1));
12448 
12449     // Sphere to sphere case
12450     if ( ( ref_face1->geometry_type() == SPHERE_SURFACE_TYPE ) && ( ref_face2->geometry_type() == SPHERE_SURFACE_TYPE ) )
12451     {
12452       ret = gme2_ptr->get_spheric_mid_surface( surface1_ptr, surface2_ptr, body_sm_to_trim_to, midsurface_body_sm );
12453     }
12454 
12455     // Cone to cone case
12456     if ( ( ref_face1->geometry_type() == CONE_SURFACE_TYPE ) && ( ref_face2->geometry_type() == CONE_SURFACE_TYPE ) )
12457     {
12458       ret = gme2_ptr->get_conic_mid_surface( surface1_ptr, surface2_ptr, body_sm_to_trim_to, midsurface_body_sm );
12459     }
12460 
12461     // Torus to torus case
12462     if ( ( ref_face1->geometry_type() == TORUS_SURFACE_TYPE ) && ( ref_face2->geometry_type() == TORUS_SURFACE_TYPE ) )
12463     {
12464       ret = gme2_ptr->get_toric_mid_surface( surface1_ptr, surface2_ptr, body_sm_to_trim_to, midsurface_body_sm );
12465     }
12466   }
12467 
12468   // Unsupported pair of surfaces
12469   if ( ! found_case )
12470   {
12471     PRINT_ERROR("In GeometryModifyTool::get_mid_surface\n"
12472         "       Midsurface calculation not yet supported for such a pair of surfaces.\n");
12473     return CUBIT_FAILURE;
12474   }
12475 
12476   if ( midsurface_body_sm )
12477   {
12478     if(CubitUndo::get_undo_enabled())
12479       CubitUndo::save_state();
12480 
12481     DLIList<Surface*> mid_surfaces;
12482     DLIList<Body*> new_bodies;
12483     midsurface_body_sm->surfaces( mid_surfaces);
12484     //make each surface of the body into its own body
12485     int i;
12486     for( i=0; i<mid_surfaces.size(); i++ )
12487     {
12488       Surface *tmp_surface = mid_surfaces.get_and_step();
12489       Surface* new_surface_ptr = gme1_ptr->make_Surface( tmp_surface );
12490 
12491       Body *new_Body = make_Body(new_surface_ptr);
12492       new_bodies.append( new_Body );
12493       DLIList<RefFace*> ref_faces;
12494       new_Body->ref_faces(ref_faces);
12495       RefFace *ref_face_ptr = ref_faces.get();
12496       mid_surface_surfs.append( ref_face_ptr );
12497     }
12498     gme1_ptr->get_gqe()->delete_solid_model_entities( midsurface_body_sm );
12499 
12500     if( CubitUndo::get_undo_enabled() )
12501     {
12502       if( new_bodies.size() )
12503         CubitUndo::note_result_bodies( new_bodies );
12504       else
12505         CubitUndo::remove_last_undo();
12506     }
12507 
12508     return ret;
12509   }
12510   else
12511     return CUBIT_FAILURE;
12512 }
12513 
12514 CubitStatus GeometryModifyTool::set_default_gme(GeometryModifyEngine* GMEPtr)
12515 {
12516     if(!GMEPtr)
12517         return CUBIT_FAILURE;
12518 
12519     int i;
12520     for (i = 0; i < gmeList.size(); i++)
12521     {
12522         if(GMEPtr == gmeList.get())
12523             break;
12524 
12525         gmeList.step();
12526     }
12527 
12528     if(i == gmeList.size())
12529         return CUBIT_FAILURE;
12530 
12531     GeometryModifyEngine* temp_ptr = gmeList.get();
12532     gmeList.remove();
12533     gmeList.insert_first(temp_ptr);
12534     return CUBIT_SUCCESS;
12535 }
12536 
12537 //=============================================================================
12538 // Description: Consolidate common setup code for tweak surface operations
12539 // Author     : Jason Kraftcheck
12540 // Date       : 11/05/03
12541 //=============================================================================
12542 GeometryModifyEngine*
12543 GeometryModifyTool::tweak_setup( DLIList<RefFace*> &input_faces,
12544                                  const char* name,
12545                                  DLIList<Body*> &output_bodies,
12546                                  DLIList<Surface*> &output_surfaces,
12547                                  CubitBoolean allow_composites)
12548 {
12549   if( input_faces.size() == 0 )
12550   {
12551     PRINT_ERROR( "No surfaces specified\n" );
12552     return 0;
12553   }
12554 
12555   //are any of the input faces merged? ...disallow that
12556   int i;
12557   for( i=input_faces.size(); i--; )
12558   {
12559     RefFace *tmp_face = input_faces.get();
12560     if( tmp_face->is_merged() )
12561     {
12562       input_faces.change_to( NULL );
12563       PRINT_ERROR("Surface %d is a merged surface.  Cannot perform %s operation on it.\n"
12564                   "       Unmerge it first\n",  tmp_face->id(), name );
12565     }
12566     input_faces.step();
12567   }
12568   input_faces.remove_all_with_value( NULL );
12569   if( input_faces.size() == 0 )
12570     return 0;
12571 
12572   // Get parent bodies
12573   DLIList<TopologyEntity*> query_input(input_faces.size()), query_output;
12574   CAST_LIST_TO_PARENT(input_faces, query_input);
12575   ModelQueryEngine::instance()
12576     ->query_model( query_input, DagType::body_type(), query_output );
12577   CAST_LIST(query_output, output_bodies, Body);
12578 
12579   if(allow_composites)
12580   {
12581     if (!okay_to_modify( output_bodies, "TWEAK" ))
12582       return 0;
12583   }
12584   else
12585   {
12586     if ( contains_intermediate_geom(output_bodies))
12587     {
12588       PRINT_ERROR("%s surfaces on volumes containing virtual geometry\n"
12589         "       is not allowed.\n"
12590         "       Delete virtual geometry on these volumes before operation.\n",
12591         name);
12592       return 0;
12593     }
12594   }
12595 
12596   // Get engine and corresponding geom entities
12597   GeometryModifyEngine* gme_ptr;
12598   gme_ptr = common_modify_engine( input_faces, output_surfaces, allow_composites );
12599   if (!gme_ptr)
12600   {
12601     PRINT_ERROR("%s surfaces on volumes containing surfaces from different\n"
12602       "       geometry engines is not allowed.\n", name);
12603   }
12604 
12605   return gme_ptr;
12606 }
12607 
12608 //=============================================================================
12609 // Description: Consolidate common setup code for tweak curve operations
12610 // Author     : Steve Storm
12611 // Date       : 03/25/05
12612 //=============================================================================
12613 GeometryModifyEngine*
12614 GeometryModifyTool::tweak_setup( DLIList<RefEdge*> &input_curves,
12615                                  const char* name,
12616                                  DLIList<Body*> &output_bodies,
12617                                  DLIList<Curve*> &output_curves,
12618                                  CubitBoolean allow_composites )
12619 {
12620   if( input_curves.size() == 0 )
12621   {
12622     PRINT_ERROR( "No curves specified\n" );
12623     return 0;
12624   }
12625 
12626   //are any of the input curves merged? ...disallow that
12627   int i;
12628   for( i=input_curves.size(); i--; )
12629   {
12630     RefEdge *tmp_edge = input_curves.get();
12631     if( tmp_edge->is_merged() )
12632     {
12633       input_curves.change_to( NULL );
12634       PRINT_ERROR("Curve %d is a merged curve.  Cannot perform %s operation on it.\n"
12635                   "       Unmerge it first\n",  tmp_edge->id(), name );
12636     }
12637     input_curves.step();
12638   }
12639   input_curves.remove_all_with_value( NULL );
12640   if( input_curves.size() == 0 )
12641     return 0;
12642 
12643   // Get parent bodies
12644   DLIList<TopologyEntity*> query_input(input_curves.size()), query_output;
12645   CAST_LIST_TO_PARENT(input_curves, query_input);
12646   ModelQueryEngine::instance()
12647     ->query_model( query_input, DagType::body_type(), query_output );
12648   CAST_LIST(query_output, output_bodies, Body);
12649 
12650   if(allow_composites)
12651   {
12652     if (!okay_to_modify( output_bodies, "TWEAK" ))
12653       return 0;
12654   }
12655   else
12656   {
12657     if ( contains_intermediate_geom(output_bodies))
12658     {
12659       PRINT_ERROR("%s surfaces on volumes containing virtual geometry\n"
12660                   "       is not allowed.\n"
12661                   "       Delete virtual geometry on these volumes before operation.\n",
12662                   name);
12663       return 0;
12664     }
12665   }
12666 
12667   // Get engine and corresponding geom entities
12668   GeometryModifyEngine* gme_ptr;
12669   gme_ptr = common_modify_engine( input_curves, output_curves );
12670   if (!gme_ptr)
12671   {
12672     PRINT_ERROR("%s curves on entities containing surfaces from different\n"
12673       "       geometry engines is not allowed.\n", name);
12674   }
12675 
12676   return gme_ptr;
12677 }
12678 
12679 //=============================================================================
12680 // Description: Consolidate common setup code for tweak vertex operations
12681 // Author     : Steve Storm
12682 // Date       : 03/25/05
12683 //=============================================================================
12684 GeometryModifyEngine*
12685 GeometryModifyTool::tweak_setup( DLIList<RefVertex*> &input_vertices,
12686                                  const char* name,
12687                                  DLIList<Body*> &output_bodies,
12688                                  DLIList<TBPoint*> &output_points,
12689                                  CubitBoolean allow_composites )
12690 {
12691   if( input_vertices.size() == 0 )
12692   {
12693     PRINT_ERROR( "No vertices specified\n" );
12694     return 0;
12695   }
12696 
12697   //are any of the input vertices merged? ...disallow that
12698   int i;
12699   for( i=input_vertices.size(); i--; )
12700   {
12701     RefVertex *tmp_vert = input_vertices.get();
12702     if( tmp_vert->is_merged() )
12703     {
12704       input_vertices.change_to( NULL );
12705       PRINT_ERROR("Vertex %d is a merged vertex.  Cannot perform %s operation on it.\n"
12706                   "       Unmerge it first\n",  tmp_vert->id(), name );
12707     }
12708     input_vertices.step();
12709   }
12710   input_vertices.remove_all_with_value( NULL );
12711   if( input_vertices.size() == 0 )
12712     return 0;
12713 
12714   // Get parent bodies
12715   DLIList<TopologyEntity*> query_input(input_vertices.size()), query_output;
12716   CAST_LIST_TO_PARENT(input_vertices, query_input);
12717   ModelQueryEngine::instance()
12718     ->query_model( query_input, DagType::body_type(), query_output );
12719   CAST_LIST(query_output, output_bodies, Body);
12720 
12721   if(allow_composites)
12722   {
12723     if (!okay_to_modify( output_bodies, "TWEAK" ))
12724       return 0;
12725   }
12726   else
12727   {
12728     if ( contains_intermediate_geom(output_bodies))
12729     {
12730       PRINT_ERROR("%s surfaces on volumes containing virtual geometry\n"
12731                   "       is not allowed.\n"
12732                   "       Delete virtual geometry on these volumes before operation.\n",
12733                   name);
12734       return 0;
12735     }
12736   }
12737 
12738   // Get engine and corresponding geom entities
12739   GeometryModifyEngine* gme_ptr;
12740   gme_ptr = common_modify_engine( input_vertices, output_points, allow_composites );
12741   if (!gme_ptr)
12742   {
12743     PRINT_ERROR("%s vertices on entities containing surfaces from different\n"
12744       "       geometry engines is not allowed.\n", name);
12745   }
12746 
12747   return gme_ptr;
12748 }
12749 
12750 //=============================================================================
12751 // Description: The user selects a surface they would like to idealize and also selects a radius
12752 //              size for fillets.  The user also specifies whether to consider internal and/or external fillets.
12753 //              The program will identify fillets which meet the users criteria and tweak remove them automatically.
12754 //              There is also a preview and exclude curve capability.
12755 // Author     : Jonathan Bugman
12756 // Date       : 10/23/2008
12757 //=============================================================================
12758 CubitStatus GeometryModifyTool::idealize_fillet_geometry(DLIList<RefEntity*> idealize_entity,
12759                                                          DLIList<RefEntity*> exclude_entity,
12760                                                          double fillet_rad,
12761                                                          CubitBoolean internal_flg,
12762                                                          CubitBoolean external_flg,
12763                                                          CubitBoolean preview)
12764 {
12765     //cast the DLIList<RefEntity> to a DLIList<RefFace>
12766     DLIList<RefFace*> face_to_idealize;
12767     CAST_LIST(idealize_entity, face_to_idealize, RefFace);
12768 
12769     //grabbing geometry tolerance
12770     double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance(),temp_fillet_radius;
12771 
12772     //grabbing all the curve loops ONLY from surfaces which are a sheet body
12773     int y, i, j, z;
12774     DLIList<RefFace*> sheet_body_idealize_face;
12775 
12776     for(i=0; i<face_to_idealize.size(); i++)
12777     {
12778         RefFace* target_face = face_to_idealize.get_and_step();
12779         DLIList<Shell*> shell_list;
12780         target_face->shells(shell_list);
12781         for(j=0; j<shell_list.size(); j++)
12782         {
12783             Shell* target_shell = shell_list.get_and_step();
12784             if(target_face->is_nonmanifold( (GroupingEntity*)target_shell ) )
12785             {
12786                 sheet_body_idealize_face.append(face_to_idealize[i]);
12787             }
12788         }
12789     }
12790 
12791     face_to_idealize.clean_out();
12792 
12793     //this section is going to remove all excluded curves loopsm from the 'master' loopsm list
12794     DLIList<Curve*> exclude_cuves;
12795     DLIList <Body*> old_body_list;
12796     if(exclude_entity.size()>0)
12797     {
12798         //cast the exclude DLIList<RefEntity> to DLIList<RefEdge>
12799         DLIList<RefEdge*> exclude_edge;
12800         CAST_LIST(exclude_entity, exclude_edge, RefEdge);
12801 
12802         //switching the DLIList<RefEdge> to DLIList<Curve>
12803         GeometryModifyEngine* gme_ptr1;
12804         gme_ptr1 = tweak_setup(exclude_edge,"idealize",old_body_list,exclude_cuves);
12805         if (NULL == gme_ptr1) {
12806           PRINT_ERROR("Unexpected NULL GeometryModifyEngine pointer.\n");
12807           return CUBIT_FAILURE;
12808         }
12809         exclude_edge.clean_out();
12810     }
12811 
12812     //switching the DLIList<RefFace> to DLIList<Surface>
12813     GeometryModifyEngine* gme_ptr;
12814     DLIList<Surface*> sheet_body_idealize_surface;
12815     gme_ptr = tweak_setup(sheet_body_idealize_face,"idealize",old_body_list,sheet_body_idealize_surface);
12816     sheet_body_idealize_face.clean_out();
12817 
12818     //grab all the loops from each sheet body surface
12819     DLIList <LoopSM*> idealize_loopSM_list;
12820     for(y=0;y<sheet_body_idealize_surface.size();y++)
12821     {
12822         sheet_body_idealize_surface[y]->loopsms(idealize_loopSM_list);
12823     }
12824     sheet_body_idealize_surface.clean_out();
12825 
12826     //search through possible fillet curves filtering only for curves of type arc
12827     //if it is an arc, does it have a straight line on both sides of it, if so'
12828     //check the radius of the arc and if it passes test add it to the list of curves to be tweaked removed
12829     DLIList <Curve*> master_curve_remove_list,possible_fillet_arcs,potential_fillet,internal_fillet, external_fillet, attached_curves;
12830     CubitVector fillet_center_point, intersection_pt,arc_mid,test_point;
12831     DLIList <TBPoint*> arc_vertices;
12832     for(y=0;y<idealize_loopSM_list.size();y++)
12833     {
12834         idealize_loopSM_list[y]->curves(possible_fillet_arcs);
12835         //doing this as a performance boost, it'll keep the code out of the next couple of for loops for situations
12836         //where there is no fillet possible, for instance, a hole with 2 curves will never be a fillet
12837         if(possible_fillet_arcs.size()>3)
12838         {
12839             for(i=0;i<possible_fillet_arcs.size();i++)
12840             {
12841                 if(possible_fillet_arcs[i]->geometry_type() == ARC_CURVE_TYPE &&
12842                     exclude_cuves.is_in_list(possible_fillet_arcs[i])==CUBIT_FALSE)
12843                 {
12844                     possible_fillet_arcs[i]->points(arc_vertices);
12845                     //don't need to check for one point as in a hole because I have a check that there needs to be
12846                     //at least 3 curves in the loop
12847 
12848                     //this is to check that there is only one curve attached to the arc
12849                     for(z=0;z<arc_vertices.size();z++)
12850                     {
12851                         arc_vertices[z]->curves(attached_curves);
12852                         if(attached_curves.size()!=2)
12853                         {
12854                             //I dont' think this break point is going to kick me far enough out of the for loop
12855                             break;
12856                         }
12857                     }
12858 
12859                     possible_fillet_arcs[i]->mid_point(arc_mid);
12860                     possible_fillet_arcs[i]->get_center_radius(fillet_center_point,temp_fillet_radius);
12861                     test_point = arc_mid + geo_tol * (fillet_center_point-arc_mid);
12862                     DLIList<Surface*> test_surf;
12863                     idealize_loopSM_list[y]->surfaces(test_surf);
12864 
12865                     //this may be dangerous but I'm assuming that a loop is on only one surface
12866                     CubitPointContainment cpc = test_surf[0]->point_containment(test_point);
12867                     if(temp_fillet_radius <= fillet_rad && cpc==CUBIT_PNT_INSIDE)
12868                     {
12869                         external_fillet.append(possible_fillet_arcs[i]);
12870                     }
12871                     else if(temp_fillet_radius <= fillet_rad && cpc==CUBIT_PNT_OUTSIDE)
12872                     {
12873                         internal_fillet.append(possible_fillet_arcs[i]);
12874                     }
12875                 }
12876             }
12877         }
12878         possible_fillet_arcs.clean_out();
12879     }
12880 
12881     if(internal_flg==CUBIT_TRUE)
12882     {
12883         master_curve_remove_list+=internal_fillet;
12884     }
12885     if(external_flg==CUBIT_TRUE)
12886     {
12887         master_curve_remove_list+=external_fillet;
12888     }
12889 
12890     //if no arcs are found to be removed, warn the user.
12891     if(master_curve_remove_list.size()==0)
12892     {
12893         PRINT_INFO( "Failed to find any fillets which met users requirements\n\n" );
12894         //I'm returning success here even though no curves were found
12895         return CUBIT_SUCCESS;
12896     }
12897     else if(preview == CUBIT_TRUE)
12898     {
12899         DLIList<BodySM*> new_bodysm_list;
12900         bool old_error_flag = GET_ERROR_FLAG();
12901         SET_ERROR_FLAG(false); // don't throw any tweak_remove errors
12902 
12903         CubitStatus stat = gme_ptr->tweak_remove(master_curve_remove_list, new_bodysm_list,CUBIT_FALSE, CUBIT_TRUE );
12904 
12905         SET_ERROR_FLAG(old_error_flag); // turn errors back on
12906         if(stat==CUBIT_FAILURE)
12907         {
12908             PRINT_WARNING("At least one of the fillets which met your requirements \n"
12909                 "           can't be preview due to the curve's geometry\n");
12910         }
12911 
12912         //output the number of holes or slots which were found
12913         PRINT_INFO("Found %d fillets which met idealization parameters\n\n", master_curve_remove_list.size());
12914         return CUBIT_SUCCESS;
12915     }
12916     else
12917     {
12918         DLIList<BodySM*> new_bodysm_list;
12919         bool old_error_flag = GET_ERROR_FLAG();
12920         SET_ERROR_FLAG(false); // don't throw any tweak_remove errors
12921 
12922         //pass master_curve_remove_list to the tweak_remove command
12923         CubitStatus stat = gme_ptr->tweak_remove(master_curve_remove_list, new_bodysm_list,CUBIT_FALSE, CUBIT_FALSE );
12924         if(stat==CUBIT_FAILURE)
12925         {
12926             PRINT_WARNING("At least one of the fillets which met your requirements \n"
12927                 "           can't be tweaked due to the curve's geometry\n");
12928         }
12929         SET_ERROR_FLAG(old_error_flag); // turn errors back on
12930 
12931         //update DAG
12932         DLIList<Body*> new_body_list;
12933         stat = finish_sm_op( old_body_list, new_bodysm_list ,new_body_list );
12934         //output the number of holes or slots which were found
12935         PRINT_INFO("Found %d fillets which met idealization parameters\n\n", master_curve_remove_list.size());
12936         return CUBIT_SUCCESS;
12937     }
12938 }
12939 
12940 //=============================================================================
12941 // Description: The user selects a surface they would like to idealize and also selects a radius
12942 //              size for holes and or selects a radius and length for slots.  The program will identify
12943 //              'holes' and 'slots' which meet the users criteria and tweak remove them automatically.
12944 //              There is also a preview and exclude curve capability.
12945 // Author     : Jonathan Bugman
12946 // Date       : 10/23/2008
12947 //=============================================================================
12948 CubitStatus GeometryModifyTool::idealize_hole_slot_geometry(DLIList<RefEntity*> idealize_entity,
12949                                                             DLIList<RefEntity*> exclude_entity,
12950                                                             double arc_radius,
12951                                                             double slot_arc_radius,
12952                                                             double slot_length,
12953                                                             CubitBoolean preview)
12954 {
12955     //cast the DLIList<RefEntity> to a DLIList<RefFace>
12956     DLIList<RefFace*> face_to_idealize;
12957     CAST_LIST(idealize_entity, face_to_idealize, RefFace);
12958 
12959     //grabbing geometry tolerance
12960     double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance();
12961 
12962     //grabbing all the curve loops ONLY from surfaces which are a sheet body
12963     int y=0, i=0, j=0;
12964     DLIList<RefFace*> sheet_body_idealize_face;
12965 
12966     for(i=0; i<face_to_idealize.size(); i++)
12967     {
12968         RefFace* target_face = face_to_idealize.get_and_step();
12969         DLIList<Shell*> shell_list;
12970         target_face->shells(shell_list);
12971         for(j=0; j<shell_list.size(); j++)
12972         {
12973             Shell* target_shell = shell_list.get_and_step();
12974             if(target_face->is_nonmanifold( (GroupingEntity*)target_shell ) )
12975             {
12976                 sheet_body_idealize_face.append(face_to_idealize[i]);
12977             }
12978         }
12979     }
12980 
12981     //if no faces to idealize that pass requirements, error out a warning message
12982     if(sheet_body_idealize_face.size()==0)
12983     {
12984         //I'm returning success here even though no surfaces found that meet shell requirements set above
12985         {
12986             PRINT_INFO( "Failed to find any feature(s) which met user requirements\n\n" );
12987         }
12988         return CUBIT_SUCCESS;
12989     }
12990 
12991     //temp_body_ptr = face_to_idealize[y]->body();
12992     //if(temp_body_ptr->is_sheet_body())
12993     //{
12994     //    sheet_body_idealize_face.append(face_to_idealize[y]);
12995     //}
12996 
12997     face_to_idealize.clean_out();
12998 
12999     //switching the DLIList<RefFace> to DLIList<Surface>
13000     GeometryModifyEngine* gme_ptr;
13001     DLIList <Body*> old_body_list;
13002     DLIList<Surface*> sheet_body_idealize_surface;
13003     gme_ptr = tweak_setup(sheet_body_idealize_face,"idealize",old_body_list,sheet_body_idealize_surface);
13004     sheet_body_idealize_face.clean_out();
13005 
13006     //grab all the loops from each sheet body surface
13007     DLIList <LoopSM*> idealize_loopSM_list;
13008     for(y=0;y<sheet_body_idealize_surface.size();y++)
13009     {
13010             sheet_body_idealize_surface[y]->loopsms(idealize_loopSM_list);
13011     }
13012     sheet_body_idealize_surface.clean_out();
13013 
13014     //this section is going to remove all excluded curves loopsm from the 'master' loopsm list
13015     if(exclude_entity.size()>0)
13016     {
13017         //cast the exclude DLIList<RefEntity> to DLIList<RefEdge>
13018         DLIList<RefEdge*> exclude_edge;
13019         CAST_LIST(exclude_entity, exclude_edge, RefEdge);
13020 
13021         //switching the DLIList<RefEdge> to DLIList<Curve>
13022         DLIList<Curve*> exclude_cuves;
13023         GeometryModifyEngine* gme_ptr1;
13024         gme_ptr1 = tweak_setup(exclude_edge,"idealize",old_body_list,exclude_cuves);
13025         if (NULL == gme_ptr1) {
13026           PRINT_ERROR("Unexpected NULL GeometryModifyEngine pointer.\n");
13027           return CUBIT_FAILURE;
13028         }
13029         exclude_edge.clean_out();
13030 
13031         //grabbing all the curve loops from the given excluded curves
13032         DLIList <LoopSM*> exclude_loops;
13033         for(y=0;y<exclude_cuves.size();y++)
13034         {
13035             exclude_cuves[y]->loopsms(exclude_loops);
13036         }
13037         exclude_cuves.clean_out();
13038 
13039         //remove the excluded loops from the list of sheet body loopsms
13040         idealize_loopSM_list -= exclude_loops;
13041     }
13042 
13043     //removing all the external loops from the list as they will not be tweak removed
13044     DLIList <LoopSM*> possible_internal_LoopSM_list;
13045     for(y=0;y<idealize_loopSM_list.size();y++)
13046     {
13047         if(idealize_loopSM_list[y]->loop_type() == LOOP_TYPE_HOLE)
13048         {
13049             possible_internal_LoopSM_list.append(idealize_loopSM_list[y]);
13050         }
13051     }
13052     idealize_loopSM_list.clean_out();
13053     DLIList <Curve*> hole_curves_to_remove;          //hole_curves_to_remove is the curves selected for removal out of the 'hole' search algorithm
13054     DLIList <Curve*> master_curve_remove_list;
13055     DLIList <LoopSM*> arc_LoopSM_list;
13056     DLIList <Surface*> temp_list;
13057 
13059     //this begins the hole search algorithm
13060     //if no arc radius given, skip hole search algorithm
13061     if(arc_radius!=CUBIT_DBL_MAX)
13062     {
13063         DLIList <LoopSM*> not_hole_loop;        //loops which don't meet the all curves are arc type filter
13064         DLIList <Curve*> possible_internal_arcs;
13065 
13066         //search through possible internal curves filtering only for curves of type arc
13067         //if one of the curves in a loop is not an arc, add that loop to the not_hole_loop list
13068         for(y=0;y<possible_internal_LoopSM_list.size();y++)
13069         {
13070             possible_internal_arcs.clean_out();
13071             possible_internal_LoopSM_list[y]->curves(possible_internal_arcs);
13072             for(i=0;i<possible_internal_arcs.size();i++)
13073             {
13074                 temp_list.clean_out();
13075                 possible_internal_arcs[i]->surfaces(temp_list);
13076                 //check whether or not curve is of arc type and whether it is attached to more than one surface
13077                 if( possible_internal_arcs[i]->geometry_type() != ARC_CURVE_TYPE || temp_list.size() != 1)
13078                 {
13079                     not_hole_loop.append(possible_internal_LoopSM_list[y]);
13080                     break;
13081                 }
13082             }
13083         }
13084 
13085         //change name of possible_internal_LoopSM_list to arc_LoopSM_list
13086         arc_LoopSM_list = possible_internal_LoopSM_list;
13087         //subtract from the possible loops the loops which don't have curves which are all arcs or are attached to more than two surfaces
13088         arc_LoopSM_list-=not_hole_loop;
13089         not_hole_loop.clean_out();
13090 
13091         //this next filter checks to make sure that all arcs of the same loop share the same
13092         //radius center within the geometry tolerance
13093         CubitVector arc_center_point, arc_center_point1;
13094         DLIList <LoopSM*> not_center_arc_loop;
13095         double rad_distance, temp_arc_radius , temp_arc_radius1;
13096 
13097         //this for loop is going to check that each loops arc curves have the same center radius point
13098         //if not you can remove that loop as a possibility for being added to the tweak_remove command
13099         for(y=0;y<arc_LoopSM_list.size();y++)
13100         {
13101             //clean out curve list before grabbing a new loop
13102             hole_curves_to_remove.clean_out();
13103             arc_LoopSM_list[y]->curves(hole_curves_to_remove);
13104             //iterate across the hole_curves_to_remove size
13105             for (i=0;i<hole_curves_to_remove.size();i++)
13106             {
13107                 //if you are on the first index, we need to set a baseline radius point
13108                 if(i==0)
13109                 {
13110                     hole_curves_to_remove[i]->get_center_radius(arc_center_point,temp_arc_radius);
13111                     //if this is the only arc in the loop go ahead and check if it meets specified arc parameter
13112                     //if it doesn't meet the users parameter add the loop to the not_center_arc_loop list
13113                     if(temp_arc_radius >= arc_radius && hole_curves_to_remove.size()==1)
13114                     {
13115                         not_center_arc_loop.append(arc_LoopSM_list[y]);
13116                         break;
13117                     }
13118                 }
13119                 //now compare the other arc center points to the baseline, if it ever fails the users parameter
13120                 //add the loop to the not_center_arc_loop list
13121                 else
13122                 {
13123                     hole_curves_to_remove[i]->get_center_radius(arc_center_point1,temp_arc_radius1);
13124                     rad_distance = arc_center_point.distance_between_squared(arc_center_point1);
13125                     if(rad_distance > geo_tol || temp_arc_radius >= arc_radius)
13126                     {
13127                         not_center_arc_loop.append(arc_LoopSM_list[y]);
13128                         break;
13129                     }
13130                 }
13131             }
13132         }
13133 
13134         //remove loops which didn't have perfect circular holes from the arc_loopsm_list
13135         arc_LoopSM_list -= not_center_arc_loop;
13136         for(y=0;y<arc_LoopSM_list.size();y++)
13137         {
13138             arc_LoopSM_list[y]->curves(hole_curves_to_remove);
13139         }
13140         master_curve_remove_list+=hole_curves_to_remove;
13141     }
13142 
13144     //this begins the slot search algorithm
13145     DLIList<LoopSM*> removable_slot_loop;
13146     if(slot_arc_radius!=CUBIT_DBL_MAX || slot_length!=CUBIT_DBL_MAX)
13147     {
13148         DLIList<LoopSM*> four_curve_possible_slot;
13149         DLIList<LoopSM*> possible_slot;
13150         DLIList<Curve*> internal_curves_in_loop;
13151 
13152         //checks to make sure the loop has only four curves - may want to expand this in the future
13153         for(y=0;y<possible_internal_LoopSM_list.size();y++)
13154         {
13155             possible_internal_LoopSM_list[y]->curves(internal_curves_in_loop);
13156             if(internal_curves_in_loop.size()==4)
13157             {
13158                 four_curve_possible_slot.append(possible_internal_LoopSM_list[y]);
13159             }
13160             internal_curves_in_loop.clean_out();
13161         }
13162 
13163 
13164         //check to make sure it alternates straight line, arc, etc...
13165         for(y=0;y<four_curve_possible_slot.size();y++)
13166         {
13167             four_curve_possible_slot[y]->curves(internal_curves_in_loop);
13168 
13169             if(internal_curves_in_loop[0]->geometry_type() == ARC_CURVE_TYPE &&
13170                 internal_curves_in_loop[1]->geometry_type() == STRAIGHT_CURVE_TYPE &&
13171                 internal_curves_in_loop[2]->geometry_type() == ARC_CURVE_TYPE &&
13172                 internal_curves_in_loop[3]->geometry_type() == STRAIGHT_CURVE_TYPE)
13173             {
13174                 int num_of_surfs=0;
13175                 for(i=0;i<internal_curves_in_loop.size();i++)
13176                 {
13177                     temp_list.clean_out();
13178                     internal_curves_in_loop[i]->surfaces(temp_list);
13179                     num_of_surfs=num_of_surfs + temp_list.size();
13180                 }
13181                 if(num_of_surfs==4)
13182                 {
13183                     possible_slot.append(four_curve_possible_slot[y]);
13184                 }
13185             }
13186             else if(internal_curves_in_loop[0]->geometry_type() == STRAIGHT_CURVE_TYPE &&
13187                 internal_curves_in_loop[1]->geometry_type() == ARC_CURVE_TYPE &&
13188                 internal_curves_in_loop[2]->geometry_type() == STRAIGHT_CURVE_TYPE &&
13189                 internal_curves_in_loop[3]->geometry_type() == ARC_CURVE_TYPE)
13190             {
13191                 int num_of_surfs=0;
13192                 for(i=0;i<internal_curves_in_loop.size();i++)
13193                 {
13194                     temp_list.clean_out();
13195                     internal_curves_in_loop[i]->surfaces(temp_list);
13196                     num_of_surfs=num_of_surfs + temp_list.size();
13197                 }
13198                 if(num_of_surfs==4)
13199                 {
13200                     possible_slot.append(four_curve_possible_slot[y]);
13201                 }
13202             }
13203             internal_curves_in_loop.clean_out();
13204         }
13205 
13206         CubitVector arc_center_point;
13207         double temp_arc_radius = CUBIT_DBL_MAX, curve_length = CUBIT_DBL_MAX;
13208 
13209         //check to make sure that the rad and/or length meet users parameters
13210         for(y=0;y<possible_slot.size();y++)
13211         {
13212             possible_slot[y]->curves(internal_curves_in_loop);
13213             //if user specified rad, then passed rad_counter should = 2 after for loop completes
13214             //if length specified, length_counter should =2 after for loop completes
13215             int rad_counter = 0, length_counter = 0;
13216             for(i=0;i<internal_curves_in_loop.size();i++)
13217             {
13218                 //if curve is an arc and user specified a radius enter if statement
13219                 if( internal_curves_in_loop[i]->geometry_type() == ARC_CURVE_TYPE && slot_arc_radius!=CUBIT_DBL_MAX )
13220                 {
13221                     //check the radius against the user inputed value
13222                     internal_curves_in_loop[i]->get_center_radius(arc_center_point,temp_arc_radius);
13223                     if(temp_arc_radius <= slot_arc_radius)
13224                     {
13225                         //if it passes rad test, add to rad_counter
13226                         rad_counter++;
13227                     }
13228                 }
13229                 else if(internal_curves_in_loop[i]->geometry_type() == STRAIGHT_CURVE_TYPE && slot_length!=CUBIT_DBL_MAX )
13230                 {
13231                     //check the length against the user inputed value
13232                     curve_length = internal_curves_in_loop[i]->get_arc_length();
13233                     if(curve_length <= slot_length)
13234                     {
13235                         //if it passes rad test, add to length_counter
13236                         length_counter++;
13237                     }
13238                 }
13239             }
13240 
13241             //checks that if user specified length and radius constraint that its parameter passes for all four curves
13242             if(slot_length!=CUBIT_DBL_MAX && slot_arc_radius!=CUBIT_DBL_MAX  && rad_counter==2 && length_counter==2)
13243             {
13244                 removable_slot_loop.append(possible_slot[y]);
13245             }
13246 
13247             //if user only specified one length or arc parameter, it only needs to meet 2 criteria
13248             else if((slot_length!=CUBIT_DBL_MAX  && length_counter==2) || (slot_arc_radius!=CUBIT_DBL_MAX  && rad_counter==2))
13249             {
13250                 removable_slot_loop.append(possible_slot[y]);
13251             }
13252             internal_curves_in_loop.clean_out();
13253         }
13254         //add removable loops curves to the master_curve_remove_list list
13255         for(y=0;y<removable_slot_loop.size();y++)
13256         {
13257             removable_slot_loop[y]->curves(master_curve_remove_list);
13258         }
13259     }
13260 
13261     //if no arcs are found to be removed, warn the user.
13262     if(master_curve_remove_list.size()==0)
13263     {
13264         //I'm returning success here even though no curves were found
13265         {
13266             PRINT_INFO( "Failed to find any feature(s) which met user requirements\n\n" );
13267         }
13268         return CUBIT_SUCCESS;
13269     }
13270     else if(preview == CUBIT_TRUE)
13271     {
13272         GfxPreview::clear();
13273 
13274         for(i=0; i<master_curve_remove_list.size();i++)
13275         {
13276             CubitStatus result;
13277             GMem g_mem;
13278 
13279             // get the graphics
13280             result = master_curve_remove_list[i]->get_geometry_query_engine()->
13281                 get_graphics( master_curve_remove_list[i], &g_mem );
13282 
13283             if (result==CUBIT_FAILURE || g_mem.pointListCount == 0)
13284             {
13285                 PRINT_WARNING("Unable to preview a curve\n" );
13286                 double len = master_curve_remove_list[i]->
13287                     length_from_u(master_curve_remove_list[i]->start_param(),master_curve_remove_list[i]->end_param());
13288 
13289                 PRINT_WARNING("Curve len: %f\n",len);
13290             }
13291 
13292             // Draw the polyline
13293             GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, CUBIT_BLUE_INDEX );
13294 
13295         }
13296 
13297         //output the number of holes or slots which were found
13298         PRINT_INFO("Found %d holes and %d slots which met idealization parameters\n\n", arc_LoopSM_list.size(),removable_slot_loop.size());
13299         GfxPreview::flush();
13300         return CUBIT_SUCCESS;
13301     }
13302     else
13303     {
13304         DLIList<BodySM*> new_bodysm_list;
13305         //pass master_curve_remove_list to the tweak_remove command
13306         CubitStatus stat = gme_ptr->tweak_remove(master_curve_remove_list, new_bodysm_list,CUBIT_FALSE, CUBIT_FALSE );
13307         if (CUBIT_SUCCESS != stat) {
13308           PRINT_ERROR("GeometryModifyEngine::tweak_remove failed.\n");
13309           return stat;
13310         }
13311 
13312         //update DAG
13313         DLIList<Body*> new_body_list;
13314         stat = finish_sm_op( old_body_list, new_bodysm_list ,new_body_list );
13315         //output the number of holes or slots which were found
13316         PRINT_INFO("Found %d holes, and %d slots which met idealization parameters\n\n", arc_LoopSM_list.size(), removable_slot_loop.size());
13317         return CUBIT_SUCCESS;
13318     }
13319 }
13320 
13321 //=============================================================================
13322 // Description: Create drop down surfaces from the external edges of a surface to another surface with options
13323 //          Use it primarially when you have a doubler plate situation and you need
13324 //      to connect them together with surfaces to represent a weld
13325 // Author     : Jonathan Bugman
13326 // Date       : 02/07/2008
13327 //=============================================================================
13328 CubitStatus GeometryModifyTool::create_surface_doubler(DLIList<RefEntity*> doubler_entity,
13329                                                        DLIList<RefEntity*> target_entity,
13330                                                        DLIList<Body*> &body_list_out,
13331                                                        CubitBoolean internal_flg,
13332                                                        CubitBoolean extend_flg,
13333                                                        CubitPlane *limit_plane,
13334                                                        CubitVector sweep_direction,
13335                                                        CubitBoolean preview)
13336 {
13337     //need to switch the DLIList<RefEntity> to a DLIList<RefFace>
13338     DLIList<RefFace*> doubler_face;
13339     DLIList<RefFace*> target_face;
13340     CAST_LIST( doubler_entity, doubler_face, RefFace);
13341     CAST_LIST( target_entity, target_face, RefFace);
13342 
13343   bool enable_undo = CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE;
13344   if(enable_undo)
13345   {
13346     CubitUndo::save_state_with_cubit_file(doubler_face);
13347   }
13348 
13349     DLIList <Surface*> doubler_surface;
13350     DLIList <Surface*> target_surface;
13351     DLIList <Body*> old_body_list;
13352     DLIList<RefFace*> tweak_face;
13353     DLIList<Surface*> tweak_surface;
13354     tweak_face+=doubler_face;
13355     tweak_face+=target_face;
13356     GeometryModifyEngine* gme_ptr;
13357     int ii=0, i=0;
13358 
13359     gme_ptr = tweak_setup(tweak_face,"doubler",old_body_list,tweak_surface);
13360     int z;
13361     for(z=0;z<doubler_face.size();z++)
13362     {
13363         doubler_surface.append(tweak_surface[z]);
13364     }
13365   for(z=doubler_face.size();z<tweak_face.size();z++)
13366     {
13367         target_surface.append(tweak_surface[z]);
13368     }
13369 
13370     DLIList<BodySM*> all_kept_bodies;
13371     DLIList<BodySM*> body_convert;
13372     DLIList<Surface*> copied_doubler_surface;
13373     DLIList <BodySM*> tweak_target_bodySM;
13374 
13375     for(z=0;z<doubler_surface.size();z++)
13376     {
13377         copied_doubler_surface.append(gme_ptr->make_Surface(doubler_surface[z]));
13378         body_convert.append(copied_doubler_surface[z]->bodysm());
13379     }
13380 
13381     //each workflow is dependent on whether or not a sweep_direction is specified
13382     if(sweep_direction == CubitVector(0,0,0))
13383     {
13384         DLIList<BodySM*> united_bodies;
13385         DLIList<BodySM*> separate_bodies;
13386         //this section takes all the doublers, unites them, and then splits them.  If only one body
13387         //then skip the aforementioned two steps.
13388         if(doubler_surface.size()==1)
13389         {
13390             separate_bodies=body_convert;
13391         }
13392         else
13393         {
13394             if(gme_ptr->unite(body_convert,united_bodies) == CUBIT_FAILURE || united_bodies.size()==0 )
13395             {
13396                 PRINT_ERROR( "Command failed at unite command\n" );
13397 
13398         if(enable_undo)
13399           CubitUndo::remove_last_undo();
13400 
13401                 return CUBIT_FAILURE;
13402             }
13403 
13404             if(gme_ptr->split_body(united_bodies[0],separate_bodies) == CUBIT_FAILURE || separate_bodies.size()==0)
13405             {
13406                 PRINT_ERROR( "Command failed at separate command\n" );
13407 
13408         if(enable_undo)
13409           CubitUndo::remove_last_undo();
13410 
13411                 return CUBIT_FAILURE;
13412             }
13413         }
13414         for(z=0; z<separate_bodies.size();z++)
13415         {
13416             DLIList<Surface*> body_surface;
13417             separate_bodies[z]->surfaces(body_surface);
13418 
13419             DLIList<CubitVector> doubler_surface_center_points;
13420             int d=0;
13421             for(d=0;d<body_surface.size();d++)
13422             {
13423                 doubler_surface_center_points.append(body_surface[d]->bounding_box().center());
13424             }
13425             CubitVector doubler_normal,doubler_center_pt,doubler_to_target_vector,target_center_pt;
13426             double extrude_distance = 0.0;
13427 
13428             //make sure that the normal of the surface is pointing towards the target surface
13429             //the thicken command thickens in the direction of the surface normal, normals are checked using dot product check
13430             CubitVector center_pt = body_surface[0]->bounding_box().center();
13431             body_surface[0]->closest_point(center_pt,&doubler_center_pt,&doubler_normal);
13432             //adding this for loop because of l bracket doublers may have the first target surface perpendicular to an opposite side doubler surface
13433             //resulting in the code erroneously failing
13434             double dot=0.0;
13435             int mm;
13436             for(mm=0; mm<target_surface.size();mm++)
13437             {
13438                 target_surface[mm]->closest_point_trimmed(doubler_center_pt, target_center_pt);
13439                 doubler_to_target_vector = target_center_pt - doubler_center_pt;
13440                 dot = doubler_to_target_vector.x()*doubler_normal.x()+doubler_to_target_vector.y()*doubler_normal.y()+doubler_to_target_vector.z()*doubler_normal.z();
13441                 if(fabs(dot)>1E-6)
13442                 {
13443                     mm=target_surface.size();
13444                 }
13445             }
13446             if(fabs(dot)<1E-6)
13447             {
13448                 PRINT_ERROR( "Doubler and target surface are touching or are perpendicular to each other\n" );
13449                 for(ii =0;ii<separate_bodies.size();ii++)
13450                 {
13451                     GeometryQueryEngine* gqe = separate_bodies[ii]->get_geometry_query_engine();
13452                     gqe->delete_solid_model_entities(separate_bodies[ii]);
13453                 }
13454 
13455                 if(enable_undo)
13456                   CubitUndo::remove_last_undo();
13457 
13458                 return CUBIT_FAILURE;
13459             }
13460             else if(dot < 0)
13461             {
13462                 if(gme_ptr->reverse_body(separate_bodies[z])==CUBIT_FAILURE)
13463                 {
13464                     PRINT_ERROR( "Command failed at reverse body command.\n" );
13465                     for(ii =0;ii<separate_bodies.size();ii++)
13466                     {
13467                         GeometryQueryEngine* gqe = separate_bodies[ii]->get_geometry_query_engine();
13468                         gqe->delete_solid_model_entities(separate_bodies[ii]);
13469                     }
13470 
13471                     if(enable_undo)
13472                       CubitUndo::remove_last_undo();
13473 
13474                     return CUBIT_FAILURE;
13475                 }
13476                 extrude_distance = 0.0001;
13477             }
13478             else
13479             {
13480                 extrude_distance = 0.0001;
13481             }
13482 
13483             DLIList<BodySM*> thickened_doubler_bodySM;
13484             DLIList<BodySM*> current_body;
13485             current_body.append(separate_bodies[z]);
13486 
13487             if(gme_ptr->thicken(current_body,thickened_doubler_bodySM,extrude_distance,CUBIT_FALSE) == CUBIT_FAILURE || thickened_doubler_bodySM.size()==0)
13488             {
13489                 PRINT_ERROR( "Command failed at thicken command, this may be due to using a non-OCC geometry engine\n" );
13490                 for(ii =0;ii<separate_bodies.size();ii++)
13491                 {
13492                     GeometryQueryEngine* gqe = separate_bodies[ii]->get_geometry_query_engine();
13493                     gqe->delete_solid_model_entities(separate_bodies[ii]);
13494                 }
13495 
13496                 if(enable_undo)
13497                   CubitUndo::remove_last_undo();
13498 
13499                 return CUBIT_FAILURE;
13500             }
13501 
13502             //need to grab the newly created surface opposite the user selected one from the thicken function to carry it through for the tweak target
13503             DLIList<Surface*> thicken_surfaces;
13504             thickened_doubler_bodySM[0]->surfaces(thicken_surfaces);
13505             DLIList <Surface*> post_thicken_doublers;
13506 
13507             int y=0;
13508             for(y=0;y<doubler_surface_center_points.size();y++)
13509             {
13510                 doubler_center_pt = doubler_surface_center_points[y];
13511                 int r=0;
13512                 for(r=0;r<thicken_surfaces.size();r++)
13513                 {
13514                     CubitVector test_center_pt = thicken_surfaces[r]->bounding_box().center();
13515                     if((test_center_pt-doubler_center_pt).length()<=.000001)
13516                     {
13517                         post_thicken_doublers.append(thicken_surfaces[r]);
13518                     }
13519                 }
13520             }
13521 
13522             DLIList <LoopSM*> doubler_loopSM_list;
13523             DLIList <Curve*> doubler_external_curves;
13524             Curve* test_external_curves1 = NULL;
13525             Curve* test_external_curves2 = NULL;
13526 
13527             //need to do this in order to grab all curves, not just external IMPORTANT:THIS HAS TO BE DONE BEFORE THE tweak? COMMAND!
13528             for(y=0;y<post_thicken_doublers.size();y++)
13529             {
13530                 post_thicken_doublers[y]->loopsms(doubler_loopSM_list);
13531             }
13532             for(i=0;i<doubler_loopSM_list.size();i++)
13533             {
13534                 doubler_loopSM_list[i]->curves(doubler_external_curves);
13535             }
13536 
13537             doubler_loopSM_list.clean_out();
13538             tweak_target_bodySM.clean_out();
13539             DLIList <LoopSM*> test_loopSM_list;
13540             DLIList <Curve*> thicken_external_curves;
13541             DLIList <Surface*> tweak_target_surface = thicken_surfaces;
13542 
13543             //stepping through the surfaces from the thicken body
13544             for(i=0; i < thicken_surfaces.size(); i++)
13545             {
13546                 thicken_surfaces[i]->loopsms(test_loopSM_list);
13547                 //grabbing the external curves from the current thicken_surface
13548                 test_loopSM_list[0]->curves(thicken_external_curves);
13549                 test_loopSM_list.clean_out();
13550                 int j=0;
13551                 for(j=0;j<thicken_external_curves.size();j++)
13552                 {
13553                     //step through the first curve
13554                     test_external_curves1 = thicken_external_curves[j];
13555                     int k=0;
13556                     for(k=0; k<doubler_external_curves.size();k++)
13557                     {
13558                         //while stepping through the doubler plate curves, compare them to the test_test_surface curves
13559                         test_external_curves2 = doubler_external_curves[k];
13560 
13561                         //if the two are equal, they are touching the doulber and therefore are either the side surfaces or the doubler
13562                         if(test_external_curves2 == test_external_curves1)
13563                         {
13564                             //remove the surface from the tweak_target_surface list
13565                             tweak_target_surface.remove_all_with_value(thicken_surfaces[i]);
13566                             break;
13567                         }
13568                     }
13569                     if(test_external_curves2 == test_external_curves1)
13570                     {
13571                         break;
13572                     }
13573 
13574                 }
13575                 thicken_external_curves.clean_out();
13576             }
13577 
13578             //pass the found opposite surface into the tweak_target routine
13579             if(gme_ptr->tweak_target(tweak_target_surface,target_surface,tweak_target_bodySM,extend_flg,limit_plane) == CUBIT_FAILURE || tweak_target_bodySM.size()==0)
13580             {
13581                 PRINT_ERROR( "Command failed at Tweak_Target routine\n" );
13582                 for(ii =0;ii<thickened_doubler_bodySM.size();ii++)
13583                 {
13584                     GeometryQueryEngine* gqe = thickened_doubler_bodySM[ii]->get_geometry_query_engine();
13585                     gqe->delete_solid_model_entities(thickened_doubler_bodySM[ii]);
13586                 }
13587 
13588                 if(enable_undo)
13589                   CubitUndo::remove_last_undo();
13590 
13591                 return CUBIT_FAILURE;
13592             }
13593 
13594             //fill out a tweak_body_surface list from tweak_target routine
13595             DLIList<Surface*> tweak_body_surfaces;
13596             tweak_target_bodySM[0]->surfaces(tweak_body_surfaces);
13597             DLIList <Curve*> tweak_external_curves;
13598             doubler_external_curves.clean_out();
13599 
13600             //refilling DLIList's as needed based on internal_flg
13601             //if we are not keeping internal surfaces we do not want it's curves in the doubler_external_curves list
13602             //otherwise if we are, we do want the curves in the list for the following sections for loop
13603             if(internal_flg==CUBIT_FALSE)
13604             {
13605                 int j=0;
13606                 for(i=0;i<post_thicken_doublers.size();i++)
13607                 {
13608                     post_thicken_doublers[i]->loopsms(doubler_loopSM_list);
13609                     for(j=0;j<doubler_loopSM_list.size();j++)
13610                     {
13611                       LoopType loop_type = doubler_loopSM_list[j]->loop_type();
13612                       if(loop_type == LOOP_TYPE_EXTERNAL ||
13613                          loop_type == LOOP_TYPE_U_PERIODIC ||
13614                          loop_type == LOOP_TYPE_V_PERIODIC)
13615                       {
13616                           doubler_loopSM_list[j]->curves(doubler_external_curves);
13617                           break;
13618                       }
13619                     }
13620                     doubler_loopSM_list.clean_out();
13621                 }
13622             }
13623             else
13624             {
13625                 for(i=0;i<post_thicken_doublers.size();i++)
13626                 {
13627                     post_thicken_doublers[i]->loopsms(doubler_loopSM_list);
13628                 }
13629                 for(i=0;i<doubler_loopSM_list.size();i++)
13630                 {
13631                     doubler_loopSM_list[i]->curves(doubler_external_curves);
13632                 }
13633 
13634             }
13635 
13636             DLIList <Surface*> surfaces_to_keep;
13637             for(i=0;i<tweak_body_surfaces.size();i++)
13638             {
13639                 tweak_body_surfaces[i]->loopsms(test_loopSM_list);
13640 
13641                 if(test_loopSM_list.size()==0)
13642                 {
13643                     PRINT_ERROR( "Command failed to find any doubler drop down curves\n" );
13644                     for(ii =0;ii<thickened_doubler_bodySM.size();ii++)
13645                     {
13646                         GeometryQueryEngine* gqe = thickened_doubler_bodySM[ii]->get_geometry_query_engine();
13647                         gqe->delete_solid_model_entities(thickened_doubler_bodySM[ii]);
13648                     }
13649 
13650                     if(enable_undo)
13651                       CubitUndo::remove_last_undo();
13652 
13653                     return CUBIT_FAILURE;
13654                 }
13655 
13656                 test_loopSM_list[0]->curves(tweak_external_curves);
13657                 test_loopSM_list.clean_out();
13658 
13659                 int j=0;
13660                 for(j=0;j<tweak_external_curves.size();j++)
13661                 {
13662                     test_external_curves1 = tweak_external_curves[j];
13663 
13664                     int k=0;
13665                     for(k=0; k<doubler_external_curves.size();k++)
13666                     {
13667                         //while stepping through the doubler plate curves, compare them to the test_loop_list
13668                         test_external_curves2 = doubler_external_curves[k];
13669 
13670                         if(test_external_curves2 == test_external_curves1)
13671                         {
13672                             surfaces_to_keep.append(tweak_body_surfaces[i]);
13673                             break;
13674                         }
13675                     }
13676                     if(test_external_curves2 == test_external_curves1)
13677                     {
13678                         break;
13679                     }
13680                 }
13681                 tweak_external_curves.clean_out();
13682             }
13683 
13684             if(surfaces_to_keep.size()==0)
13685             {
13686                 PRINT_ERROR( "Failed to find and keep surfaces\n" );
13687                 for(ii =0;ii<tweak_target_bodySM.size();ii++)
13688                 {
13689                     GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
13690                     gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
13691                 }
13692 
13693                 if(enable_undo)
13694                   CubitUndo::remove_last_undo();
13695 
13696                 return CUBIT_FAILURE;
13697             }
13698 
13699             //do this to remove the copied_doubler_surface since we no longer need the surface anymore
13700             int c=0;
13701             for(c=0;c<post_thicken_doublers.size();c++)
13702             {
13703                 surfaces_to_keep.remove_all_with_value(post_thicken_doublers[c]);
13704             }
13705 
13706             DLIList <Surface*> surfaces_to_remove = tweak_body_surfaces;
13707             surfaces_to_remove -= surfaces_to_keep;
13708             DLIList<BodySM*> resulting_bodies;
13709 
13710             //remove all surfaces in the surfaces_to_remove list
13711             if(gme_ptr->tweak_remove(surfaces_to_remove,resulting_bodies,CUBIT_FALSE) == CUBIT_FAILURE || resulting_bodies.size()==0)
13712             {
13713                 PRINT_ERROR( "Command failed at Tweak_Remove routine\n" );
13714                 for(ii =0;ii<tweak_target_bodySM.size();ii++)
13715                 {
13716                     GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
13717                     gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
13718                 }
13719 
13720                 if(enable_undo)
13721                   CubitUndo::remove_last_undo();
13722 
13723                 return CUBIT_FAILURE;
13724             }
13725             all_kept_bodies+=resulting_bodies;
13726         }
13727     }
13728     else
13729     {
13730         DLIList<BodySM*> swept_bodies;
13731         DLIList<BodySM*> swept_doubler_bodySM;
13732 
13733         //take the copied_doubler_surface and extrude it along the sweep_direction to create a body
13734         for(z=0;z<copied_doubler_surface.size();z++)
13735         {
13736             DLIList<GeometryEntity*> DLIList_copied_doubler_surface;
13737             DLIList_copied_doubler_surface.append(copied_doubler_surface[z]);
13738             if(gme_ptr->sweep_translational(DLIList_copied_doubler_surface,swept_doubler_bodySM,sweep_direction*0.0001,0.0,0,CUBIT_FALSE,CUBIT_FALSE) == CUBIT_FAILURE || swept_doubler_bodySM.size()==0)
13739             {
13740                 PRINT_ERROR( "Command failed at sweep->extrude command\n" );
13741                 for(ii =0;ii<body_convert.size();ii++)
13742                 {
13743                     GeometryQueryEngine* gqe = body_convert[ii]->get_geometry_query_engine();
13744                     gqe->delete_solid_model_entities(body_convert[ii]);
13745                 }
13746 
13747                 if(enable_undo)
13748                   CubitUndo::remove_last_undo();
13749 
13750                 return CUBIT_FAILURE;
13751             }
13752             swept_bodies+=swept_doubler_bodySM;
13753             swept_doubler_bodySM.clean_out();
13754         }
13755 
13756         DLIList<BodySM*> united_bodies;
13757         DLIList<BodySM*> separate_bodies;
13758         //if more than one body, unite and split the newly created bodies, if only one body skip this step
13759         //as the unite will fail
13760         if(swept_bodies.size()==1)
13761         {
13762             separate_bodies=swept_bodies;
13763         }
13764         else
13765         {
13766             if(gme_ptr->unite(swept_bodies,united_bodies) == CUBIT_FAILURE || united_bodies.size()==0 )
13767             {
13768                 PRINT_ERROR( "Command failed at unite command\n" );
13769 
13770         if(enable_undo)
13771           CubitUndo::remove_last_undo();
13772 
13773                 return CUBIT_FAILURE;
13774             }
13775 
13776             if(gme_ptr->split_body(united_bodies[0],separate_bodies) == CUBIT_FAILURE || separate_bodies.size()==0)
13777             {
13778                 PRINT_ERROR( "Command failed at separate command\n" );
13779 
13780         if(enable_undo)
13781           CubitUndo::remove_last_undo();
13782 
13783                 return CUBIT_FAILURE;
13784             }
13785         }
13786 
13787         //create another copy of copied_doubler_surface since copied_doubler_surface is going to be manipulated
13788         DLIList<Surface*> temp_copied_doubler_surface=copied_doubler_surface;
13789         for(z=0;z<separate_bodies.size();z++)
13790         {
13791             //need to grab the newly created surface opposite the user selected one from the thicken function to carry it through for the tweak target
13792             //this will need to be changed to a for loop to account for multiple thickened bodies if we impliment multiple doubler surfaces
13793             DLIList<Surface*> thicken_surfaces;
13794             separate_bodies[z]->surfaces(thicken_surfaces);
13795 
13796             //initializing a lot of variables to be used in the next few steps
13797             DLIList<Surface*> master_surface_remove_list;
13798             DLIList <Curve*> thicken_external_curves;
13799             DLIList<Surface*> tweak_target_surface;
13800             DLIList<Surface*> surfaces_to_remove;
13801 
13802             //using a centerpoint of the surfaces, I want to find out which surface from the recently swept bodies corresponds to the surface of the body closest the target
13803             //this has to be done because sweep_translational moves the source surface.  Thicken on the otherhand does and doesn't based on number of surfaces being thickened.
13804             int y=0;
13805             for(y=0;y<temp_copied_doubler_surface.size();y++)
13806             {
13807                 CubitVector doubler_center_pt = temp_copied_doubler_surface[y]->bounding_box().center();
13808                 int r=0;
13809                 for(r=0;r<thicken_surfaces.size();r++)
13810                 {
13811                     CubitVector test_center_pt = thicken_surfaces[r]->bounding_box().center();
13812                     if((test_center_pt-doubler_center_pt).length()<=.000001)
13813                     {
13814                         tweak_target_surface.append(thicken_surfaces[r]);
13815                         surfaces_to_remove.append(temp_copied_doubler_surface[y]);
13816                     }
13817                 }
13818             }
13819             //remove the manipulated surfaces from the temp_copied_doubler_surface list
13820             temp_copied_doubler_surface-=surfaces_to_remove;
13821             surfaces_to_remove.clean_out();
13822 
13823             //grab all the curves of the doubler
13824             DLIList <Curve*> doubler_external_curves;
13825             DLIList <LoopSM*> doubler_loopSM_list;
13826             for(y=0;y<tweak_target_surface.size();y++)
13827             {
13828                 tweak_target_surface[y]->loopsms(doubler_loopSM_list);
13829             }
13830 
13831             for(i=0;i<doubler_loopSM_list.size();i++)
13832             {
13833                 doubler_loopSM_list[i]->curves(doubler_external_curves);
13834             }
13835 
13836             DLIList <Surface*> doubler_surface_for_this_body = thicken_surfaces;
13837             Curve* test_external_curves1 = NULL;
13838             Curve* test_external_curves2 = NULL;
13839             DLIList <LoopSM*> test_loopSM_list;
13840 
13841             for(i=0; i < thicken_surfaces.size(); i++)
13842             {
13843                 //step through the thickened bodies surfaces
13844                 thicken_surfaces[i]->loopsms(test_loopSM_list);
13845                 //grabbing the external curve loop from the face and making it a DLIList <RefEdge*>
13846                 test_loopSM_list[0]->curves(thicken_external_curves);
13847 
13848                 int j=0;
13849                 for(j=0;j<thicken_external_curves.size();j++)
13850                 {
13851                     //step through the loop list
13852                     test_external_curves1 = thicken_external_curves[j];
13853 
13854                     int k=0;
13855                     for(k=0; k<doubler_external_curves.size();k++)
13856                     {
13857                         //while stepping through the doubler plate curves, compare them to the test_loop_list
13858                         test_external_curves2 = doubler_external_curves[k];
13859 
13860                         if(test_external_curves2 == test_external_curves1)
13861                         {
13862                             doubler_surface_for_this_body.remove_all_with_value(thicken_surfaces[i]);
13863                             break;
13864                         }
13865                     }
13866                     if(test_external_curves2 == test_external_curves1)
13867                     {
13868                         break;
13869                     }
13870                 }
13871 
13872                 thicken_external_curves.clean_out();
13873                 thicken_external_curves.reset();
13874                 test_loopSM_list.clean_out();
13875             }
13876 
13877             //DLIList <BodySM*> tweak_target_bodySM
13878             tweak_target_bodySM.clean_out();
13879             if(gme_ptr->tweak_target(tweak_target_surface,target_surface,tweak_target_bodySM,extend_flg,limit_plane) == CUBIT_FAILURE || tweak_target_bodySM.size()==0)
13880             {
13881                 PRINT_ERROR( "Command failed at Tweak_Target routine\n" );
13882                 for(ii =0;ii<body_convert.size();ii++)
13883                 {
13884                     GeometryQueryEngine* gqe = body_convert[ii]->get_geometry_query_engine();
13885                     gqe->delete_solid_model_entities(body_convert[ii]);
13886                 }
13887 
13888                 if(enable_undo)
13889                   CubitUndo::remove_last_undo();
13890 
13891                 return CUBIT_FAILURE;
13892             }
13893 
13894             //make note of the doubler_surface and add it to the delete list
13895             master_surface_remove_list+=doubler_surface_for_this_body;
13896 
13897             //clean out these DLIList's as they will be used later on
13898             doubler_loopSM_list.clean_out();
13899             doubler_external_curves.clean_out();
13900 
13901             //refilling DLIList's as needed based on internal_flg
13902             //basically if surfaces share a curve, that surface will be kept so if you don't want the internal surfaces
13903             //create the list without the internal curves and they'll be removed
13904             if(internal_flg==CUBIT_FALSE)
13905             {
13906                 int j=0;
13907                 for(i=0;i<doubler_surface_for_this_body.size();i++)
13908                 {
13909                     doubler_surface_for_this_body[i]->loopsms(doubler_loopSM_list);
13910                     for(j=0;j<doubler_loopSM_list.size();j++)
13911                     {
13912                       LoopType loop_type = doubler_loopSM_list[j]->loop_type();
13913                       if(loop_type == LOOP_TYPE_EXTERNAL ||
13914                          loop_type == LOOP_TYPE_U_PERIODIC ||
13915                          loop_type == LOOP_TYPE_V_PERIODIC)
13916                       {
13917                           doubler_loopSM_list[j]->curves(doubler_external_curves);
13918                           break;
13919                       }
13920 
13921                     }
13922                     doubler_loopSM_list.clean_out();
13923                 }
13924             }
13925             else
13926             {
13927                 for(i=0;i<doubler_surface_for_this_body.size();i++)
13928                 {
13929                     doubler_surface_for_this_body[i]->loopsms(doubler_loopSM_list);
13930                 }
13931                 for(i=0;i<doubler_loopSM_list.size();i++)
13932                 {
13933                     doubler_loopSM_list[i]->curves(doubler_external_curves);
13934                 }
13935             }
13936 
13937             //recreate the thicken_surfaces list based now on the bodies after the tweak_target command
13938             thicken_surfaces.clean_out();
13939             tweak_target_bodySM[0]->surfaces(thicken_surfaces);
13940 
13941             DLIList <Surface*> surfaces_to_keep;
13942             surfaces_to_remove = thicken_surfaces;
13943             DLIList <Curve*> tweak_external_curves;
13944 
13945             for(i=0;i<thicken_surfaces.size();i++)
13946             {
13947                 thicken_surfaces[i]->loopsms(test_loopSM_list);
13948                 //grabs the external curves from face
13949                 test_loopSM_list[0]->curves(tweak_external_curves);
13950 
13951                 int j=0;
13952                 for(j=0;j<tweak_external_curves.size();j++)
13953                 {
13954                     //step through the loop list
13955                     test_external_curves1 = tweak_external_curves[j];
13956 
13957                     int k=0;
13958                     for(k=0; k<doubler_external_curves.size();k++)
13959                     {
13960                         //while stepping through the doubler plate curves, compare them to the test_loop_list
13961                         test_external_curves2 = doubler_external_curves[k];
13962 
13963                         if(test_external_curves2 == test_external_curves1)
13964                         {
13965                             surfaces_to_keep.append(thicken_surfaces[i]);
13966                             break;
13967                         }
13968                     }
13969                     if(test_external_curves2 == test_external_curves1)
13970                     {
13971                         break;
13972                     }
13973                 }
13974                 test_loopSM_list.clean_out();
13975                 tweak_external_curves.clean_out();
13976             }
13977 
13978             if(surfaces_to_keep.size()==0)
13979             {
13980                 PRINT_ERROR( "Failed to find and keep tweak_target surfaces\n" );
13981                 for(ii =0;ii<tweak_target_bodySM.size();ii++)
13982                 {
13983                     GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
13984                     gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
13985                 }
13986 
13987         if(enable_undo)
13988           CubitUndo::remove_last_undo();
13989 
13990                 return CUBIT_FAILURE;
13991             }
13992 
13993             //subtract surfaces
13994             surfaces_to_remove -= surfaces_to_keep;
13995             master_surface_remove_list+=surfaces_to_remove;
13996 
13997             DLIList<BodySM*> resulting_bodies;
13998 
13999             if(gme_ptr->tweak_remove(master_surface_remove_list,resulting_bodies,CUBIT_FALSE) == CUBIT_FAILURE || resulting_bodies.size()==0)
14000             {
14001                 PRINT_ERROR( "Command failed at Tweak_Remove routine\n" );
14002                 for(ii =0;ii<tweak_target_bodySM.size();ii++)
14003                 {
14004                     GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
14005                     gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
14006                 }
14007 
14008         if(enable_undo)
14009           CubitUndo::remove_last_undo();
14010 
14011                 return CUBIT_FAILURE;
14012             }
14013 
14014             //all_kept_bodies is a list of bodies that will eventually be passed into finish_sm_op at the end
14015             all_kept_bodies+=resulting_bodies;
14016         }
14017     }
14018 
14019     if(preview==CUBIT_FALSE)
14020     {
14021         DLIList<BodySM*> bodies_to_unite;
14022         //check to see if their is only one body.  If only one body skip over the unite and split because
14023         //the unite command will fail (there is a check at the beginning to return cubit_failure)
14024         //append the original doubler surfaces to the resulting body list
14025 
14026         for(i=0;i<doubler_surface.size();i++)
14027         {
14028             all_kept_bodies.insert_first(doubler_surface[i]->bodysm());
14029         }
14030         if(all_kept_bodies.size()!=1)
14031         {
14032             if(gme_ptr->unite(all_kept_bodies,bodies_to_unite) == CUBIT_FAILURE || bodies_to_unite.size()==0 )
14033             {
14034                 PRINT_ERROR( "Command failed at unite command\n" );
14035 
14036                 if(enable_undo)
14037                   CubitUndo::remove_last_undo();
14038 
14039                 return CUBIT_FAILURE;
14040             }
14041             all_kept_bodies.clean_out();
14042             if(gme_ptr->split_body(bodies_to_unite[0],all_kept_bodies) == CUBIT_FAILURE || all_kept_bodies.size()==0)
14043             {
14044                 PRINT_ERROR( "Command failed at separate command\n" );
14045 
14046                 if(enable_undo)
14047                   CubitUndo::remove_last_undo();
14048 
14049                 return CUBIT_FAILURE;
14050             }
14051         }
14052         else
14053         {
14054                 PRINT_WARNING( "Command may have failed at finding doubler surface(s) and appending them to the drop-down surfaces\n" );
14055 
14056                 if(enable_undo)
14057                   CubitUndo::remove_last_undo();
14058 
14059                 return CUBIT_FAILURE;
14060         }
14061 
14062         //update DAG
14063         CubitStatus stat;
14064         stat = finish_sm_op( old_body_list, all_kept_bodies ,body_list_out );
14065     if (CUBIT_SUCCESS != stat) {
14066       PRINT_ERROR("GeometryModifyTool::finish_sm_op failed.\n");
14067       return stat;
14068     }
14069     if(enable_undo)
14070       CubitUndo::note_result_bodies(body_list_out);
14071 
14072         return CUBIT_SUCCESS;
14073     }
14074     else
14075     {
14076         DLIList<Curve*> kept_curves;
14077         for(i =0;i<all_kept_bodies.size();i++)
14078         {
14079             all_kept_bodies[i]->curves(kept_curves);
14080         }
14081 
14082         GfxPreview::clear();
14083 
14084         for(i=0; i<kept_curves.size();i++)
14085         {
14086             CubitStatus result;
14087             GMem g_mem;
14088 
14089             // get the graphics
14090             result = kept_curves[i]->get_geometry_query_engine()->
14091                 get_graphics( kept_curves[i], &g_mem );
14092 
14093             if (result==CUBIT_FAILURE || g_mem.pointListCount == 0)
14094             {
14095                 PRINT_WARNING("Unable to preview a curve\n" );;
14096                 double len = kept_curves[i]->
14097                     length_from_u(kept_curves[i]->start_param(),kept_curves[i]->end_param());
14098 
14099                 PRINT_WARNING("Curve len: %f\n",len);
14100             }
14101 
14102             // Draw the polyline
14103             GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, CUBIT_BLUE_INDEX );
14104         }
14105         GfxPreview::flush();
14106         for(ii =0;ii<tweak_target_bodySM.size();ii++)
14107         {
14108             GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
14109             gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
14110         }
14111 
14112         if(enable_undo)
14113           CubitUndo::note_result_bodies(body_list_out);
14114 
14115         return CUBIT_SUCCESS;
14116     }
14117 }
14118 
14119 //=============================================================================
14120 // Function   : tweak_bend
14121 // Member Type: PUBLIC
14122 // Description: Bend solid bodies based on a bend radius and angle
14123 // Author     : Sam Showman
14124 // Date       : 06/23/08
14125 //=============================================================================
14126 CubitStatus GeometryModifyTool::tweak_bend( DLIList<Body*> &bend_bodies,
14127                                             DLIList<Body*> &new_body_list,
14128                                             CubitVector& neutral_root,
14129                                             CubitVector& bend_axis,
14130                                             CubitVector& bend_direction,
14131                                             double radius,
14132                                             double angle,
14133                                             DLIList<CubitVector>& bend_regions,
14134                                             double width,
14135                                             CubitBoolean center_bend,
14136                                             int num_points,
14137                                             CubitBoolean keep_old_body,
14138                                             CubitBoolean preview )
14139 {
14140     if (CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE)
14141     {
14142         if (keep_old_body)
14143             CubitUndo::save_state();
14144         else
14145             CubitUndo::save_state_with_cubit_file( bend_bodies );
14146     }
14147 
14148     DLIList<BodySM*> new_body_sm_list;
14149     DLIList<BodySM*> bend_bodies_sm;
14150     GeometryModifyEngine* engine;
14151     engine = common_modify_engine(bend_bodies, bend_bodies_sm);
14152 
14153     if (!preview)
14154     {
14155         //do_attribute_setup();
14156         //push_attributes_before_modify(bend_bodies_sm);
14157     }
14158 
14159     CubitStatus result = engine->tweak_bend(
14160             bend_bodies_sm,
14161             new_body_sm_list,
14162             neutral_root,
14163             bend_axis,
14164             bend_direction,
14165             radius,
14166             angle,
14167             bend_regions,
14168             width,
14169             center_bend,
14170             num_points,
14171             keep_old_body,
14172             preview);
14173 
14174     if (result == CUBIT_FAILURE)
14175     {
14176         if (!preview)
14177         {
14178             //remove_pushed_attributes(bend_bodies_sm, bend_bodies);
14179             //do_attribute_cleanup();
14180         }
14181         if (CubitUndo::get_undo_enabled())
14182             CubitUndo::remove_last_undo();
14183         return CUBIT_FAILURE;
14184     }
14185 
14186     if (preview == CUBIT_FALSE)
14187     {
14188         //restore_vg_after_modify(new_body_sm_list, bend_bodies, engine);
14189         //remove_pushed_attributes(new_body_sm_list, bend_bodies);
14190 
14191         // Update DAG
14192         CubitStatus stat = finish_sm_op( bend_bodies, new_body_sm_list, new_body_list );
14193         if (CubitUndo::get_undo_enabled())
14194         {
14195             if (stat == CUBIT_SUCCESS)
14196                 CubitUndo::note_result_bodies( new_body_list );
14197             else
14198                 CubitUndo::remove_last_undo();
14199         }
14200 
14201         //do_attribute_cleanup();
14202 
14203         // Update graphics
14204         /*
14205         bend_bodies.reset();
14206         int i = 0;
14207         for (i = 0; i < bend_bodies.size(); i++)
14208         {
14209             Body* body_ptr = bend_bodies.get_and_step();
14210             body_ptr->notify_all_observers( GEOMETRY_MODIFIED );
14211         }//*/
14212 
14213         // get list of entities to update
14214         DLIList<RefEntity*> entities_to_update;
14215         int i;
14216         for(i=0; i < new_body_sm_list.size(); i++)
14217         {
14218             BodySM* bodysm = new_body_sm_list.get_and_step();
14219             DLIList<TopologyBridge*> to_check;
14220             DLIList<TopologyBridge*> tmp;
14221             DLIList<Surface*> surfs;
14222             bodysm->surfaces(surfs);
14223             DLIList<Curve*> curves;
14224             bodysm->curves(curves);
14225             DLIList<TBPoint*> points;
14226             bodysm->points(points);
14227             to_check.append(bodysm);
14228             to_check.append(bodysm->lump());
14229             CAST_LIST_TO_PARENT(surfs, tmp);
14230             to_check += tmp;
14231             CAST_LIST_TO_PARENT(curves, tmp);
14232             to_check += tmp;
14233             CAST_LIST_TO_PARENT(points, tmp);
14234             to_check += tmp;
14235 
14236             int k;
14237             for(k=0; k<to_check.size(); k++)
14238                 if(BridgeManager* m = to_check.get_and_step()->bridge_manager())
14239                     if(TopologyEntity* t = m->topology_entity())
14240                         entities_to_update.append(CAST_TO(t, RefEntity));
14241 
14242         }
14243         // Update graphics
14244         while (entities_to_update.size())
14245             AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
14246 
14247         return stat;
14248     }
14249 
14250     return CUBIT_SUCCESS;
14251 }
14252 
14253 
14254 
14255 //=============================================================================
14256 // Description: Chamfer curves on solid and sheet bodies.  The left and right
14257 //              offsets are with respect to the curve direction.  If the given
14258 //              right offset is negative, the left offset is used.  Users can
14259 //              preview to clarify the meaning of left and right.
14260 // Author     : Steve Storm
14261 // Date       : 03/25/05
14262 //=============================================================================
14263 CubitStatus GeometryModifyTool::tweak_chamfer( DLIList<RefEdge*> &ref_edge_list,
14264                                                double left_offset,
14265                                                DLIList<Body*> &new_body_list,
14266                                                double right_offset,
14267                                                CubitBoolean keep_old_body,
14268                                                CubitBoolean preview )
14269 {
14270   DLIList<Curve*> curve_list(ref_edge_list.size());
14271   DLIList<Body*> old_body_list;
14272   GeometryModifyEngine* gme_ptr;
14273 
14274   gme_ptr = tweak_setup( ref_edge_list, "Chamfering", old_body_list, curve_list, CUBIT_TRUE );
14275   if( !gme_ptr )
14276     return CUBIT_FAILURE;
14277 
14278   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
14279   {
14280     if( keep_old_body )
14281       CubitUndo::save_state();
14282     else
14283       CubitUndo::save_state_with_cubit_file( ref_edge_list );
14284   }
14285 
14286   DLIList<BodySM*> body_sms;
14287   for(int i=old_body_list.size(); i--;)
14288   {
14289     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
14290     if(bsm)
14291       body_sms.append_unique(bsm);
14292   }
14293 
14294   if(!preview)
14295   {
14296     do_attribute_setup();
14297     push_attributes_before_modify(body_sms);
14298   }
14299 
14300   // Do chamfering
14301   DLIList<BodySM*> new_bodysm_list;
14302   CubitStatus stat = gme_ptr->tweak_chamfer( curve_list, left_offset, new_bodysm_list,
14303                                             right_offset, keep_old_body, preview );
14304   if(stat == CUBIT_FAILURE )
14305   {
14306     if(!preview)
14307     {
14308       if( CubitUndo::get_undo_enabled() )
14309         CubitUndo::remove_last_undo();
14310       remove_pushed_attributes(new_bodysm_list, old_body_list);
14311       do_attribute_cleanup();
14312     }
14313     return stat;
14314   }
14315   else
14316   {
14317     if(!preview)
14318     {
14319       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
14320       remove_pushed_attributes(new_bodysm_list, old_body_list);
14321     }
14322   }
14323 
14324   if( preview == CUBIT_FALSE )
14325   {
14326     // Update DAG
14327     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
14328 
14329     if( CubitUndo::get_undo_enabled() )
14330     {
14331       if( stat == CUBIT_SUCCESS )
14332         CubitUndo::note_result_bodies( new_body_list );
14333       else
14334         CubitUndo::remove_last_undo();
14335     }
14336     do_attribute_cleanup();
14337 
14338     return stat;
14339   }
14340   return CUBIT_SUCCESS;
14341 }
14342 
14343 void GeometryModifyTool::propagate_from_small_edge(RefEdge *edge,
14344                                                  DLIList<RefEdge*> &small_edges,
14345                                                  DLIList<RefFace*> &narrow_faces,
14346                                                  DLIList<RefFace*> &processed_faces,
14347                                                  double small_edge_length)
14348 {
14349   int i, j;
14350   // First find any small edges connected to this edge.
14351   DLIList<RefVertex*> edge_verts;
14352   edge->ref_vertices(edge_verts);
14353   for(i=edge_verts.size(); i--;)
14354   {
14355     RefVertex *vert = edge_verts.get_and_step();
14356     DLIList<RefEdge*> vert_edges;
14357     vert->ref_edges(vert_edges);
14358     for(j=vert_edges.size(); j--;)
14359     {
14360       RefEdge *cur_edge = vert_edges.get_and_step();
14361       if(cur_edge != edge && !cur_edge->marked())
14362       {
14363         // Mark of > 0 means it has been processed.
14364         cur_edge->marked(1);
14365         if(cur_edge->get_arc_length() < small_edge_length)
14366         {
14367           small_edges.append(cur_edge);
14368           // Mark of 2 means it is a small edge.
14369           cur_edge->marked(2);
14370           propagate_from_small_edge(cur_edge, small_edges, narrow_faces,
14371             processed_faces, small_edge_length);
14372         }
14373       }
14374     }
14375   }
14376   // Now look at adjacent narrow faces and recursively process them.
14377   DLIList<RefFace*> edge_faces;
14378   edge->ref_faces(edge_faces);
14379   for(i=edge_faces.size(); i--;)
14380   {
14381     RefFace *cur_face = edge_faces.get_and_step();
14382     if(!cur_face->marked())
14383     {
14384       cur_face->marked(1);
14385       if(GeomMeasureTool::narrow_region_exists(cur_face, small_edge_length))
14386       {
14387         DLIList<CubitVector> split_pos1_list;
14388         DLIList<CubitVector> split_pos2_list;
14389         GeomMeasureTool::find_split_points_for_narrow_regions(cur_face,
14390           small_edge_length, split_pos1_list, split_pos2_list);
14391         if(split_pos1_list.size() == 0)
14392         {
14393           narrow_faces.append_unique(cur_face);
14394           propagate_over_narrow_face(cur_face, edge, processed_faces,
14395             small_edges, narrow_faces, small_edge_length);
14396         }
14397       }
14398     }
14399   }
14400 }
14401 
14402 void GeometryModifyTool::propagate_over_narrow_face(RefFace *narrow_face,
14403                                                   RefEdge *edge,
14404                                                   DLIList<RefFace*> &processed_faces,
14405                                                   DLIList<RefEdge*> &small_edges,
14406                                                   DLIList<RefFace*> &narrow_faces,
14407                                                   double small_edge_length)
14408 {
14409   int i, j;
14410   processed_faces.append(narrow_face);
14411   DLIList<RefEdge*> face_edges;
14412   narrow_face->ref_edges(face_edges);
14413   for(i=face_edges.size(); i--;)
14414   {
14415     RefEdge *cur_edge = face_edges.get_and_step();
14416     if(cur_edge != edge && !cur_edge->marked())
14417     {
14418       cur_edge->marked(1);
14419       if(cur_edge->get_arc_length() < small_edge_length)
14420       {
14421         cur_edge->marked(2);
14422         small_edges.append(cur_edge);
14423         propagate_from_small_edge(cur_edge, small_edges,
14424                 narrow_faces, processed_faces, small_edge_length);
14425       }
14426       else
14427       {
14428         DLIList<RefFace*> edge_faces;
14429         cur_edge->ref_faces(edge_faces);
14430         for(j=edge_faces.size(); j--;)
14431         {
14432           RefFace *cur_face = edge_faces.get_and_step();
14433           if(cur_face != narrow_face)
14434           {
14435             if(!cur_face->marked())
14436             {
14437               cur_face->marked(1);
14438               if(GeomMeasureTool::narrow_region_exists(cur_face, small_edge_length))
14439               {
14440                 DLIList<CubitVector> split_pos1_list;
14441                 DLIList<CubitVector> split_pos2_list;
14442                 GeomMeasureTool::find_split_points_for_narrow_regions(cur_face,
14443                   small_edge_length, split_pos1_list, split_pos2_list);
14444                 if(split_pos1_list.size() == 0)
14445                 {
14446                   narrow_faces.append_unique(cur_face);
14447                   propagate_over_narrow_face(cur_face, edge, processed_faces,
14448                     small_edges, narrow_faces, small_edge_length);
14449                 }
14450               }
14451             }
14452           }
14453         }
14454       }
14455     }
14456   }
14457 }
14458 
14459 void GeometryModifyTool::push_tolerance_attribute(DLIList<Body*> &body_list)
14460 {
14461   Body* local_body;
14462   DLIList<RefEntity*> child_list;
14463 
14464   //save attribute settings
14465   CGMApp::instance()->save_current_attribute_states();
14466 
14467   CGMApp::instance()->attrib_manager()->auto_flag(0);
14468   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ENTITY_TOL, CUBIT_TRUE);
14469 
14470   for (int i = body_list.size(); i--;)
14471   {
14472     child_list.clean_out();
14473 
14474     local_body = body_list.get_and_step();
14475     local_body->get_all_child_ref_entities( child_list);
14476     child_list.append(local_body);
14477     CubitAttribUser::auto_update_cubit_attrib( child_list );
14478   }
14479 }
14480 
14481 void GeometryModifyTool::propagate_merge_tolerance(DLIList<Body*> &body_list)
14482 {
14483   // For each body
14484   //  get a list of all children that have a local tolerance
14485   //  iterate over that list
14486   //    for each entity, get a list of all of its children
14487   //    if the parent's tolerance is > child tolerance && the child isn't in the owner_set list
14488   //     then set the child's tolerance to the parent's tolerance
14489 
14490   DLIList<RefEntity*> owner_set_tolerance_list;
14491   DLIList<RefEntity*> entity_list;
14492 
14493   double parent_tolerance = 0.0;
14494 
14495   for (int i=body_list.size(); i--;)
14496   {
14497     Body* local_body = body_list.get_and_step();
14498 
14499     // First, get all the children for this body. Save those that already have
14500     // a local tolerance set
14501     local_body->get_all_child_ref_entities(entity_list);
14502     for (int i = entity_list.size(); i--;)
14503     {
14504       RefEntity* local_entity = entity_list.get_and_step();
14505       if (local_entity->local_tolerance() > 0.0)
14506         owner_set_tolerance_list.append(local_entity);
14507     }
14508 
14509     // for each entity in the owner_set list, get all of its children
14510     for (int i = owner_set_tolerance_list.size(); i--;)
14511     {
14512       RefEntity* local_entity = owner_set_tolerance_list.get_and_step();
14513       parent_tolerance = local_entity->local_tolerance();
14514 
14515       entity_list.clean_out();
14516       local_entity->get_all_child_ref_entities(entity_list);
14517       for (int j = entity_list.size(); j--;)
14518       {
14519         RefEntity* child_entity = entity_list.get_and_step();
14520         if (!owner_set_tolerance_list.is_in_list(child_entity))
14521         {
14522           if (child_entity->local_tolerance() < parent_tolerance)
14523             child_entity->local_tolerance(parent_tolerance);
14524         }
14525       }
14526     }
14527   }
14528 }
14529 
14530 CubitStatus GeometryModifyTool::remove_topology( DLIList<RefEdge*> &ref_edge_list,
14531                                                   DLIList<RefFace*> &ref_face_list,
14532                                                   double backoff_distance,
14533                                                   double small_curve_size,
14534                                                   DLIList<Body*> &new_body_list,
14535                                                   CubitBoolean propagate,
14536                                                   CubitBoolean preview)
14537 {
14538   int i, j;
14539   CubitStatus ret = CUBIT_SUCCESS;
14540   DLIList<Surface*> surf_list;
14541   DLIList<Curve*> curve_list;
14542   DLIList<Body*> old_body_list;
14543   GeometryModifyEngine *gme_ptr1=NULL, *gme_ptr2=NULL, *gme_ptr=NULL;
14544   Body *b1=NULL, *b2=NULL, *b=NULL;
14545 
14546   if(ref_edge_list.size())
14547     b1 = ref_edge_list.get()->body();
14548   if(ref_face_list.size())
14549     b2 = ref_face_list.get()->body();
14550 
14551   if(b1 && b2)
14552   {
14553     if(b1 == b2)
14554       b = b1;
14555   }
14556   else if(b1)
14557     b = b1;
14558   else if(b2)
14559     b = b2;
14560 
14561   if(b)
14562     old_body_list.append(b);
14563   else
14564   {
14565     PRINT_ERROR("Failed to find an owning body for the topology being removed.\n");
14566     ret = CUBIT_FAILURE;
14567   }
14568 
14569   if(ret == CUBIT_SUCCESS)
14570   {
14571     if (!okay_to_modify( old_body_list, "REMOVE_TOPOLOGY" ))
14572       ret = CUBIT_FAILURE;
14573     else
14574     {
14575       // Remove any edges from the list that aren't small enough.
14576       DLIList<RefEdge*> edges_to_remove;
14577       for(i=ref_edge_list.size(); i--;)
14578       {
14579         RefEdge* re = ref_edge_list.get_and_step();
14580         if(re->get_arc_length() > small_curve_size)
14581         {
14582           edges_to_remove.append(re);
14583           PRINT_INFO("Ignoring curve %d as it is not a small curve based on the input. "
14584             "Try a larger small_curve_size value.\n", re->id());
14585         }
14586       }
14587       ref_edge_list -= edges_to_remove;
14588 
14589       // Remove any faces from the list that don't have at least one small edge.
14590       DLIList<RefFace*> faces_to_remove;
14591       for(i=ref_face_list.size(); i--;)
14592       {
14593         DLIList<RefEdge*> face_edges;
14594         RefFace* rf = ref_face_list.get_and_step();
14595         rf->ref_edges(face_edges);
14596         int face_ok = 0;
14597         for(j=face_edges.size(); j && !face_ok; j--)
14598         {
14599           RefEdge* cur_edge = face_edges.get_and_step();
14600           if(cur_edge->get_arc_length() <= small_curve_size)
14601             face_ok = 1;
14602         }
14603         if(!face_ok)
14604         {
14605           faces_to_remove.append(rf);
14606           PRINT_INFO("Ignoring surface %d as it does not have at least one small curve in it based on the input. "
14607             "Try a larger small_curve_size value.\n", rf->id());
14608         }
14609       }
14610       ref_face_list -= faces_to_remove;
14611     }
14612 
14613     if(ref_face_list.size() > 0 || ref_edge_list.size() > 0)
14614     {
14615       // If told to do so propagate the topology to be removed to include
14616       // other narrow surfaces and small edges.
14617       if(propagate)
14618       {
14619         // Get all of the small edges into a single list.
14620         DLIList<RefEdge*> small_edges = ref_edge_list;
14621         for(i=ref_face_list.size(); i--;)
14622         {
14623           RefFace *face = ref_face_list.get_and_step();
14624           DLIList<RefEdge*> edges;
14625           face->ref_edges(edges);
14626           for(j=edges.size(); j--;)
14627           {
14628             RefEdge *edge = edges.get_and_step();
14629             if(edge->get_arc_length() < small_curve_size)
14630               small_edges.append(edge);
14631           }
14632         }
14633         small_edges.uniquify_ordered();
14634 
14635         DLIList<RefFace*> processed_faces;
14636         DLIList<RefEdge*> copy_of_small_edges = small_edges;
14637         DLIList<RefFace*> narrow_faces;
14638 
14639         DLIList<RefFace*> all_faces;
14640         DLIList<RefEdge*> all_edges;
14641 
14642         // Set all of the marked flags to 0.
14643         b->ref_faces(all_faces);
14644         for(i=all_faces.size(); i>0; i--)
14645           all_faces.get_and_step()->marked(0);
14646 
14647         b->ref_edges(all_edges);
14648         for(i=all_edges.size(); i>0; i--)
14649           all_edges.get_and_step()->marked(0);
14650 
14651         // Mark of >0 means it has been processed.
14652         // Mark of 2 means it is a small edge.
14653         for(i=small_edges.size(); i>0; i--)
14654           small_edges.get_and_step()->marked(2);
14655 
14656         // First look at all of the edges connected to small edges
14657         // to see if there are other small edges.
14658         while(copy_of_small_edges.size())
14659         {
14660           RefEdge *edge = copy_of_small_edges.extract();
14661           propagate_from_small_edge(edge, small_edges,
14662                   narrow_faces, processed_faces, small_curve_size);
14663         }
14664 
14665         ref_face_list += narrow_faces;
14666         ref_face_list.uniquify_ordered();
14667 
14668         ref_edge_list = small_edges;
14669         ref_edge_list.uniquify_ordered();
14670         // Append to face list here so we don't lose the ones that were passed in.
14671       }
14672     }
14673     else
14674     {
14675       PRINT_WARNING("No entities to remove.\n");
14676       ret = CUBIT_FAILURE;
14677     }
14678   }
14679 
14680   if(ret == CUBIT_SUCCESS)
14681   {
14682     if(ref_edge_list.size())
14683     {
14684       for(i=ref_edge_list.size(); i--;)
14685       {
14686         RefEdge *re = ref_edge_list.get_and_step();
14687         Curve *cur = re->get_curve_ptr();
14688         DLIList<TopologyBridge*> tmp_curve_list;
14689         GeometryQueryEngine *gqe = cur->get_geometry_query_engine();
14690         gqe->get_underlying_curves(cur, tmp_curve_list);
14691         if(tmp_curve_list.size() == 0)
14692           tmp_curve_list.append(cur);
14693         for(int p=tmp_curve_list.size(); p--;)
14694         {
14695           Curve *crv = dynamic_cast<Curve*>(tmp_curve_list.get_and_step());
14696           if(!gme_ptr1)
14697             gme_ptr1 = get_engine(crv);
14698           curve_list.append(crv);
14699         }
14700       }
14701     }
14702     if(ref_face_list.size())
14703     {
14704       for(i=ref_face_list.size(); i--;)
14705       {
14706         RefFace *rf = ref_face_list.get_and_step();
14707         Surface *sur = rf->get_surface_ptr();
14708         DLIList<TopologyBridge*> tmp_surf_list;
14709         GeometryQueryEngine *gqe = sur->get_geometry_query_engine();
14710         gqe->get_underlying_surfaces(sur, tmp_surf_list);
14711         if(tmp_surf_list.size() == 0)
14712           tmp_surf_list.append(sur);
14713         for(int p=tmp_surf_list.size(); p--;)
14714         {
14715           Surface *srf = dynamic_cast<Surface*>(tmp_surf_list.get_and_step());
14716           if(!gme_ptr2)
14717             gme_ptr2 = get_engine(srf);
14718           surf_list.append(srf);
14719         }
14720       }
14721     }
14722     if(gme_ptr1 && gme_ptr2)
14723     {
14724       if(gme_ptr1 == gme_ptr2)
14725         gme_ptr = gme_ptr1;
14726     }
14727     else if(gme_ptr1)
14728       gme_ptr = gme_ptr1;
14729     else if(gme_ptr2)
14730       gme_ptr = gme_ptr2;
14731 
14732     if(!gme_ptr)
14733     {
14734       PRINT_ERROR("Failed to find a geometry modify engine.\n");
14735       ret = CUBIT_FAILURE;
14736     }
14737   }
14738 
14739   if(ret == CUBIT_SUCCESS)
14740   {
14741     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
14742     {
14743       DLIList<Body*> bodies;
14744       int i;
14745       for( i=ref_face_list.size(); i--; )
14746       {
14747         RefFace* ref_face = ref_face_list.get_and_step();
14748         bodies.append( ref_face->body() );
14749       }
14750       for( i=ref_edge_list.size(); i--; )
14751       {
14752         RefEdge* ref_edge = ref_edge_list.get_and_step();
14753         bodies.append( ref_edge->body() );
14754       }
14755       bodies.uniquify_ordered();
14756       CubitUndo::save_state_with_cubit_file( bodies );
14757     }
14758 
14759     if(preview == CUBIT_FALSE)
14760       do_attribute_setup();
14761 
14762     DLIList<BodySM*> body_sm_list(old_body_list.size());
14763     GeometryModifyEngine* gme = common_modify_engine(old_body_list, body_sm_list);
14764 
14765     if(preview == CUBIT_FALSE)
14766       push_attributes_before_modify(body_sm_list);
14767 
14768     DLIList<BodySM*> new_bodysm_list;
14769     if(gme_ptr->remove_topology(curve_list, surf_list, backoff_distance, small_curve_size,
14770         new_bodysm_list, preview) == CUBIT_FAILURE)
14771     {
14772       if( CubitUndo::get_undo_enabled() )
14773         CubitUndo::remove_last_undo();
14774 
14775       if(!preview)
14776         remove_pushed_attributes(new_bodysm_list, old_body_list);
14777 
14778       ret = CUBIT_FAILURE;
14779     }
14780     else
14781     {
14782       if( preview == CUBIT_FALSE )
14783       {
14784         restore_vg_after_modify(new_bodysm_list, old_body_list, gme);
14785         remove_pushed_attributes(new_bodysm_list, old_body_list);
14786 
14787         // Update DAG
14788         ret = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
14789 
14790         if( CubitUndo::get_undo_enabled() )
14791         {
14792           if( ret == CUBIT_FAILURE)
14793             CubitUndo::remove_last_undo();
14794           else
14795             CubitUndo::note_result_bodies( new_body_list );
14796         }
14797       }
14798     }
14799 
14800     if(preview == CUBIT_FALSE)
14801       do_attribute_cleanup();
14802   }
14803 
14804   return ret;
14805 }
14806 
14807 //=============================================================================
14808 // Description: Chamfer vertices on solid or sheet bodies.  On a solid body
14809 //              there can be up to 3 offsets; on a sheet body up to 2 offsets.
14810 //              The offsets are in the direction of the supplied edges.  If
14811 //              multiple vertices are supplied, only one offset value is
14812 //              allowed and the edges are not used.
14813 // Author     : Steve Storm
14814 // Date       : 03/25/05
14815 //=============================================================================
14816 CubitStatus
14817 GeometryModifyTool::tweak_chamfer( DLIList<RefVertex*> &ref_vertex_list,
14818                                    double offset1,
14819                                    DLIList<Body*> &new_body_list,
14820                                    RefEdge *edge1,
14821                                    double offset2,
14822                                    RefEdge *edge2,
14823                                    double offset3,
14824                                    RefEdge *edge3,
14825                                    CubitBoolean keep_old_body,
14826                                    CubitBoolean preview )
14827 {
14828   if( offset1 <= 0.0 )
14829   {
14830     PRINT_ERROR( "Chamfer radius not specified.\n" );
14831     return CUBIT_FAILURE;
14832   }
14833 
14834   DLIList<TBPoint*> point_list(ref_vertex_list.size());
14835   DLIList<Body*> old_body_list;
14836   GeometryModifyEngine* gme_ptr;
14837 
14838   gme_ptr = tweak_setup( ref_vertex_list, "Chamfering", old_body_list, point_list, CUBIT_TRUE );
14839   if( !gme_ptr )
14840     return CUBIT_FAILURE;
14841 
14842   RefVertex *ref_vertex_ptr = ref_vertex_list.get();
14843   if( ref_vertex_list.size() == 1 && (edge1 || edge2 || edge3) )
14844   {
14845     // Make sure input edges are attached to the input vertex
14846     DLIList<RefEdge*> ref_edge_list;
14847     ref_vertex_ptr->ref_edges( ref_edge_list );
14848 
14849     if( edge1 && !ref_edge_list.is_in_list( edge1 ) )
14850     {
14851       PRINT_ERROR( "Specified curve %d not attached to vertex %d\n", edge1->id(),
14852         ref_vertex_ptr->id() );
14853       return CUBIT_FAILURE;
14854     }
14855 
14856     if( edge2 && !ref_edge_list.is_in_list( edge2 ) )
14857     {
14858       PRINT_ERROR( "Specified curve %d not attached to vertex %d\n", edge1->id(),
14859         ref_vertex_ptr->id() );
14860       return CUBIT_FAILURE;
14861     }
14862 
14863     if( edge3 && !ref_edge_list.is_in_list( edge3 ) )
14864     {
14865       PRINT_ERROR( "Specified curve %d not attached to vertex %d\n", edge1->id(),
14866         ref_vertex_ptr->id() );
14867       return CUBIT_FAILURE;
14868     }
14869 
14870     // Make sure offsets supplied
14871     if( edge1 && offset1 < 0.0 )
14872     {
14873       PRINT_ERROR( "Offset for curve %d specified incorrectly.\n", edge1->id() );
14874       return CUBIT_FAILURE;
14875     }
14876 
14877     if( edge2 && offset2 < 0.0 )
14878     {
14879       PRINT_ERROR( "Offset for curve %d specified incorrectly.\n", edge2->id() );
14880       return CUBIT_FAILURE;
14881     }
14882 
14883     if( edge3 && offset3 < 0.0 )
14884     {
14885       PRINT_ERROR( "Offset for curve %d specified incorrectly.\n", edge3->id() );
14886       return CUBIT_FAILURE;
14887     }
14888   }
14889 
14890   if( point_list.size() > 1 && offset2 > 0.0 )
14891   {
14892     PRINT_ERROR( "Cannot supply multiple radii when chamfering multiple vertices.\n" );
14893     return CUBIT_FAILURE;
14894   }
14895 
14896   Curve *curve1 = NULL;
14897   Curve *curve2 = NULL;
14898   Curve *curve3 = NULL;
14899 
14900   if( edge1 )
14901   {
14902     TopologyBridge* bridge = 0;
14903     GeometryModifyEngine* edge_gme = get_engine(edge1, &bridge);
14904     if( gme_ptr != edge_gme )
14905     {
14906       PRINT_ERROR( "Specified curve %d must belong to same geometry engine as vertex %d.\n",
14907         edge1->id(), ref_vertex_ptr->id()  );
14908       return CUBIT_FAILURE;
14909     }
14910     curve1 = dynamic_cast<Curve*>(bridge);
14911   }
14912 
14913   if( edge2 )
14914   {
14915     TopologyBridge* bridge = 0;
14916     GeometryModifyEngine* edge_gme = get_engine(edge2, &bridge);
14917     if( gme_ptr != edge_gme )
14918     {
14919       PRINT_ERROR( "Specified curve %d must belong to same geometry engine as vertex %d.\n",
14920         edge2->id(), ref_vertex_ptr->id()  );
14921       return CUBIT_FAILURE;
14922     }
14923     curve2 = dynamic_cast<Curve*>(bridge);
14924   }
14925 
14926   if( edge3 )
14927   {
14928     TopologyBridge* bridge = 0;
14929     GeometryModifyEngine* edge_gme = get_engine(edge3, &bridge);
14930     if( gme_ptr != edge_gme )
14931     {
14932       PRINT_ERROR( "Specified curve %d must belong to same geometry engine as vertex %d.\n",
14933         edge3->id(), ref_vertex_ptr->id()  );
14934       return CUBIT_FAILURE;
14935     }
14936     curve3 = dynamic_cast<Curve*>(bridge);
14937   }
14938 
14939   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
14940   {
14941     if( keep_old_body )
14942       CubitUndo::save_state();
14943     else
14944       CubitUndo::save_state_with_cubit_file( ref_vertex_list );
14945   }
14946 
14947   DLIList<BodySM*> body_sms;
14948   for(int i=old_body_list.size(); i--;)
14949   {
14950     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
14951     if(bsm)
14952       body_sms.append_unique(bsm);
14953   }
14954   
14955   if(!preview)
14956   {
14957     do_attribute_setup();
14958     push_attributes_before_modify(body_sms);
14959   }
14960 
14961   // Do chamfering
14962   DLIList<BodySM*> new_bodysm_list;
14963   CubitStatus stat = gme_ptr->tweak_chamfer( point_list, offset1, new_bodysm_list, curve1, offset2,
14964                                             curve2, offset3, curve3, keep_old_body, preview );
14965   
14966   if(stat == CUBIT_FAILURE)
14967   {
14968     if( CubitUndo::get_undo_enabled() )
14969       CubitUndo::remove_last_undo();
14970     if(!preview)
14971     {
14972       remove_pushed_attributes(new_bodysm_list, old_body_list);
14973       do_attribute_cleanup();
14974     }
14975     return stat;
14976   }
14977   else
14978   {
14979     if(!preview)
14980     {
14981       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
14982       remove_pushed_attributes(new_bodysm_list, old_body_list);
14983     }
14984   }
14985   
14986   if( preview == CUBIT_FALSE )
14987   {
14988     // Update DAG
14989     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
14990 
14991     if( CubitUndo::get_undo_enabled()  )
14992     {
14993       if( stat == CUBIT_FAILURE )
14994         CubitUndo::remove_last_undo();
14995       else if( keep_old_body )
14996         CubitUndo::note_result_bodies( new_body_list );
14997     }
14998     do_attribute_cleanup();
14999     return stat;
15000   }
15001 
15002   return CUBIT_SUCCESS;
15003 }
15004 
15005 //=============================================================================
15006 // Description: Create a round fillet (or blend) at the given curves on solid
15007 //              or sheet bodies.
15008 // Author     : Steve Storm
15009 // Date       : 03/25/05
15010 //=============================================================================
15011 CubitStatus GeometryModifyTool::tweak_fillet( DLIList<RefEdge*> &ref_edge_list,
15012                                               double radius,
15013                                               DLIList<Body*> &new_body_list,
15014                                               CubitBoolean keep_old_body,
15015                                               CubitBoolean preview )
15016 {
15017   DLIList<Curve*> curve_list(ref_edge_list.size());
15018   DLIList<Body*> old_body_list;
15019   GeometryModifyEngine* gme_ptr;
15020 
15021   gme_ptr = tweak_setup( ref_edge_list, "Filleting", old_body_list, curve_list, CUBIT_TRUE );
15022   if( !gme_ptr )
15023     return CUBIT_FAILURE;
15024 
15025   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15026   {
15027     if( keep_old_body )
15028       CubitUndo::save_state();
15029     else
15030       CubitUndo::save_state_with_cubit_file( ref_edge_list );
15031   }
15032 
15033   DLIList<BodySM*> body_sms;
15034   for(int i=old_body_list.size(); i--;)
15035   {
15036     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
15037     if(bsm)
15038       body_sms.append_unique(bsm);
15039   }
15040   
15041   if(!preview)
15042   {
15043     do_attribute_setup();
15044     push_attributes_before_modify(body_sms);
15045   }
15046 
15047   // Do filleting
15048   DLIList<BodySM*> new_bodysm_list;
15049   CubitStatus stat = gme_ptr->tweak_fillet(curve_list, radius, new_bodysm_list, keep_old_body,
15050                                            preview );
15051   
15052   if(stat == CUBIT_FAILURE )
15053   {
15054     if(!preview)
15055     {
15056       if( CubitUndo::get_undo_enabled() )
15057         CubitUndo::remove_last_undo();
15058       remove_pushed_attributes(new_bodysm_list, old_body_list);
15059       do_attribute_cleanup();
15060     }
15061     return stat;
15062   }
15063   else
15064   {
15065     if(!preview)
15066     {
15067       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
15068       remove_pushed_attributes(new_bodysm_list, old_body_list);
15069     }
15070   }
15071   
15072   if( preview == CUBIT_FALSE )
15073   {
15074     // Update DAG
15075     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15076 
15077     if( CubitUndo::get_undo_enabled() )
15078     {
15079       if( stat == CUBIT_FAILURE )
15080         CubitUndo::remove_last_undo();
15081       else if( keep_old_body )
15082         CubitUndo::note_result_bodies( new_body_list );
15083     }
15084     do_attribute_cleanup();
15085 
15086     return stat;
15087   }
15088   return CUBIT_SUCCESS;
15089 }
15090 
15091 //=============================================================================
15092 // Description: Create a round fillet (or blend) at the given curves on a solid
15093 //              or sheet body.  The fillet has a variable radius from the start
15094 //              to the end of the curve.
15095 // Author     : Steve Storm
15096 // Date       : 03/25/05
15097 //=============================================================================
15098 CubitStatus GeometryModifyTool::tweak_fillet( RefEdge *ref_edge_ptr,
15099                                               double start_radius,
15100                                               double end_radius,
15101                                               Body *&new_body_ptr,
15102                                               CubitBoolean keep_old_body,
15103                                               CubitBoolean preview )
15104 {
15105   DLIList<Curve*> curve_list(1);
15106   DLIList<Body*> old_body_list;
15107   GeometryModifyEngine* gme_ptr;
15108 
15109   DLIList<RefEdge*> ref_edge_list(1);
15110   ref_edge_list.append( ref_edge_ptr );
15111 
15112   gme_ptr = tweak_setup( ref_edge_list, "Filleting", old_body_list, curve_list, CUBIT_TRUE );
15113   if( !gme_ptr )
15114     return CUBIT_FAILURE;
15115 
15116   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15117   {
15118     if( keep_old_body )
15119       CubitUndo::save_state();
15120     else
15121     {
15122       DLIList<RefEdge*> edges(1);
15123       edges.append( ref_edge_ptr );
15124       CubitUndo::save_state_with_cubit_file( edges );
15125     }
15126   }
15127   
15128   DLIList<BodySM*> body_sms;
15129   for(int i=old_body_list.size(); i--;)
15130   {
15131     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
15132     if(bsm)
15133       body_sms.append_unique(bsm);
15134   }
15135   
15136   if(!preview)
15137   {
15138     do_attribute_setup();
15139     push_attributes_before_modify(body_sms);
15140   }
15141 
15142   // Do filleting
15143   BodySM *new_bodysm_ptr;
15144   Curve *curve_ptr = curve_list.get();
15145   CubitStatus stat = gme_ptr->tweak_fillet( curve_ptr, start_radius,
15146                                             end_radius, new_bodysm_ptr,
15147                                             keep_old_body, preview );
15148 
15149   if( CubitUndo::get_undo_enabled() )
15150     if( stat == CUBIT_FAILURE)
15151       CubitUndo::remove_last_undo();
15152 
15153   DLIList<BodySM*> new_bodysm_list;
15154   new_bodysm_list.append(new_bodysm_ptr);
15155   if( stat == CUBIT_FAILURE )
15156   {
15157     remove_pushed_attributes(new_bodysm_list, old_body_list);
15158     do_attribute_cleanup();
15159     return stat;
15160   }
15161   else
15162   {
15163     restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
15164     remove_pushed_attributes(new_bodysm_list, old_body_list);
15165   }
15166 
15167   if( preview == CUBIT_FALSE )
15168   {
15169     // Update DAG
15170     DLIList<BodySM*> new_bodysm_list;
15171     new_bodysm_list.append( new_bodysm_ptr );
15172     DLIList<Body*> new_body_list;
15173     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15174 
15175     if( CubitUndo::get_undo_enabled()  )
15176     {
15177       if( stat == CUBIT_FAILURE )
15178         CubitUndo::remove_last_undo();
15179       else if( keep_old_body )
15180         CubitUndo::note_result_bodies( new_body_list );
15181     }
15182 
15183     new_body_ptr = new_body_list.get();
15184 
15185     do_attribute_cleanup();
15186 
15187     return stat;
15188   }
15189   return CUBIT_SUCCESS;
15190 }
15191 
15192 //=============================================================================
15193 // Description: Create a round fillet (or blend) at the given vertices on sheet
15194 //              bodies.
15195 // Author     : Steve Storm
15196 // Date       : 03/25/05
15197 //=============================================================================
15198 CubitStatus
15199 GeometryModifyTool::tweak_fillet( DLIList<RefVertex*> &ref_vertex_list,
15200                                   double radius,
15201                                   DLIList<Body*> &new_body_list,
15202                                   CubitBoolean keep_old_body,
15203                                   CubitBoolean preview )
15204 {
15205   DLIList<TBPoint*> point_list(ref_vertex_list.size());
15206   DLIList<Body*> old_body_list;
15207   GeometryModifyEngine* gme_ptr;
15208 
15209   gme_ptr = tweak_setup( ref_vertex_list, "Filleting", old_body_list, point_list, CUBIT_TRUE );
15210   if( !gme_ptr )
15211     return CUBIT_FAILURE;
15212 
15213   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15214   {
15215     if( keep_old_body )
15216       CubitUndo::save_state();
15217     else
15218       CubitUndo::save_state_with_cubit_file( ref_vertex_list );
15219   }
15220   
15221   DLIList<BodySM*> body_sms;
15222   for(int i=old_body_list.size(); i--;)
15223   {
15224     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
15225     if(bsm)
15226       body_sms.append_unique(bsm);
15227   }
15228   
15229   if(!preview)
15230   {
15231     do_attribute_setup();
15232     push_attributes_before_modify(body_sms);
15233   }
15234 
15235   // Do filleting
15236   DLIList<BodySM*> new_bodysm_list;
15237   CubitStatus stat = gme_ptr->tweak_fillet( point_list, radius,
15238                                             new_bodysm_list, keep_old_body,
15239                                             preview );
15240   if(stat == CUBIT_FAILURE )
15241   {
15242     if(!preview)
15243     {
15244       if( CubitUndo::get_undo_enabled() )
15245         CubitUndo::remove_last_undo();
15246       remove_pushed_attributes(new_bodysm_list, old_body_list);
15247       do_attribute_cleanup();
15248     }
15249     return stat;
15250   }
15251   else
15252   {
15253     if(!preview)
15254     {
15255       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
15256       remove_pushed_attributes(new_bodysm_list, old_body_list);
15257     }
15258   }
15259 
15260   if( preview == CUBIT_FALSE )
15261   {
15262     // Update DAG
15263     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15264 
15265     if( CubitUndo::get_undo_enabled()  )
15266     {
15267       if( stat == CUBIT_FAILURE )
15268         CubitUndo::remove_last_undo();
15269       else if( keep_old_body )
15270         CubitUndo::note_result_bodies( new_body_list );
15271     }
15272     
15273     do_attribute_cleanup();
15274 
15275     return stat;
15276   }
15277   return CUBIT_SUCCESS;
15278 }
15279 
15280 //=============================================================================
15281 // Description: Tweak specified faces of a volume or volumes along a vector.
15282 // Author     : Steve Storm
15283 // Date       : 03/25/05
15284 //=============================================================================
15285 CubitStatus GeometryModifyTool::tweak_move( DLIList<RefFace*>& ref_face_list,
15286                                             const CubitVector &delta,
15287                                             DLIList<Body*>& new_body_list,
15288                                             CubitBoolean keep_old_body,
15289                                             CubitBoolean preview )
15290 {
15291   DLIList<Surface*> surface_list(ref_face_list.size());
15292   DLIList<Body*> old_body_list;
15293   GeometryModifyEngine* gme_ptr;
15294 
15295   gme_ptr = tweak_setup( ref_face_list, "Moving", old_body_list, surface_list, CUBIT_TRUE );
15296   if (!gme_ptr)
15297     return CUBIT_FAILURE;
15298 
15299   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15300   {
15301     if( keep_old_body )
15302       CubitUndo::save_state();
15303     else
15304     {
15305       int i;
15306       DLIList<RefEdge*> ref_edges;
15307       for( i=ref_face_list.size(); i--; )
15308         ref_face_list.get_and_step()->ref_edges( ref_edges );
15309       ref_edges.uniquify_unordered();
15310       CubitUndo::save_state_with_cubit_file( ref_edges );
15311     }
15312   }
15313 
15314   int i;
15315   DLIList<BodySM*> body_sms;
15316   for(i=old_body_list.size(); i--;)
15317   {
15318     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
15319     if(bsm)
15320       body_sms.append_unique(bsm);
15321   }
15322 
15323   if(!preview)
15324   {
15325     do_attribute_setup();
15326     push_attributes_before_modify(body_sms);
15327   }
15328 
15329   // Do move
15330   DLIList<BodySM*> new_bodysm_list;
15331   CubitStatus stat = gme_ptr->tweak_move( surface_list, delta,
15332                                           new_bodysm_list, keep_old_body,
15333                                           preview );
15334 
15335 
15336   if( CubitUndo::get_undo_enabled() )
15337     if( stat == CUBIT_FAILURE)
15338       CubitUndo::remove_last_undo();
15339 
15340   if( stat == CUBIT_FAILURE )
15341   {
15342     if(!preview)
15343     {
15344       remove_pushed_attributes(new_bodysm_list, old_body_list);
15345       do_attribute_cleanup();
15346     }
15347     return stat;
15348   }
15349   else
15350   {
15351     if(!preview)
15352     {
15353       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
15354       remove_pushed_attributes(new_bodysm_list, old_body_list);
15355     }
15356   }
15357 
15358   // loop body sm list and find surfaces that need updating.
15359   // this is to account for some cases where the topology doesn't change, but the geometry does.
15360   DLIList<RefEntity*> entities_to_update;
15361   for(i=0; i<new_bodysm_list.size(); i++)
15362   {
15363     BodySM* bodysm = new_bodysm_list.get_and_step();
15364     DLIList<Surface*> surfs;
15365     bodysm->surfaces(surfs);
15366     int j;
15367     // find a surface that is also found in our input list
15368     for(j=0; j<surfs.size(); j++, surfs.step())
15369     {
15370       BridgeManager* man = surfs.get()->bridge_manager();
15371       if(man)
15372       {
15373         RefFace* ref_face = CAST_TO(man->topology_entity(), RefFace);
15374         if(ref_face && ref_face_list.is_in_list(ref_face))
15375         {
15376           // get neighbors
15377           DLIList<TBPoint*> neighbor_points;
15378           surfs.get()->points(neighbor_points);
15379           DLIList<Curve*> neighbor_curves;
15380           DLIList<Surface*> neighbor_surfaces;
15381           DLIList<TopologyBridge*> neighbors;
15382           DLIList<TopologyBridge*> tmp;
15383           int k;
15384           for(k=0; k<neighbor_points.size(); k++)
15385             neighbor_points.get_and_step()->surfaces(neighbor_surfaces);
15386           for(k=0; k<neighbor_points.size(); k++)
15387             neighbor_points.get_and_step()->curves(neighbor_curves);
15388 
15389           CAST_LIST_TO_PARENT(neighbor_points, tmp);
15390           neighbors += tmp;
15391           neighbor_curves.uniquify_ordered();
15392           CAST_LIST_TO_PARENT(neighbor_curves, tmp);
15393           neighbors += tmp;
15394           neighbor_surfaces.uniquify_ordered();
15395           CAST_LIST_TO_PARENT(neighbor_surfaces, tmp);
15396           neighbors += tmp;
15397           neighbors.append(surfs.get()->lump());
15398           neighbors.append(surfs.get()->bodysm());
15399 
15400           for(k=0; k<neighbors.size(); k++)
15401             if(BridgeManager* m = neighbors.get_and_step()->bridge_manager())
15402               if(TopologyEntity* t = m->topology_entity())
15403                 entities_to_update.append(CAST_TO(t, RefEntity));
15404         }
15405       }
15406     }
15407   }
15408 
15409   if( preview == CUBIT_FALSE )
15410   {
15411     // Update DAG
15412     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15413 
15414     if( CubitUndo::get_undo_enabled()  )
15415     {
15416       if( stat == CUBIT_FAILURE )
15417         CubitUndo::remove_last_undo();
15418       else if( keep_old_body )
15419         CubitUndo::note_result_bodies( new_body_list );
15420     }
15421 
15422     // Update graphics
15423     while (entities_to_update.size())
15424       AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
15425 
15426     do_attribute_cleanup();
15427   }
15428 
15429 
15430   //collect all the new faces
15431   DLIList<RefFace*> new_faces;
15432   for( i=new_body_list.size(); i--; )
15433   {
15434     Body *new_body = new_body_list.get_and_step();
15435     DLIList<RefFace*> tmp_faces;
15436     new_body->ref_faces( tmp_faces );
15437     new_faces += tmp_faces;
15438   }
15439 
15440   //unmerge any merged adjacent surfaces or
15441   //merged curves in unmerged adjacent surfaces
15442   DLIList<RefFace*> adjacent_faces_to_unmerge;
15443   DLIList<RefEdge*> adjacent_edges_to_unmerge;
15444   for(i=ref_face_list.size(); i--;)
15445   {
15446     RefFace *tweaked_face = ref_face_list.get_and_step();
15447     if( !new_faces.move_to( tweaked_face ) )
15448       continue;
15449 
15450     //get all the edges of the face you tweaked
15451     DLIList<RefEdge*> tweaked_face_edges;
15452     tweaked_face->ref_edges( tweaked_face_edges );
15453     adjacent_edges_to_unmerge += tweaked_face_edges;
15454 
15455     //get all the adjacent faces to this edge
15456     int j;
15457     for( j=tweaked_face_edges.size(); j--; )
15458     {
15459       RefEdge *tmp_edge = tweaked_face_edges.get_and_step();
15460       DLIList<RefFace*> tmp_faces;
15461       tmp_edge->ref_faces( tmp_faces );
15462       tmp_faces.remove( tweaked_face );
15463       adjacent_faces_to_unmerge += tmp_faces;
15464     }
15465 
15466     //get all edges not in the surface,
15467     //sharing vertices with the surface
15468     DLIList<RefVertex*> ref_vertices;
15469     tweaked_face->ref_vertices( ref_vertices );
15470     for( j=ref_vertices.size(); j--; )
15471     {
15472       RefVertex *tmp_vert = ref_vertices.get_and_step();
15473       DLIList<RefEdge*>  ref_edges;
15474       tmp_vert->ref_edges( ref_edges );
15475 
15476       int k;
15477       for( k=ref_edges.size(); k--; )
15478       {
15479         RefEdge *tmp_edge = ref_edges.get_and_step();
15480         if( !tweaked_face_edges.move_to( tmp_edge ) )
15481           adjacent_edges_to_unmerge.append( tmp_edge );
15482       }
15483     }
15484   }
15485 
15486   //unmerge any adjacent faces
15487   adjacent_faces_to_unmerge.uniquify_unordered();
15488   for( i=adjacent_faces_to_unmerge.size(); i--; )
15489   {
15490     RefFace *ref_face = adjacent_faces_to_unmerge.get_and_step();
15491 
15492     DLIList<TopologyBridge*> bridge_list;
15493     ref_face->bridge_manager()->get_bridge_list(bridge_list);
15494     if (bridge_list.size() > 1)
15495     {
15496       if( MergeTool::instance()->unmerge( ref_face ) )
15497         PRINT_WARNING("Unmerging Surface %d\n", ref_face->id() );
15498     }
15499   }
15500 
15501   //unmerge any adjacent edges
15502   adjacent_edges_to_unmerge.uniquify_unordered();
15503   for( i=adjacent_edges_to_unmerge.size(); i--; )
15504   {
15505     RefEdge *ref_edge = adjacent_edges_to_unmerge.get_and_step();
15506     DLIList<TopologyBridge*> bridge_list;
15507     ref_edge->bridge_manager()->get_bridge_list(bridge_list);
15508     if (bridge_list.size() > 1)
15509     {
15510       if( MergeTool::instance()->unmerge( ref_edge) )
15511         PRINT_WARNING("Unmerging Curve %d\n", ref_edge->id() );
15512     }
15513   }
15514 
15515 
15516   return stat;
15517 }
15518 
15519 //=============================================================================
15520 // Description: Tweak specified curves of a sheet body along a vector.
15521 // Author     : Steve Storm
15522 // Date       : 03/25/05
15523 //=============================================================================
15524 CubitStatus GeometryModifyTool::tweak_move( DLIList<RefEdge*>& ref_edge_list,
15525                                             const CubitVector &delta,
15526                                             DLIList<Body*>& new_body_list,
15527                                             CubitBoolean keep_old_body,
15528                                             CubitBoolean preview )
15529 {
15530   DLIList<Curve*> curve_list(ref_edge_list.size());
15531   DLIList<Body*> old_body_list;
15532   GeometryModifyEngine* gme_ptr;
15533 
15534   gme_ptr = tweak_setup( ref_edge_list, "Moving", old_body_list, curve_list );
15535   if (!gme_ptr)
15536     return CUBIT_FAILURE;
15537 
15538   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15539   {
15540     if( keep_old_body )
15541       CubitUndo::save_state();
15542     else
15543       CubitUndo::save_state_with_cubit_file( ref_edge_list );
15544   }
15545 
15546   // Do move
15547   DLIList<BodySM*> new_bodysm_list;
15548   CubitStatus stat = gme_ptr->tweak_move( curve_list, delta,
15549                                           new_bodysm_list, keep_old_body,
15550                                           preview );
15551 
15552   if( CubitUndo::get_undo_enabled() )
15553     if( stat == CUBIT_FAILURE)
15554       CubitUndo::remove_last_undo();
15555 
15556   if( stat == CUBIT_FAILURE )
15557     return stat;
15558 
15559   if( preview == CUBIT_FALSE )
15560   {
15561     // Update DAG
15562     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15563 
15564     if( CubitUndo::get_undo_enabled()  )
15565     {
15566       if( stat == CUBIT_FAILURE )
15567         CubitUndo::remove_last_undo();
15568       else if( keep_old_body )
15569         CubitUndo::note_result_bodies( new_body_list );
15570     }
15571   }
15572 
15573   // Update graphics
15574   DLIList<Body*> moved_bodies(new_body_list);
15575   moved_bodies.intersect(old_body_list);
15576   while (moved_bodies.size())
15577     moved_bodies.pop()->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
15578 
15579   return stat;
15580 }
15581 
15582 //=============================================================================
15583 // Description: Tweak specified faces of a volume or volumes by offsetting
15584 //              those faces by the offset distance.
15585 // Author     : Steve Storm
15586 // Date       : 03/25/05
15587 //=============================================================================
15588 CubitStatus GeometryModifyTool::tweak_offset( DLIList<RefFace*> &ref_face_list,
15589                                               double offset_distance,
15590                                               DLIList<RefFace*> *add_ref_face_list_ptr,
15591                                               DLIList<double> *add_offset_list_ptr,
15592                                               DLIList<Body*> &new_body_list,
15593                                               CubitBoolean keep_old_body,
15594                                               CubitBoolean preview )
15595 {
15596   DLIList<RefFace*> all_ref_face_list(ref_face_list.size());
15597   all_ref_face_list = ref_face_list;
15598   if( add_ref_face_list_ptr->size() )
15599     all_ref_face_list += *add_ref_face_list_ptr;
15600 
15601   DLIList<Surface*> surface_list(ref_face_list.size());
15602   DLIList<Body*> old_body_list;
15603   GeometryModifyEngine* gme_ptr;
15604 
15605   gme_ptr = tweak_setup( ref_face_list, "Offsetting", old_body_list, surface_list, CUBIT_TRUE );
15606   if (!gme_ptr)
15607     return CUBIT_FAILURE;
15608 
15609   DLIList<Surface*> add_surface_list;
15610   if( add_ref_face_list_ptr && add_ref_face_list_ptr->size() )
15611   {
15612     DLIList<Body*> old_body_list2;
15613     GeometryModifyEngine* gme_ptr2 = tweak_setup( *add_ref_face_list_ptr, "Offsetting",
15614       old_body_list2, add_surface_list, CUBIT_TRUE );
15615     if (!gme_ptr2)
15616       return CUBIT_FAILURE;
15617     if( gme_ptr != gme_ptr2 )
15618     {
15619       PRINT_ERROR("Offsetting surfaces on volumes containing surfaces from different\n"
15620         "       geometry engines is not allowed.\n");
15621       return CUBIT_FAILURE;
15622     }
15623     old_body_list.merge_unique( old_body_list2 );
15624   }
15625 
15626   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15627   {
15628     if( keep_old_body )
15629       CubitUndo::save_state();
15630     else
15631     {
15632       int i;
15633       DLIList<RefEdge*> ref_edges;
15634       for( i=ref_face_list.size(); i--; )
15635         all_ref_face_list.get_and_step()->ref_edges( ref_edges );
15636       ref_edges.uniquify_unordered();
15637       CubitUndo::save_state_with_cubit_file( ref_edges );
15638     }
15639   }
15640 
15641   int i;
15642   if(!preview)
15643   {
15644     DLIList<BodySM*> body_sms;
15645     for(i=old_body_list.size(); i--;)
15646     {
15647       BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
15648       if(bsm)
15649         body_sms.append_unique(bsm);
15650     }
15651 
15652     do_attribute_setup();
15653     push_attributes_before_modify(body_sms);
15654   }
15655 
15656   // Do offset
15657   DLIList<BodySM*> new_bodysm_list;
15658   CubitStatus stat;
15659   if( add_surface_list.size() )
15660     stat = gme_ptr->tweak_offset( surface_list, offset_distance,
15661                                   &add_surface_list, add_offset_list_ptr,
15662                                   new_bodysm_list, keep_old_body, preview );
15663   else
15664     stat = gme_ptr->tweak_offset( surface_list, offset_distance, NULL, NULL,
15665                                   new_bodysm_list, keep_old_body, preview );
15666 
15667   if( CubitUndo::get_undo_enabled() )
15668     if( stat == CUBIT_FAILURE)
15669       CubitUndo::remove_last_undo();
15670 
15671   if( stat == CUBIT_FAILURE )
15672   {
15673     if(!preview)
15674     {
15675       remove_pushed_attributes(new_bodysm_list, old_body_list);
15676       do_attribute_cleanup();
15677     }
15678     return stat;
15679   }
15680   else
15681   {
15682     if(!preview)
15683     {
15684       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
15685       remove_pushed_attributes(new_bodysm_list, old_body_list);
15686     }
15687   }
15688 
15689   // Collect all of the old faces to be compared later with the new faces...DJQ
15690   DLIList<RefFace*> old_faces;
15691   for (i = 0; i < old_body_list.size(); i++)
15692   {
15693       Body *old_body = old_body_list.get_and_step();
15694       DLIList<RefFace*> tmp_faces;
15695       old_body->ref_faces(tmp_faces);
15696       old_faces +=tmp_faces;
15697   }
15698 
15699   if( preview == CUBIT_FALSE )
15700   {
15701     // Update DAG
15702     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15703 
15704     if( CubitUndo::get_undo_enabled()  )
15705     {
15706       if( stat == CUBIT_FAILURE )
15707         CubitUndo::remove_last_undo();
15708       else if( keep_old_body )
15709         CubitUndo::note_result_bodies( new_body_list );
15710     }
15711     do_attribute_cleanup();
15712   }
15713 
15714   //collect all the new faces
15715   DLIList<RefFace*> new_faces;
15716   for( i=new_body_list.size(); i--; )
15717   {
15718     Body *new_body = new_body_list.get_and_step();
15719     DLIList<RefFace*> tmp_faces;
15720     new_body->ref_faces( tmp_faces );
15721     new_faces += tmp_faces;
15722   }
15723 
15724   // Compare the new_faces list with the old_faces list to determine which faces are created
15725   // Add these faces to the all_ref_face_list to check for its neighbors...DJQ
15726   DLIList<RefFace*> difference = new_faces;
15727   difference -= old_faces;
15728   all_ref_face_list += difference;
15729 
15730   // loop body sm list and find surfaces that need updating.
15731   // this is to account for some cases where the topology
15732   //doesn't change, but the geometry does.
15733 
15734   DLIList<RefEntity*> entities_to_update;
15735   for(i=0; i<new_bodysm_list.size(); i++)
15736   {
15737     BodySM* bodysm = new_bodysm_list.get_and_step();
15738     DLIList<Surface*> surfs;
15739     bodysm->surfaces(surfs);
15740     int j;
15741     // find a surface that is also found in our input list
15742     for(j=0; j<surfs.size(); j++, surfs.step())
15743     {
15744       BridgeManager* man = surfs.get()->bridge_manager();
15745       if(man)
15746       {
15747         RefFace* ref_face = CAST_TO(man->topology_entity(), RefFace);
15748         if(ref_face && all_ref_face_list.is_in_list(ref_face))
15749         {
15750           // get neighbors
15751           DLIList<TBPoint*> neighbor_points;
15752           surfs.get()->points(neighbor_points);
15753           DLIList<Curve*> neighbor_curves;
15754           DLIList<Surface*> neighbor_surfaces;
15755           DLIList<TopologyBridge*> neighbors;
15756           DLIList<TopologyBridge*> tmp;
15757           int k;
15758           for(k=0; k<neighbor_points.size(); k++)
15759             neighbor_points.get_and_step()->surfaces(neighbor_surfaces);
15760           for(k=0; k<neighbor_points.size(); k++)
15761             neighbor_points.get_and_step()->curves(neighbor_curves);
15762 
15763           CAST_LIST_TO_PARENT(neighbor_points, tmp);
15764           neighbors += tmp;
15765           neighbor_curves.uniquify_ordered();
15766           CAST_LIST_TO_PARENT(neighbor_curves, tmp);
15767           neighbors += tmp;
15768           neighbor_surfaces.uniquify_ordered();
15769           CAST_LIST_TO_PARENT(neighbor_surfaces, tmp);
15770           neighbors += tmp;
15771           neighbors.append(surfs.get()->lump());
15772           neighbors.append(surfs.get()->bodysm());
15773 
15774           for(k=0; k<neighbors.size(); k++)
15775             if(BridgeManager* m = neighbors.get_and_step()->bridge_manager())
15776               if(TopologyEntity* t = m->topology_entity())
15777                 entities_to_update.append(CAST_TO(t, RefEntity));
15778         }
15779       }
15780     }
15781   }
15782 
15783 
15784   //unmerge any merged adjacent surfaces or
15785   //merged curves in unmerged adjacent surfaces
15786   DLIList<RefFace*> adjacent_faces_to_unmerge;
15787   DLIList<RefEdge*> adjacent_edges_to_unmerge;
15788   for(i=ref_face_list.size(); i--;)
15789   {
15790     RefFace *tweaked_face = ref_face_list.get_and_step();
15791     if( !new_faces.move_to( tweaked_face ) )
15792       continue;
15793 
15794     //get all the edges of the face you tweaked
15795     DLIList<RefEdge*> tweaked_face_edges;
15796     tweaked_face->ref_edges( tweaked_face_edges );
15797     adjacent_edges_to_unmerge += tweaked_face_edges;
15798 
15799     //get all the adjacent faces to this edge
15800     int j;
15801     for( j=tweaked_face_edges.size(); j--; )
15802     {
15803       RefEdge *tmp_edge = tweaked_face_edges.get_and_step();
15804       DLIList<RefFace*> tmp_faces;
15805       tmp_edge->ref_faces( tmp_faces );
15806       tmp_faces.remove( tweaked_face );
15807       adjacent_faces_to_unmerge += tmp_faces;
15808     }
15809 
15810     //get all edges not in the surface,
15811     //sharing vertices with the surface
15812     DLIList<RefVertex*> ref_vertices;
15813     tweaked_face->ref_vertices( ref_vertices );
15814     for( j=ref_vertices.size(); j--; )
15815     {
15816       RefVertex *tmp_vert = ref_vertices.get_and_step();
15817       DLIList<RefEdge*>  ref_edges;
15818       tmp_vert->ref_edges( ref_edges );
15819 
15820       int k;
15821       for( k=ref_edges.size(); k--; )
15822       {
15823         RefEdge *tmp_edge = ref_edges.get_and_step();
15824         if( !tweaked_face_edges.move_to( tmp_edge ) )
15825           adjacent_edges_to_unmerge.append( tmp_edge );
15826       }
15827     }
15828   }
15829 
15830   //unmerge any adjacent faces
15831   adjacent_faces_to_unmerge.uniquify_unordered();
15832   for( i=adjacent_faces_to_unmerge.size(); i--; )
15833   {
15834     RefFace *ref_face = adjacent_faces_to_unmerge.get_and_step();
15835 
15836     DLIList<TopologyBridge*> bridge_list;
15837     ref_face->bridge_manager()->get_bridge_list(bridge_list);
15838     if (bridge_list.size() > 1)
15839     {
15840       if( MergeTool::instance()->unmerge( ref_face ) )
15841         PRINT_WARNING("Unmerging Surface %d\n", ref_face->id() );
15842     }
15843   }
15844 
15845   //unmerge any adjacent edges
15846   adjacent_edges_to_unmerge.uniquify_unordered();
15847   for( i=adjacent_edges_to_unmerge.size(); i--; )
15848   {
15849     RefEdge *ref_edge = adjacent_edges_to_unmerge.get_and_step();
15850     DLIList<TopologyBridge*> bridge_list;
15851     ref_edge->bridge_manager()->get_bridge_list(bridge_list);
15852     if (bridge_list.size() > 1)
15853     {
15854       if( MergeTool::instance()->unmerge( ref_edge) )
15855         PRINT_WARNING("Unmerging Curve %d\n", ref_edge->id() );
15856     }
15857   }
15858 
15859   // Update graphics
15860   while (entities_to_update.size())
15861     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
15862 
15863   return stat;
15864 }
15865 
15866 //=============================================================================
15867 // Description: Tweak specified curves of a sheet body or bodies by offsetting
15868 //              those curves by the offset distance.
15869 // Author     : Steve Storm
15870 // Date       : 03/25/05
15871 //=============================================================================
15872 CubitStatus GeometryModifyTool::tweak_offset( DLIList<RefEdge*> &ref_edge_list,
15873                                               double offset_distance,
15874                                               DLIList<RefEdge*> *add_ref_edge_list_ptr,
15875                                               DLIList<double> *add_offset_list_ptr,
15876                                               DLIList<Body*> &new_body_list,
15877                                               CubitBoolean keep_old_body,
15878                                               CubitBoolean preview )
15879 {
15880   DLIList<RefEdge*> all_ref_edge_list(ref_edge_list.size());
15881   all_ref_edge_list = ref_edge_list;
15882   if( add_ref_edge_list_ptr )
15883     all_ref_edge_list += *add_ref_edge_list_ptr;
15884 
15885   DLIList<Curve*> curve_list(ref_edge_list.size());
15886   DLIList<Body*> old_body_list;
15887   GeometryModifyEngine* gme_ptr;
15888 
15889   gme_ptr = tweak_setup( ref_edge_list, "Offsetting", old_body_list, curve_list );
15890   if (!gme_ptr)
15891     return CUBIT_FAILURE;
15892 
15893   DLIList<Curve*> add_curve_list;
15894   if( add_ref_edge_list_ptr && add_ref_edge_list_ptr->size() )
15895   {
15896     DLIList<Body*> old_body_list2;
15897     GeometryModifyEngine* gme_ptr2 = tweak_setup( *add_ref_edge_list_ptr, "Offsetting",
15898       old_body_list2, add_curve_list );
15899     if (!gme_ptr2)
15900       return CUBIT_FAILURE;
15901     if( gme_ptr != gme_ptr2 )
15902     {
15903       PRINT_ERROR("Offsetting curves on entities containing surfaces from different\n"
15904       "       geometry engines is not allowed.\n");
15905       return CUBIT_FAILURE;
15906     }
15907     old_body_list.merge_unique( old_body_list2 );
15908   }
15909 
15910   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15911   {
15912     if( keep_old_body )
15913       CubitUndo::save_state();
15914     else
15915       CubitUndo::save_state_with_cubit_file( all_ref_edge_list );
15916   }
15917 
15918   // Do offset
15919   DLIList<BodySM*> new_bodysm_list;
15920   CubitStatus stat;
15921   if( add_curve_list.size() )
15922     stat = gme_ptr->tweak_offset( curve_list, offset_distance, &add_curve_list,
15923     add_offset_list_ptr, new_bodysm_list, keep_old_body, preview );
15924   else
15925     stat = gme_ptr->tweak_offset( curve_list, offset_distance, NULL, NULL,
15926     new_bodysm_list, keep_old_body, preview );
15927 
15928   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15929     if( stat == CUBIT_FAILURE)
15930       CubitUndo::remove_last_undo();
15931 
15932   if( stat == CUBIT_FAILURE )
15933     return CUBIT_FAILURE;
15934 
15935   DLIList<RefEntity*> entities_to_update;
15936   if( preview == CUBIT_FALSE )
15937   {
15938     // check for resued entities, they have been moved and we need to notify observers
15939     for(int i=0; i<new_bodysm_list.size(); i++)
15940     {
15941       BodySM* bodysm = new_bodysm_list.get_and_step();
15942       DLIList<TopologyBridge*> to_check;
15943       DLIList<TopologyBridge*> tmp;
15944       DLIList<Surface*> surfs;
15945       bodysm->surfaces(surfs);
15946       DLIList<Curve*> curves;
15947       bodysm->curves(curves);
15948       DLIList<TBPoint*> points;
15949       bodysm->points(points);
15950       to_check.append(bodysm);
15951       to_check.append(bodysm->lump());
15952       CAST_LIST_TO_PARENT(surfs, tmp);
15953       to_check += tmp;
15954       CAST_LIST_TO_PARENT(curves, tmp);
15955       to_check += tmp;
15956       CAST_LIST_TO_PARENT(points, tmp);
15957       to_check += tmp;
15958 
15959       int k;
15960       for(k=0; k<to_check.size(); k++)
15961         if(BridgeManager* m = to_check.get_and_step()->bridge_manager())
15962           if(TopologyEntity* t = m->topology_entity())
15963             entities_to_update.append(CAST_TO(t, RefEntity));
15964     }
15965 
15966     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
15967 
15968     if( CubitUndo::get_undo_enabled()  )
15969     {
15970       if( stat == CUBIT_FAILURE )
15971         CubitUndo::remove_last_undo();
15972       else if( keep_old_body )
15973         CubitUndo::note_result_bodies( new_body_list );
15974     }
15975   }
15976 
15977   // Update graphics
15978   while (entities_to_update.size())
15979     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
15980 
15981   // Update graphics
15982   DLIList<Body*> moved_bodies(new_body_list);
15983   moved_bodies.intersect(old_body_list);
15984   while (moved_bodies.size())
15985     moved_bodies.pop()->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
15986 
15987   return stat;
15988 }
15989 
15990 
15991 CubitStatus GeometryModifyTool::tweak_remove_individually(
15992                                               DLIList<RefFace*> &ref_face_list,
15993                                               DLIList<Body*> &new_body_list,
15994                                               CubitBoolean keep_surface,
15995                                               CubitBoolean keep_old_body,
15996                                               CubitBoolean preview )
15997 {
15998   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
15999   {
16000     if( keep_old_body )
16001       CubitUndo::save_state();
16002     else
16003       CubitUndo::save_state_with_cubit_file( ref_face_list );
16004   }
16005 
16006   // Split things up if individual
16007   //build a surfae to volume map
16008   std::map<RefFace*, RefVolume*> surface_to_volume_map;
16009 
16010   int i;
16011   for (i = ref_face_list.size(); i--; )
16012   {
16013     RefFace *tmp_face = ref_face_list.get_and_step();
16014     RefVolume *tmp_vol = tmp_face->ref_volume();
16015     surface_to_volume_map.insert( std::map<RefFace*, RefVolume*>::value_type( tmp_face, tmp_vol));
16016   }
16017 
16018   DLIList<RefFace*> one_ref_face;
16019   DLIList<Body*> tmp_new_body_list;
16020   CubitStatus total_rv = CUBIT_FAILURE;
16021   bool extend = true;
16022 
16023   // Succeed if any one surface succeeds.
16024   for (i = ref_face_list.size(); i--; )
16025   {
16026     //make sure that the surface to remove is still in the body...
16027     //that it hasn't been removed from a previous tweak operation
16028     RefFace *tmp_face = ref_face_list.get_and_step();
16029     std::map<RefFace*, RefVolume*>::iterator tmp_iter;
16030     tmp_iter = surface_to_volume_map.find( tmp_face );
16031     RefVolume *tmp_vol = tmp_iter->second;
16032     DLIList<RefFace*> ref_face_list;
16033     tmp_vol->ref_faces( ref_face_list );
16034     if( !ref_face_list.move_to( tmp_face ) )
16035       continue;
16036 
16037     one_ref_face.clean_out();
16038     one_ref_face.append( tmp_face );
16039     int id = one_ref_face.get()->id();
16040 
16041     //See if the owning body of the face is a multi-volume body
16042     Body *owning_body = one_ref_face.get()->body();
16043     int number_volumes_before = owning_body->num_ref_volumes();
16044 
16045     tmp_new_body_list.clean_out();
16046 
16047     CubitStatus rv = this->tweak_remove(one_ref_face, tmp_new_body_list,
16048       extend, keep_surface, keep_old_body, preview );
16049     if (rv)
16050     {
16051       total_rv = CUBIT_SUCCESS;
16052       if( !preview )
16053         PRINT_INFO("Successfully removed Surface %d\n\n", id);
16054       else
16055         PRINT_INFO("Successfully removed Surface %d in preview\n\n", id);
16056 
16057       //see if we have a multi-volume body or multiple bodies
16058       //if so, we know the original volume was destroyed, so we
16059       //cannot remove any more surfaces because the check above is
16060       //highly likely to crash
16061       bool volume_destroyed = false;
16062       int number_volumes_after = tmp_new_body_list.get()->num_ref_volumes();
16063       if( number_volumes_after > number_volumes_before  )
16064         volume_destroyed = true;
16065 
16066       new_body_list += tmp_new_body_list;
16067 
16068       if( volume_destroyed == true )
16069       {
16070         PRINT_WARNING("Unable to remove more surfaces because multiple bodies\n"
16071                       "       have been produced from removing surfaces individually\n" );
16072         if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16073         {
16074           if( total_rv == CUBIT_FAILURE )  //didn't remove any surfaces
16075             CubitUndo::remove_last_undo();
16076           else
16077             CubitUndo::note_result_bodies( new_body_list );
16078         }
16079 
16080         return total_rv;
16081       }
16082     }
16083     else
16084     {
16085       if( !preview )
16086         PRINT_INFO("Unable to remove Surface %d\n\n", id);
16087       else
16088         PRINT_INFO("Unable to remove Surface %d in preview\n\n", id);
16089     }
16090   }
16091 
16092   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16093   {
16094     if( total_rv == CUBIT_FAILURE)
16095       CubitUndo::remove_last_undo();
16096     else if( keep_old_body || keep_surface )
16097       CubitUndo::note_result_bodies( new_body_list );
16098   }
16099 
16100   return total_rv;
16101 }
16102 
16103 
16104 //=============================================================================
16105 // Description: Function to remove surfaces from a body and then extend the
16106 //              remaining surfaces to fill the gap or hole.
16107 // Author     : Steve Storm
16108 // Date       : 03/25/05
16109 //=============================================================================
16110 CubitStatus GeometryModifyTool::tweak_remove_together(
16111                                               DLIList<RefFace*> &ref_face_list,
16112                                               DLIList<Body*> &new_body_list,
16113                                               CubitBoolean extend_adjoining,
16114                                               CubitBoolean keep_surface,
16115                                               CubitBoolean keep_old_body,
16116                                               CubitBoolean preview )
16117 {
16118 
16119   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16120   {
16121     if( keep_old_body )
16122       CubitUndo::save_state();
16123     else
16124       CubitUndo::save_state_with_cubit_file( ref_face_list );
16125   }
16126 
16127   CubitStatus stat = tweak_remove( ref_face_list, new_body_list,
16128                                    extend_adjoining, keep_surface,
16129                                    keep_old_body, preview );
16130 
16131   if( stat == CUBIT_FAILURE )
16132   {
16133     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16134       CubitUndo::remove_last_undo();
16135 
16136     return CUBIT_FAILURE;
16137   }
16138 
16139 
16140   if( preview == CUBIT_FALSE )
16141   {
16142     if( CubitUndo::get_undo_enabled()  )
16143     {
16144       if( stat == CUBIT_FAILURE )
16145         CubitUndo::remove_last_undo();
16146       else if( keep_old_body || keep_surface )
16147         CubitUndo::note_result_bodies( new_body_list );
16148     }
16149   }
16150 
16151   return CUBIT_SUCCESS;
16152 }
16153 
16154 //private funcion...should not be called from outside this class
16155 CubitStatus GeometryModifyTool::tweak_remove( DLIList<RefFace*> &ref_face_list,
16156                                               DLIList<Body*> &new_body_list,
16157                                               CubitBoolean extend_adjoining,
16158                                               CubitBoolean keep_surface,
16159                                               CubitBoolean keep_old_body,
16160                                               CubitBoolean preview )
16161 {
16162    DLIList<Surface*> surface_list(ref_face_list.size());
16163    DLIList<Body*> old_body_list;
16164    GeometryModifyEngine* gme_ptr;
16165 
16166    // clear any preview previews
16167    GfxPreview::clear();
16168 
16169    //collect all neighboring surfaces to those in the list
16170    int i,j;
16171    DLIList<RefFace*> neighboring_surfaces;
16172    DLIList<RefEdge*> merged_ref_edges_before;
16173    for( i=ref_face_list.size(); i--; )
16174    {
16175      RefFace *tmp_face = ref_face_list.get_and_step();
16176      DLIList<RefEdge*> ref_edge_list;
16177      tmp_face->ref_edges( ref_edge_list );
16178      for( j=ref_edge_list.size(); j--; )
16179        ref_edge_list.get_and_step()->ref_faces( neighboring_surfaces );
16180 
16181      DLIList<RefVertex*> tmp_verts;
16182      tmp_face->ref_vertices( tmp_verts );
16183      for( j=tmp_verts.size(); j--; )
16184      {
16185        RefVertex *tmp_vert = tmp_verts.get_and_step();
16186        DLIList<RefEdge*> tmp_edges;
16187        tmp_vert->ref_edges( tmp_edges );
16188        int kk;
16189        for( kk=tmp_edges.size(); kk--; )
16190        {
16191          RefEdge *tmp_edge = tmp_edges.get_and_step();
16192          if( tmp_edge->is_merged() )
16193            merged_ref_edges_before.append( tmp_edge);
16194        }
16195      }
16196    }
16197 
16198   //uniquify and add other surfaces
16199   neighboring_surfaces.uniquify_unordered();
16200   neighboring_surfaces += ref_face_list;
16201 
16202    gme_ptr = tweak_setup( ref_face_list, "Removing", old_body_list, surface_list, CUBIT_TRUE );
16203    if (!gme_ptr)
16204      return CUBIT_FAILURE;
16205 
16206    DLIList<Surface*> kept_surface_list;
16207    if( keep_surface )
16208    {
16209      int kk;
16210      for( kk=surface_list.size(); kk--; )
16211      {
16212        Surface *new_surf = gme_ptr->make_Surface( surface_list.get_and_step() );
16213        kept_surface_list.append( new_surf );
16214      }
16215    }
16216 
16217    DLIList<BodySM*> body_sms;
16218    for(i=old_body_list.size(); i--;)
16219    {
16220      BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
16221      if(bsm)
16222        body_sms.append_unique(bsm);
16223    }
16224 
16225    if(!preview)
16226    {
16227     do_attribute_setup();
16228     push_attributes_before_modify(body_sms);
16229    }
16230 
16231    // Do remove
16232    DLIList<BodySM*> new_bodysm_list;
16233    CubitStatus removal_status =
16234        gme_ptr->tweak_remove( surface_list,
16235                               new_bodysm_list,
16236                               extend_adjoining,
16237                               keep_old_body,
16238                               preview );
16239 
16240 
16241    if( removal_status == CUBIT_FAILURE )
16242    {
16243      if(!preview)
16244       remove_pushed_attributes(new_bodysm_list, old_body_list);
16245      if( keep_surface )
16246      {
16247        int kk;
16248        for( kk=kept_surface_list.size(); kk--; )
16249        {
16250          Surface *surf = kept_surface_list.get_and_step();
16251          gme_ptr->get_gqe()->delete_solid_model_entities( surf );
16252        }
16253      }
16254      if(!preview)
16255       do_attribute_cleanup();
16256      return CUBIT_FAILURE;
16257    }
16258    else
16259    {
16260      if(!preview)
16261      {
16262         restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
16263         remove_pushed_attributes(new_bodysm_list, old_body_list);
16264      }
16265    }
16266 
16267   // for each new bodysm, find surfaces that need updating.
16268   // this is to account for some cases where the topology doesn't change, but the geometry does.
16269   DLIList<RefEntity*> entities_to_update;
16270   for(i=0; i<new_bodysm_list.size(); i++)
16271   {
16272     BodySM* bodysm = new_bodysm_list.get_and_step();
16273     DLIList<Surface*> surfs;
16274     bodysm->surfaces(surfs);
16275     int j;
16276     // find a surface that is also found in our input list
16277     for(j=0; j<surfs.size(); j++, surfs.step())
16278     {
16279       BridgeManager* man = surfs.get()->bridge_manager();
16280       if(man)
16281       {
16282         RefFace* ref_face = CAST_TO(man->topology_entity(), RefFace);
16283         if( ref_face && neighboring_surfaces.is_in_list(ref_face) )
16284         {
16285           // get neighbors
16286           DLIList<TBPoint*> neighbor_points;
16287           surfs.get()->points(neighbor_points);
16288           DLIList<Curve*> neighbor_curves;
16289           DLIList<Surface*> neighbor_surfaces;
16290           DLIList<TopologyBridge*> neighbors;
16291           DLIList<TopologyBridge*> tmp;
16292           int k;
16293           for(k=0; k<neighbor_points.size(); k++)
16294             neighbor_points.get_and_step()->surfaces(neighbor_surfaces);
16295           for(k=0; k<neighbor_points.size(); k++)
16296             neighbor_points.get_and_step()->curves(neighbor_curves);
16297 
16298           CAST_LIST_TO_PARENT(neighbor_points, tmp);
16299           neighbors += tmp;
16300           neighbor_curves.uniquify_ordered();
16301           CAST_LIST_TO_PARENT(neighbor_curves, tmp);
16302           neighbors += tmp;
16303           neighbor_surfaces.uniquify_ordered();
16304           CAST_LIST_TO_PARENT(neighbor_surfaces, tmp);
16305           neighbors += tmp;
16306           neighbors.append(surfs.get()->lump());
16307           neighbors.append(surfs.get()->bodysm());
16308 
16309           for(k=0; k<neighbors.size(); k++)
16310           {
16311             if(BridgeManager* m = neighbors.get_and_step()->bridge_manager())
16312             {
16313               if(TopologyEntity* t = m->topology_entity())
16314               {
16315                 RefEntity *ref_ent = CAST_TO(t, RefEntity );
16316                 entities_to_update.append(ref_ent);
16317               }
16318             }
16319           }
16320         }
16321       }
16322     }
16323   }
16324 
16325 
16326   DLIList<Body*> kept_surface_bodies;
16327   if( preview == CUBIT_FALSE && keep_surface )
16328   {
16329     int kk;
16330     for( kk=kept_surface_list.size(); kk--; )
16331     {
16332       Surface *surf = kept_surface_list.get_and_step();
16333       Body *new_body = make_Body( surf );
16334       kept_surface_bodies.append( new_body );
16335     }
16336   }
16337 
16338     // Update DAG
16339   CubitStatus stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
16340 
16341   if(!preview)
16342     do_attribute_cleanup();
16343 
16344   if( keep_surface )
16345     new_body_list += kept_surface_bodies;
16346 
16347   if( stat == CUBIT_FAILURE)
16348       return CUBIT_FAILURE;
16349 
16350     // Update graphics
16351   while (entities_to_update.size())
16352     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
16353 
16354 
16355   //unmerge all curves attached to these vertices after
16356   DLIList<RefEdge*> merged_ref_edges_after;
16357   for( i=new_body_list.size(); i--; )
16358   {
16359     Body *new_body = new_body_list.get_and_step();
16360     DLIList<RefVertex*> tmp_verts;
16361     new_body->ref_vertices( tmp_verts);
16362 
16363     for( j=tmp_verts.size(); j--; )
16364     {
16365       RefVertex *tmp_vert = tmp_verts.get_and_step();
16366       DLIList<RefEdge*> tmp_edges;
16367       if( tmp_vert->is_merged() )
16368       {
16369         tmp_vert->ref_edges( tmp_edges );
16370         int k;
16371         for( k=tmp_edges.size(); k--; )
16372         {
16373           RefEdge *tmp_edge = tmp_edges.get_and_step();
16374           if( tmp_edge->is_merged() )
16375             merged_ref_edges_after.append( tmp_edge );
16376         }
16377       }
16378     }
16379   }
16380 
16381   merged_ref_edges_before.uniquify_unordered();
16382   for( i=merged_ref_edges_before.size(); i--; )
16383   {
16384     RefEdge *tmp_edge = merged_ref_edges_before.get_and_step();
16385     if( merged_ref_edges_after.is_in_list( tmp_edge ) )
16386       MergeTool::instance()->unmerge( tmp_edge );
16387   }
16388 
16389   return CUBIT_SUCCESS;
16390 }
16391 
16392 
16393 //=============================================================================
16394 // Description: Function to remove curves from a sheet body and then extend the
16395 //              remaining curves or fill the gap or hole.
16396 // Author     : Steve Storm
16397 // Date       : 03/25/05
16398 //=============================================================================
16399 CubitStatus GeometryModifyTool::tweak_remove( DLIList<RefEdge*> &ref_edge_list,
16400                                               DLIList<Body*> &new_body_list,
16401                                               CubitBoolean keep_old_body,
16402                                               CubitBoolean preview )
16403 {
16404   DLIList<Curve*> curve_list(ref_edge_list.size());
16405   DLIList<Body*> old_body_list;
16406   GeometryModifyEngine* gme_ptr;
16407 
16408   // clear any preview previews
16409   GfxPreview::clear();
16410 
16411   gme_ptr = tweak_setup( ref_edge_list, "Removing", old_body_list, curve_list );
16412   if( !gme_ptr )
16413     return CUBIT_FAILURE;
16414 
16415   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16416   {
16417     if( keep_old_body )
16418       CubitUndo::save_state();
16419     else
16420       CubitUndo::save_state_with_cubit_file( ref_edge_list );
16421   }
16422 
16423   // Do remove
16424   DLIList<BodySM*> new_bodysm_list;
16425   CubitStatus stat = gme_ptr->tweak_remove( curve_list, new_bodysm_list,
16426                                             keep_old_body, preview );
16427   //collect all neighboring curves to those in the list
16428    int i, j;
16429    DLIList<RefEdge*> neighboring_curves;
16430    for( i=ref_edge_list.size(); i--; )
16431    {
16432      RefEdge *tmp_edge = ref_edge_list.get_and_step();
16433      DLIList<RefVertex*> tmp_ref_vertex_list;
16434      tmp_edge->ref_vertices( tmp_ref_vertex_list );
16435      for( j=tmp_ref_vertex_list.size(); j--; )
16436        tmp_ref_vertex_list.get_and_step()->ref_edges( neighboring_curves );
16437    }
16438 
16439   //uniquify and add other curves
16440   neighboring_curves.uniquify_unordered();
16441   //neighboring_curves += ref_edge_list;
16442 
16443   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16444     if( stat == CUBIT_FAILURE )
16445       CubitUndo::remove_last_undo();
16446 
16447   if( stat == CUBIT_FAILURE)
16448     return stat;
16449 
16450   // loop body sm list and find curves that need updating.
16451   // this is to account for some cases where the topology doesn't change, but the geometry does.
16452   DLIList<RefEntity*> entities_to_update;
16453   for(i=0; i<new_bodysm_list.size(); i++)
16454   {
16455     BodySM* bodysm = new_bodysm_list.get_and_step();
16456     DLIList<Curve*> curves;
16457     bodysm->curves(curves);
16458     int j;
16459     // find a surface that is also found in our input list
16460     for(j=0; j<curves.size(); j++, curves.step())
16461     {
16462       BridgeManager* man = curves.get()->bridge_manager();
16463       if(man)
16464       {
16465         RefEdge* ref_edge = CAST_TO(man->topology_entity(), RefEdge);
16466         if( ref_edge && neighboring_curves.is_in_list(ref_edge) )
16467         {
16468           // get neighbors
16469           DLIList<TBPoint*> neighbor_points;
16470           curves.get()->points(neighbor_points);
16471           DLIList<Curve*> neighbor_curves;
16472           DLIList<Surface*> neighbor_surfaces;
16473           DLIList<TopologyBridge*> neighbors;
16474           DLIList<TopologyBridge*> tmp;
16475           int k;
16476           for(k=0; k<neighbor_points.size(); k++)
16477             neighbor_points.get_and_step()->surfaces(neighbor_surfaces);
16478           for(k=0; k<neighbor_points.size(); k++)
16479             neighbor_points.get_and_step()->curves(neighbor_curves);
16480 
16481           CAST_LIST_TO_PARENT(neighbor_points, tmp);
16482           neighbors += tmp;
16483           neighbor_curves.uniquify_ordered();
16484           CAST_LIST_TO_PARENT(neighbor_curves, tmp);
16485           neighbors += tmp;
16486           neighbor_surfaces.uniquify_ordered();
16487           CAST_LIST_TO_PARENT(neighbor_surfaces, tmp);
16488           neighbors += tmp;
16489           //neighbors.append(curves.get()->lump());
16490           //neighbors.append(curves.get()->bodysm());
16491 
16492           for(k=0; k<neighbors.size(); k++)
16493           {
16494             if(BridgeManager* m = neighbors.get_and_step()->bridge_manager())
16495             {
16496               if(TopologyEntity* t = m->topology_entity())
16497               {
16498                 RefEntity *ref_ent = CAST_TO(t, RefEntity );
16499                 entities_to_update.append(ref_ent);
16500               }
16501             }
16502           }
16503         }
16504       }
16505     }
16506   }
16507 
16508   if(preview == CUBIT_FALSE )
16509   {
16510     // Update DAG
16511     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
16512 
16513     // Update graphics
16514     while (entities_to_update.size())
16515       AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
16516 
16517     if( CubitUndo::get_undo_enabled()  )
16518     {
16519       if( stat == CUBIT_FAILURE )
16520         CubitUndo::remove_last_undo();
16521       else if( keep_old_body )
16522         CubitUndo::note_result_bodies( new_body_list );
16523     }
16524   }
16525 
16526   return stat;
16527 }
16528 
16529 
16530 //=============================================================================
16531 // Description: Tweak specified faces of a volume or volumes up to a target
16532 //              surface or set of connected target surfaces.
16533 // Author     : Steve Storm
16534 // Date       : 03/25/05
16535 //=============================================================================
16536 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefFace*> &ref_face_list,
16537                                               DLIList<RefFace*> &target_face_list,
16538                                               DLIList<Body*> &new_body_list,
16539                                               CubitBoolean extend_flg,
16540                                               CubitPlane *limit_plane,
16541                                               CubitBoolean reverse_flg,
16542                                               CubitBoolean keep_old_body,
16543                                               CubitBoolean preview )
16544 {
16545   DLIList<Surface*> surface_list(ref_face_list.size());
16546   DLIList<Surface*> target_surf_list(target_face_list.size());
16547   DLIList<Body*> old_body_list;
16548   GeometryModifyEngine *gme_ptr1, *gme_ptr2;
16549 
16550   gme_ptr1 = tweak_setup( ref_face_list, "Tweaking", old_body_list, surface_list, CUBIT_TRUE );
16551   if (!gme_ptr1)
16552     return CUBIT_FAILURE;
16553 
16554   DLIList<Body*> old_body_list2;
16555   gme_ptr2 = tweak_setup( target_face_list, "Tweaking", old_body_list2, target_surf_list, CUBIT_TRUE );
16556   if (!gme_ptr2)
16557     return CUBIT_FAILURE;
16558 
16559   if( gme_ptr1 != gme_ptr2 )
16560   {
16561     PRINT_ERROR( "Target surfaces must belong to same geometry engine as tweaked surfaces.\n" );
16562     return CUBIT_FAILURE;
16563   }
16564 
16565   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16566   {
16567     if( keep_old_body )
16568       CubitUndo::save_state();
16569     else
16570       CubitUndo::save_state_with_cubit_file( ref_face_list );
16571   }
16572 
16573   int i;
16574   DLIList<Body*> all_bodies = old_body_list;
16575   all_bodies += old_body_list2;
16576   DLIList<BodySM*> body_sms;
16577   for(i=all_bodies.size(); i--;)
16578   {
16579     BodySM* bsm = all_bodies.get_and_step()->get_body_sm_ptr();
16580     if(bsm)
16581       body_sms.append_unique(bsm);
16582   }
16583 
16584   if(!preview)
16585   {
16586     do_attribute_setup();
16587     push_attributes_before_modify(body_sms);
16588   }
16589 
16590   // Do tweak to target
16591   DLIList<BodySM*> new_bodysm_list;
16592   CubitStatus stat = gme_ptr1->tweak_target( surface_list, target_surf_list,
16593                                              new_bodysm_list, extend_flg,
16594                                              limit_plane, reverse_flg,
16595                                              keep_old_body, preview );
16596 
16597 
16598   if( stat == CUBIT_FAILURE )
16599   {
16600     if(!preview)
16601       remove_pushed_attributes(new_bodysm_list, all_bodies);
16602     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16603       CubitUndo::remove_last_undo();
16604     if(!preview)
16605       do_attribute_cleanup();
16606     return CUBIT_FAILURE;
16607   }
16608   else
16609   {
16610     if(!preview)
16611     {
16612       restore_vg_after_modify(new_bodysm_list, all_bodies, gme_ptr1);
16613       remove_pushed_attributes(new_bodysm_list, all_bodies);
16614     }
16615   }
16616 
16617   // Collect all the old_faces to be compared against new_faces later...DJQ
16618   DLIList<RefFace*> old_faces;
16619   for (i = 0; i < old_body_list.size(); i++)
16620   {
16621       Body *old_body = old_body_list.get_and_step();
16622       DLIList<RefFace*> tmp_faces;
16623       old_body->ref_faces(tmp_faces);
16624       old_faces +=tmp_faces;
16625   }
16626 
16627   // Update DAG
16628   stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
16629 
16630   if(!preview)
16631     do_attribute_cleanup();
16632 
16633   if( stat == CUBIT_FAILURE )
16634   {
16635     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16636       CubitUndo::remove_last_undo();
16637     return CUBIT_FAILURE;
16638   }
16639 
16640   //collect all the new faces
16641   DLIList<RefFace*> new_faces;
16642   for( i=new_body_list.size(); i--; )
16643   {
16644     Body *new_body = new_body_list.get_and_step();
16645     DLIList<RefFace*> tmp_faces;
16646     new_body->ref_faces( tmp_faces );
16647     new_faces += tmp_faces;
16648   }
16649 
16650   // Compare the new_faces list with the old_faces list to determine which faces are created
16651   // Add these faces to the all_ref_face_list to check for its neighbors...DJQ
16652   DLIList<RefFace*> difference = new_faces;
16653   difference -= old_faces;
16654   ref_face_list += difference;
16655 
16656 
16657   // loop body sm list and find surfaces that need updating.
16658   // this is to account for some cases where the topology doesn't change, but the geometry does.
16659   DLIList<RefEntity*> entities_to_update;
16660   for(i=0; i<new_bodysm_list.size(); i++)
16661   {
16662     BodySM* bodysm = new_bodysm_list.get_and_step();
16663     DLIList<Surface*> surfs;
16664     bodysm->surfaces(surfs);
16665     int j;
16666     // find a surface that is also found in our input list
16667     // some times the target surface gets modified
16668     for(j=0; j<surfs.size(); j++, surfs.step())
16669     {
16670       BridgeManager* man = surfs.get()->bridge_manager();
16671       if(man)
16672       {
16673         RefFace* ref_face = CAST_TO(man->topology_entity(), RefFace);
16674         if(ref_face && (ref_face_list.is_in_list(ref_face) ||
16675             target_face_list.is_in_list(ref_face)))
16676         {
16677           // get neighbors
16678           DLIList<TBPoint*> neighbor_points;
16679           surfs.get()->points(neighbor_points);
16680           DLIList<Curve*> neighbor_curves;
16681           DLIList<Surface*> neighbor_surfaces;
16682           DLIList<TopologyBridge*> neighbors;
16683           DLIList<TopologyBridge*> tmp;
16684           int k;
16685           for(k=0; k<neighbor_points.size(); k++)
16686             neighbor_points.get_and_step()->surfaces(neighbor_surfaces);
16687           for(k=0; k<neighbor_points.size(); k++)
16688             neighbor_points.get_and_step()->curves(neighbor_curves);
16689 
16690           CAST_LIST_TO_PARENT(neighbor_points, tmp);
16691           neighbors += tmp;
16692           neighbor_curves.uniquify_ordered();
16693           CAST_LIST_TO_PARENT(neighbor_curves, tmp);
16694           neighbors += tmp;
16695           neighbor_surfaces.uniquify_ordered();
16696           CAST_LIST_TO_PARENT(neighbor_surfaces, tmp);
16697           neighbors += tmp;
16698           neighbors.append(surfs.get()->lump());
16699           neighbors.append(surfs.get()->bodysm());
16700 
16701           for(k=0; k<neighbors.size(); k++)
16702             if(BridgeManager* m = neighbors.get_and_step()->bridge_manager())
16703               if(TopologyEntity* t = m->topology_entity())
16704                 entities_to_update.append(CAST_TO(t, RefEntity));
16705         }
16706       }
16707     }
16708   }
16709 
16710   //unmerge any merged adjacent surfaces or
16711   //merged curves in unmerged adjacent surfaces
16712   DLIList<RefFace*> adjacent_faces_to_unmerge;
16713   DLIList<RefEdge*> adjacent_edges_to_unmerge;
16714   for(i=ref_face_list.size(); i--;)
16715   {
16716     RefFace *tweaked_face = ref_face_list.get_and_step();
16717     if( !new_faces.move_to( tweaked_face ) )
16718       continue;
16719 
16720     //get all the edges of the face you tweaked
16721     DLIList<RefEdge*> tweaked_face_edges;
16722     tweaked_face->ref_edges( tweaked_face_edges );
16723     adjacent_edges_to_unmerge += tweaked_face_edges;
16724 
16725     //get all the adjacent faces to this edge
16726     int j;
16727     for( j=tweaked_face_edges.size(); j--; )
16728     {
16729       RefEdge *tmp_edge = tweaked_face_edges.get_and_step();
16730       DLIList<RefFace*> tmp_faces;
16731       tmp_edge->ref_faces( tmp_faces );
16732       tmp_faces.remove( tweaked_face );
16733       adjacent_faces_to_unmerge += tmp_faces;
16734     }
16735 
16736     //get all edges not in the surface,
16737     //sharing vertices with the surface
16738     DLIList<RefVertex*> ref_vertices;
16739     tweaked_face->ref_vertices( ref_vertices );
16740     for( j=ref_vertices.size(); j--; )
16741     {
16742       RefVertex *tmp_vert = ref_vertices.get_and_step();
16743       DLIList<RefEdge*>  ref_edges;
16744       tmp_vert->ref_edges( ref_edges );
16745 
16746       int k;
16747       for( k=ref_edges.size(); k--; )
16748       {
16749         RefEdge *tmp_edge = ref_edges.get_and_step();
16750         if( !tweaked_face_edges.move_to( tmp_edge ) )
16751           adjacent_edges_to_unmerge.append( tmp_edge );
16752       }
16753     }
16754   }
16755 
16756   //unmerge any adjacent faces
16757   adjacent_faces_to_unmerge.uniquify_unordered();
16758   for( i=adjacent_faces_to_unmerge.size(); i--; )
16759   {
16760     RefFace *ref_face = adjacent_faces_to_unmerge.get_and_step();
16761 
16762     DLIList<TopologyBridge*> bridge_list;
16763     ref_face->bridge_manager()->get_bridge_list(bridge_list);
16764     if (bridge_list.size() > 1)
16765     {
16766       if( MergeTool::instance()->unmerge( ref_face ) )
16767         PRINT_WARNING("Unmerging Surface %d\n", ref_face->id() );
16768     }
16769   }
16770 
16771   //unmerge any adjacent edges
16772   adjacent_edges_to_unmerge.uniquify_unordered();
16773   for( i=adjacent_edges_to_unmerge.size(); i--; )
16774   {
16775     RefEdge *ref_edge = adjacent_edges_to_unmerge.get_and_step();
16776     DLIList<TopologyBridge*> bridge_list;
16777     ref_edge->bridge_manager()->get_bridge_list(bridge_list);
16778     if (bridge_list.size() > 1)
16779     {
16780       if( MergeTool::instance()->unmerge( ref_edge) )
16781         PRINT_WARNING("Unmerging Curve %d\n", ref_edge->id() );
16782     }
16783   }
16784 
16785   if( CubitUndo::get_undo_enabled() && keep_old_body )
16786     CubitUndo::note_result_bodies( new_body_list );
16787 
16788   // Update graphics
16789   while (entities_to_update.size())
16790     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
16791 
16792 
16793   return CUBIT_SUCCESS;
16794 }
16795 
16796 //=============================================================================
16797 // Description: Tweak specified faces of a volume or volumes up to a target
16798 //              plane.
16799 // Author     : Steve Storm
16800 // Date       : 05/10/05
16801 //=============================================================================
16802 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefFace*> &ref_face_list,
16803                                               CubitPlane &plane,
16804                                               DLIList<Body*> &new_body_list,
16805                                               CubitBoolean reverse_flg,
16806                                               CubitBoolean keep_old_body,
16807                                               CubitBoolean preview )
16808 {
16809   DLIList<Surface*> surface_list(ref_face_list.size()+1);
16810   DLIList<Body*> old_body_list;
16811   GeometryModifyEngine* gme_ptr;
16812 
16813   gme_ptr = tweak_setup( ref_face_list, "Tweaking", old_body_list, surface_list, CUBIT_TRUE );
16814   if (!gme_ptr)
16815     return CUBIT_FAILURE;
16816 
16817   // Create a target Surface from the plane (arbitrarily 10.0 X 10.0 in size)
16818 
16819   // Get corners of the surface
16820   CubitVector normal = plane.normal();
16821   CubitVector x, y;
16822   normal.orthogonal_vectors( x, y );
16823   CubitVector p1 = plane.point_on_plane();
16824   CubitVector p2, p3, p4;
16825   p1.next_point( x, 5.0, p1 );
16826   p1.next_point( y, 5.0, p1 );
16827   p1.next_point( -x, 10.0, p2 );
16828   p2.next_point( -y, 10.0, p3 );
16829   p3.next_point( x, 10.0, p4 );
16830 
16831   BodySM* bodysm_ptr = gme_ptr->planar_sheet( p1, p2, p3, p4 );
16832   if( !bodysm_ptr )
16833   {
16834     PRINT_ERROR( "unable to create target surface from plane\n" );
16835     return CUBIT_FAILURE;
16836   }
16837 
16838   DLIList<Surface*> target_surf_list;
16839   bodysm_ptr->surfaces( target_surf_list );
16840   if( !target_surf_list.size() )
16841   {
16842     PRINT_ERROR( "unable to create target surface from plane\n" );
16843     return CUBIT_FAILURE;
16844   }
16845 
16846   int i;
16847   DLIList<BodySM*> body_sms;
16848   for(i=old_body_list.size(); i--;)
16849   {
16850     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
16851     if(bsm)
16852       body_sms.append_unique(bsm);
16853   }
16854 
16855   if(!preview)
16856   {
16857     do_attribute_setup();
16858     push_attributes_before_modify(body_sms);
16859   }
16860 
16861   // Do tweak to target
16862   DLIList<BodySM*> new_bodysm_list;
16863   CubitStatus stat = gme_ptr->tweak_target( surface_list, target_surf_list,
16864                                             new_bodysm_list, CUBIT_TRUE,
16865                                             NULL, reverse_flg, keep_old_body,
16866                                             preview );
16867 
16868 
16869   if( stat == CUBIT_FAILURE )
16870   {
16871     if(!preview)
16872       remove_pushed_attributes(new_bodysm_list, old_body_list);
16873     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16874       CubitUndo::remove_last_undo();
16875     if(!preview)
16876       do_attribute_cleanup();
16877     return CUBIT_FAILURE;
16878   }
16879   else
16880   {
16881     if(!preview)
16882     {
16883       restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
16884       remove_pushed_attributes(new_bodysm_list, old_body_list);
16885     }
16886   }
16887 
16888   // Delete temporary sheet body
16889   bodysm_ptr->get_geometry_query_engine()->delete_solid_model_entities( bodysm_ptr );
16890 
16891   // Update DAG
16892   stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
16893 
16894   if(!preview)
16895     do_attribute_cleanup();
16896 
16897   if( stat == CUBIT_FAILURE )
16898   {
16899     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16900       CubitUndo::remove_last_undo();
16901     return CUBIT_FAILURE;
16902   }
16903 
16904   // Update graphics
16905   DLIList<Body*> moved_bodies(new_body_list);
16906   moved_bodies.intersect(old_body_list);
16907   while (moved_bodies.size())
16908     moved_bodies.pop()->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
16909 
16910   return CUBIT_SUCCESS;
16911 }
16912 
16913 //=============================================================================
16914 // Description: Tweak specified edges of a surface or set of surfaces (in sheet
16915 //              bodies) up to a target surface or set of target surfaces.
16916 // Author     : Steve Storm
16917 // Date       : 03/25/05
16918 //=============================================================================
16919 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefEdge*> &ref_edge_list,
16920                                               DLIList<RefFace*> &target_face_list,
16921                                               DLIList<Body*> &new_body_list,
16922                                               CubitBoolean extend_flg,
16923                                               CubitPlane *limit_plane,
16924                                               CubitBoolean reverse_flg,
16925                                               CubitBoolean keep_old,
16926                                               CubitBoolean preview,
16927                                               double max_area_increase /*= 0%*/ )
16928 {
16929   DLIList<Curve*> curve_list(ref_edge_list.size());
16930   DLIList<Surface*> target_surf_list(target_face_list.size());
16931   DLIList<Body*> old_body_list;
16932   GeometryModifyEngine *gme_ptr1, *gme_ptr2;
16933 
16934   gme_ptr1 = tweak_setup( ref_edge_list, "Tweaking", old_body_list, curve_list );
16935   if( !gme_ptr1 )
16936     return CUBIT_FAILURE;
16937 
16938   DLIList<Body*> old_body_list2;
16939   gme_ptr2 = tweak_setup( target_face_list, "Tweaking", old_body_list2, target_surf_list );
16940   if( !gme_ptr2 )
16941     return CUBIT_FAILURE;
16942 
16943   if( gme_ptr1 != gme_ptr2 )
16944   {
16945     PRINT_ERROR( "Target surface(s) must belong to same geometry engine as tweaked curves.\n" );
16946     return CUBIT_FAILURE;
16947   }
16948 
16949   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16950   {
16951     if( keep_old )
16952       CubitUndo::save_state();
16953     else
16954       CubitUndo::save_state_with_cubit_file( ref_edge_list );
16955   }
16956 
16957   // Do tweak to target
16958   DLIList<BodySM*> new_bodysm_list;
16959   CubitStatus stat = gme_ptr1->tweak_target( curve_list, target_surf_list,
16960                                              new_bodysm_list, extend_flg,
16961                                              limit_plane, reverse_flg,
16962                                              keep_old, preview, max_area_increase );
16963 
16964   if( stat == CUBIT_FAILURE )
16965   {
16966     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16967       CubitUndo::remove_last_undo();
16968     return CUBIT_FAILURE;
16969   }
16970 
16971   // Update DAG
16972   stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
16973 
16974 
16975   if( stat == CUBIT_FAILURE )
16976   {
16977     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16978       CubitUndo::remove_last_undo();
16979     return CUBIT_FAILURE;
16980   }
16981 
16982   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
16983   {
16984     if( keep_old )
16985       CubitUndo::note_result_bodies( new_body_list );
16986   }
16987 
16988   // Update graphics
16989   DLIList<Body*> moved_bodies(new_body_list);
16990   moved_bodies.intersect(old_body_list);
16991   while (moved_bodies.size())
16992   moved_bodies.pop()->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
16993 
16994   return CUBIT_SUCCESS;
16995 }
16996 
16997 //=============================================================================
16998 // Description: Tweak specified edges of a surface or set of surfaces (in sheet
16999 //              bodies) up to a target plane.
17000 // Author     : Steve Storm
17001 // Date       : 03/25/05
17002 //=============================================================================
17003 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefEdge*> &ref_edge_list,
17004                                               CubitPlane &plane,
17005                                               DLIList<Body*> &new_body_list,
17006                                               CubitBoolean reverse_flg,
17007                                               CubitBoolean keep_old,
17008                                               CubitBoolean preview )
17009 {
17010   DLIList<Curve*> curve_list(ref_edge_list.size());
17011   DLIList<Body*> old_body_list;
17012   GeometryModifyEngine* gme_ptr;
17013 
17014   gme_ptr = tweak_setup( ref_edge_list, "Tweaking", old_body_list, curve_list );
17015   if( !gme_ptr )
17016     return CUBIT_FAILURE;
17017 
17018   // Create a target Surface from the plane (arbitrarily 10.0 X 10.0 in size)
17019 
17020   // Get corners of the surface
17021   CubitVector normal = plane.normal();
17022   CubitVector x, y;
17023   normal.orthogonal_vectors( x, y );
17024   CubitVector p1 = plane.point_on_plane();
17025   CubitVector p2, p3, p4;
17026   p1.next_point( x, 5.0, p1 );
17027   p1.next_point( y, 5.0, p1 );
17028   p1.next_point( -x, 10.0, p2 );
17029   p2.next_point( -y, 10.0, p3 );
17030   p3.next_point( x, 10.0, p4 );
17031 
17032   BodySM* bodysm_ptr = gme_ptr->planar_sheet( p1, p2, p3, p4 );
17033   if( !bodysm_ptr )
17034   {
17035     PRINT_ERROR( "unable to create target surface from plane\n" );
17036     return CUBIT_FAILURE;
17037   }
17038 
17039   DLIList<Surface*> target_surf_list;
17040   bodysm_ptr->surfaces( target_surf_list );
17041   if( !target_surf_list.size() )
17042   {
17043     PRINT_ERROR( "unable to create target surface from plane\n" );
17044     return CUBIT_FAILURE;
17045   }
17046 
17047   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17048   {
17049     if( keep_old )
17050       CubitUndo::save_state();
17051     else
17052       CubitUndo::save_state_with_cubit_file( ref_edge_list );
17053   }
17054 
17055   // Do tweak to target
17056   DLIList<BodySM*> new_bodysm_list;
17057   CubitStatus stat = gme_ptr->tweak_target( curve_list, target_surf_list,
17058                                             new_bodysm_list, CUBIT_TRUE,
17059                                             NULL, reverse_flg, keep_old,
17060                                             preview );
17061 
17062   if( stat == CUBIT_FAILURE )
17063   {
17064     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17065       CubitUndo::remove_last_undo();
17066     return CUBIT_FAILURE;
17067   }
17068 
17069   // Delete temporary sheet body
17070   bodysm_ptr->get_geometry_query_engine()->delete_solid_model_entities( bodysm_ptr );
17071 
17072   // Update DAG
17073   stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
17074 
17075   if( stat == CUBIT_FAILURE )
17076   {
17077     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17078       CubitUndo::remove_last_undo();
17079     return CUBIT_FAILURE;
17080   }
17081 
17082   if( CubitUndo::get_undo_enabled() && keep_old )
17083     CubitUndo::note_result_bodies( new_body_list );
17084 
17085   // Update graphics
17086   DLIList<Body*> moved_bodies(new_body_list);
17087   moved_bodies.intersect(old_body_list);
17088   while (moved_bodies.size())
17089     moved_bodies.pop()->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
17090 
17091   return CUBIT_SUCCESS;
17092 }
17093 
17094 //=============================================================================
17095 // Description: Tweak specified edges of a sheet body or bodies up to target
17096 //              curves that are part of a sheet body.  The target is a surface
17097 //              created by thickening the owning surface of the target curves.
17098 // Author     : Steve Storm
17099 // Date       : 03/25/05
17100 //=============================================================================
17101 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefEdge*> &ref_edge_list,
17102                                               DLIList<RefEdge*> &target_edge_list,
17103                                               DLIList<Body*> &new_body_list,
17104                                               CubitBoolean extend_flg,
17105                                               CubitPlane *limit_plane,
17106                                               CubitBoolean reverse_flg,
17107                                               CubitBoolean keep_old,
17108                                               CubitBoolean preview,
17109                                               double max_area_increase /*= 0*/ )
17110 {
17111   DLIList<Curve*> curve_list(ref_edge_list.size());
17112   DLIList<Curve*> target_curve_list(target_edge_list.size());
17113   DLIList<Body*> old_body_list;
17114   GeometryModifyEngine *gme_ptr1, *gme_ptr2;
17115 
17116   gme_ptr1 = tweak_setup( ref_edge_list, "Tweaking", old_body_list, curve_list );
17117   if( !gme_ptr1 )
17118     return CUBIT_FAILURE;
17119 
17120   DLIList<Body*> old_body_list2;
17121   gme_ptr2 = tweak_setup( target_edge_list, "Tweaking", old_body_list2, target_curve_list );
17122   if( !gme_ptr2 )
17123     return CUBIT_FAILURE;
17124 
17125   if( gme_ptr1 != gme_ptr2 )
17126   {
17127     PRINT_ERROR( "Target curves must belong to same geometry engine as tweaked curves.\n" );
17128     return CUBIT_FAILURE;
17129   }
17130 
17131   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17132   {
17133     if( keep_old )
17134       CubitUndo::save_state();
17135     else
17136       CubitUndo::save_state_with_cubit_file( ref_edge_list );
17137   }
17138 
17139   // Do tweak to target
17140   DLIList<BodySM*> new_bodysm_list;
17141   CubitStatus stat = gme_ptr1->tweak_target( curve_list, target_curve_list,
17142                                              new_bodysm_list, extend_flg,
17143                                              limit_plane, reverse_flg,
17144                                              keep_old, preview, max_area_increase );
17145 
17146   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17147     if( stat == CUBIT_FAILURE )
17148       CubitUndo::remove_last_undo();
17149 
17150   if( stat == CUBIT_FAILURE)
17151     return stat;
17152 
17153   DLIList<RefEntity*> entities_to_update;
17154   if( preview == CUBIT_FALSE )
17155   {
17156     // check for resued entities, they have been moved and we need to notify observers
17157     int i;
17158     for(i=0; i<new_bodysm_list.size(); i++)
17159     {
17160       BodySM* bodysm = new_bodysm_list.get_and_step();
17161       DLIList<TopologyBridge*> to_check;
17162       DLIList<TopologyBridge*> tmp;
17163       DLIList<Surface*> surfs;
17164       bodysm->surfaces(surfs);
17165       DLIList<Curve*> curves;
17166       bodysm->curves(curves);
17167       DLIList<TBPoint*> points;
17168       bodysm->points(points);
17169       to_check.append(bodysm);
17170       to_check.append(bodysm->lump());
17171       CAST_LIST_TO_PARENT(surfs, tmp);
17172       to_check += tmp;
17173       CAST_LIST_TO_PARENT(curves, tmp);
17174       to_check += tmp;
17175       CAST_LIST_TO_PARENT(points, tmp);
17176       to_check += tmp;
17177 
17178       int k;
17179       for(k=0; k<to_check.size(); k++)
17180         if(BridgeManager* m = to_check.get_and_step()->bridge_manager())
17181           if(TopologyEntity* t = m->topology_entity())
17182             entities_to_update.append(CAST_TO(t, RefEntity));
17183     }
17184 
17185     // Update DAG
17186     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
17187 
17188     if( CubitUndo::get_undo_enabled()  )
17189     {
17190       if( stat == CUBIT_FAILURE )
17191         CubitUndo::remove_last_undo();
17192       else if( keep_old )
17193         CubitUndo::note_result_bodies( new_body_list );
17194     }
17195   }
17196 
17197   // Update graphics
17198   while (entities_to_update.size())
17199     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, entities_to_update.pop()));
17200 
17201   // Update graphics
17202   DLIList<Body*> moved_bodies(new_body_list);
17203   moved_bodies.intersect(old_body_list);
17204   while (moved_bodies.size())
17205     AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::GEOMETRY_MODIFIED, moved_bodies.pop()));
17206 
17207   return stat;
17208 }
17209 
17210 //=============================================================================
17211 // Description: Tweak specified vertex of a sheet body to a given location.
17212 //              The given vertex must be part of a planar surface or surfaces
17213 //              attached to linear curves only.  The given location will be
17214 //              projected to be on the planar surface(s) before being used.
17215 // Author     : Steve Storm
17216 // Date       : 09/09/08
17217 //=============================================================================
17218 CubitStatus
17219 GeometryModifyTool::tweak_target( RefVertex *ref_vertex_ptr,
17220                                   DLIList<RefFace*> &modify_ref_face_list,
17221                                   CubitVector &target_loc,
17222                                   Body *&new_Body_ptr,
17223                                   CubitBoolean keep_old,
17224                                   CubitBoolean preview )
17225 {
17226   if( modify_ref_face_list.size() == 0 )
17227   {
17228     PRINT_ERROR( "No surfaces found to modify\n" );
17229     return CUBIT_FAILURE;
17230   }
17231 
17232   int i;
17233   RefFace *ref_face_ptr;
17234 
17235   // Check to make sure vertex is part of all given surfaces
17236   modify_ref_face_list.reset();
17237   for( i=modify_ref_face_list.size(); i--; )
17238   {
17239     ref_face_ptr = modify_ref_face_list.get_and_step();
17240 
17241     if( !ref_face_ptr->is_directly_related( ref_vertex_ptr ) )
17242     {
17243       PRINT_ERROR( "Vertex %d is not part of 'modify' Surface %d\n",
17244         ref_vertex_ptr->id(), ref_face_ptr->id() );
17245       return CUBIT_FAILURE;
17246     }
17247   }
17248 
17249   GeometryModifyEngine *gme_ptr;
17250   DLIList<RefVertex*> ref_vertex_list(1);
17251   ref_vertex_list.append( ref_vertex_ptr );
17252   DLIList<Body*> old_body_list;
17253   DLIList<TBPoint*> point_list(1);
17254   gme_ptr = tweak_setup( ref_vertex_list, "Tweaking", old_body_list, point_list );
17255   if( !gme_ptr )
17256     return CUBIT_FAILURE;
17257 
17258   // We already made sure the vertex is part of all of the modify faces, so
17259   // just use the common_modify_engine function to get the surface_list
17260   DLIList<Surface*> surface_list;
17261   if( !common_modify_engine( modify_ref_face_list, surface_list ) )
17262     return CUBIT_FAILURE;
17263 
17264   // Make sure part of a sheet body, not a solid body
17265   Body *body_ptr = ref_vertex_ptr->body();
17266   if( !body_ptr->is_sheet_body() )
17267   {
17268     PRINT_ERROR( "Vertex %d is not in a sheet body - Body %d is solid.\n"
17269       "       Tweaking a vertex to a target currently not possible on solid bodies.\n",
17270       ref_vertex_ptr->id(), body_ptr->id() );
17271     return CUBIT_FAILURE;
17272   }
17273 
17274   // Make sure all the given surfaces are planar
17275   modify_ref_face_list.reset();
17276   for( i=modify_ref_face_list.size(); i--; )
17277   {
17278     ref_face_ptr = modify_ref_face_list.get_and_step();
17279 
17280     if( !ref_face_ptr->is_planar() )
17281     {
17282       PRINT_ERROR( "Surfaces to modify must be planar - Surface %d is not planar\n", ref_face_ptr->id() );
17283       return CUBIT_FAILURE;
17284     }
17285   }
17286 
17287   // Make sure all curves (on modify surfaces) attached to the given vertex are linear
17288   // Get all attached curves
17289   int j;
17290   DLIList<RefEdge*> ref_edge_list;
17291   ref_vertex_ptr->ref_edges( ref_edge_list );
17292   RefEdge *ref_edge_ptr;
17293   for( i=ref_edge_list.size(); i--; )
17294   {
17295     ref_edge_ptr = ref_edge_list.get_and_step();
17296 
17297     // Check to see if this edge is linear, if it is in one of the modify surfaces
17298     modify_ref_face_list.reset();
17299     for( j=modify_ref_face_list.size(); j--; )
17300     {
17301       ref_face_ptr = modify_ref_face_list.get_and_step();
17302       if( ref_face_ptr->is_directly_related( ref_edge_ptr ) )
17303       {
17304         Curve *curve_ptr = ref_edge_ptr->get_curve_ptr();
17305         GeometryType curve_type = curve_ptr->geometry_type();
17306         if( curve_type != STRAIGHT_CURVE_TYPE )
17307         {
17308           PRINT_ERROR( "Curve %d is not linear. Curves that are in the 'modify'\n"
17309             "       surfaces attached to the tweak vertex must be linear.\n",
17310             ref_edge_ptr->id() );
17311           return CUBIT_FAILURE;
17312         }
17313         else
17314           break;
17315       }
17316     }
17317   }
17318 
17319   // Project the location to the given surfaces and make sure all of these locations
17320   // are the same
17321   modify_ref_face_list.reset();
17322 
17323   CubitVector ref_loc( target_loc ); // Reference location
17324   ref_face_ptr = modify_ref_face_list.get_and_step();
17325   ref_face_ptr->move_to_surface( ref_loc );
17326   int ref_surf_id = ref_face_ptr->id();
17327 
17328   for( i=modify_ref_face_list.size()-1; i--; )
17329   {
17330     ref_face_ptr = modify_ref_face_list.get_and_step();
17331 
17332     CubitVector proj_loc( target_loc );
17333     ref_face_ptr->move_to_surface( proj_loc );
17334 
17335     if( !ref_loc.about_equal( proj_loc ) )
17336     {
17337       PRINT_ERROR( "Target location must project to all of the 'modify' surfaces at\n"
17338         "       exactly the same location - the tweaked Vertex %d will move to this\n"
17339         "       common (same) projected location, tweaking the modify surfaces with it.\n"
17340         "       Given target location = %f, %f, %f\n"
17341         "       Projected location on Surface %d = %f, %f, %f\n"
17342         "       Projected location on Surface %d = %f, %f, %f\n",
17343         ref_vertex_ptr->id(),
17344         target_loc.x(), target_loc.y(), target_loc.z(),
17345         ref_surf_id, ref_loc.x(), ref_loc.y(), ref_loc.z(),
17346         ref_face_ptr->id(), proj_loc.x(), proj_loc.y(), proj_loc.z() );
17347 
17348       return CUBIT_FAILURE;
17349     }
17350   }
17351 
17352   // It looks like the inputs are valid so get ready to do the tweak
17353   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17354   {
17355     if( keep_old )
17356       CubitUndo::save_state();
17357     else
17358       CubitUndo::save_state_with_cubit_file( ref_vertex_list );
17359   }
17360 
17361   TBPoint *point_ptr = point_list.get();
17362 
17363   // Do tweak to target
17364   BodySM *new_bodysm_ptr;
17365   CubitStatus stat = gme_ptr->tweak_target( point_ptr, surface_list,
17366                                             ref_loc,
17367                                             new_bodysm_ptr,
17368                                             keep_old, preview );
17369 
17370   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
17371     if( stat == CUBIT_FAILURE )
17372       CubitUndo::remove_last_undo();
17373 
17374   if( stat == CUBIT_FAILURE)
17375     return stat;
17376 
17377   DLIList<BodySM*> new_bodysm_list;
17378   new_bodysm_list.append( new_bodysm_ptr );
17379   DLIList<Body*> new_body_list;
17380 
17381   if( preview == CUBIT_FALSE )
17382   {
17383     // Update DAG
17384     stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
17385 
17386     if( CubitUndo::get_undo_enabled() )
17387     {
17388       if( stat == CUBIT_FAILURE )
17389         CubitUndo::remove_last_undo();
17390       else if( keep_old )
17391         CubitUndo::note_result_bodies( new_body_list );
17392     }
17393   }
17394 
17395   // Update graphics
17396   DLIList<Body*> moved_bodies(new_body_list);
17397   moved_bodies.intersect(old_body_list);
17398   while (moved_bodies.size())
17399     moved_bodies.pop()->notify_sub_all_observers( GeometryEvent::GEOMETRY_MODIFIED );
17400 
17401   return stat;
17402 }
17403 
17404 // KGM
17405 #if 0
17406 bool GeometryModifyTool::contains_intermediate_geometry(DLIList<RefFace*>& ref_face_list) const
17407 {
17408   for (int i = 0; i < ref_face_list.size(); i++)
17409     if (GeometryQueryTool::instance()->
17410         contains_intermediate_geometry(ref_face_list.next(i)))
17411       return true;
17412 
17413   return false;
17414 }
17415 #endif
17416 
17417 /*
17418 //the following surface tool operations added by Tyronne Lim (CAT) ********************
17419 CubitStatus GeometryModifyTool::create_net_surface( DLIList<Surface*>& ref_face_list, BodySM *& new_body,
17420                                                     DLIList<DLIList<CubitVector*>*> &vec_lists_u,
17421                                                     DLIList<DLIList<CubitVector*>*> &vec_lists_v,
17422                                                     double net_tol, CubitBoolean heal )
17423 {
17424    GeometryModifyEngine* GMEPtr = get_engine(ref_face_list.get());
17425    return GMEPtr->create_net_surface( ref_face_list, new_body, vec_lists_u, vec_lists_v, net_tol, heal );
17426 } */
17427 
17428 CubitStatus GeometryModifyTool::create_net_surface( DLIList<RefEdge*>& u_curves, DLIList<RefEdge*>& v_curves,
17429                                                     double net_tol, CubitBoolean heal )
17430 {
17431   DLIList<TopologyBridge*> bridge_list;
17432   DLIList<TopologyEntity*> entity_list;
17433   CAST_LIST_TO_PARENT( u_curves, entity_list );
17434 
17435   GeometryModifyEngine* GME_ptr =
17436     common_modify_engine( entity_list, bridge_list );
17437   if(! GME_ptr )
17438   {
17439      PRINT_ERROR("Cannot construct a Surface using entities that do "
17440                  "not share a common GeometryModifyEngine.\n");
17441      return CUBIT_FAILURE;
17442   }
17443 
17444   DLIList<Curve*> curves_in_u(bridge_list.size());
17445   CAST_LIST( bridge_list, curves_in_u, Curve );
17446 
17447   bridge_list.clean_out();
17448   entity_list.clean_out();
17449   CAST_LIST_TO_PARENT( v_curves, entity_list );
17450 
17451   GeometryModifyEngine* dummy_GME_ptr =
17452     common_modify_engine( entity_list, bridge_list );
17453   if(! dummy_GME_ptr || dummy_GME_ptr != GME_ptr )
17454   {
17455      PRINT_ERROR("Cannot construct a Surface using entities that do "
17456                  "not share a common GeometryModifyEngine.\n");
17457      return CUBIT_FAILURE;
17458   }
17459 
17460   DLIList<Curve*> curves_in_v(bridge_list.size());
17461   CAST_LIST( bridge_list, curves_in_v, Curve );
17462 
17463   BodySM *new_smbody = NULL;
17464   if( !GME_ptr->create_net_surface( curves_in_u, curves_in_v, new_smbody, net_tol, heal ) )
17465     return CUBIT_FAILURE;
17466 
17467   if (CubitUndo::get_undo_enabled())
17468     CubitUndo::save_state();
17469 
17470   Body* new_body = NULL;
17471   new_body = GeometryQueryTool::instance()->make_Body( new_smbody );
17472   if( new_body )
17473   {
17474     if (CubitUndo::get_undo_enabled())
17475       CubitUndo::note_result_body(new_body);
17476 
17477     return CUBIT_SUCCESS;
17478   }
17479   else
17480   {
17481     if (CubitUndo::get_undo_enabled())
17482       CubitUndo::remove_last_undo();
17483 
17484     return CUBIT_FAILURE;
17485   }
17486 }
17487 
17488 CubitStatus GeometryModifyTool::create_offset_surface( RefFace* ref_face_ptr, double offset_distance )
17489 {
17490   TopologyBridge *bridge_ptr = NULL;
17491   GeometryModifyEngine* GMEPtr = get_engine(ref_face_ptr, &bridge_ptr );
17492 
17493   Surface *tmp_surf = NULL;
17494   tmp_surf = CAST_TO( bridge_ptr, Surface );
17495 
17496   BodySM *new_smbody;
17497   if( !GMEPtr->create_offset_surface( tmp_surf, new_smbody, offset_distance ) )
17498     return CUBIT_FAILURE;
17499 
17500   if (CubitUndo::get_undo_enabled())
17501     CubitUndo::save_state();
17502 
17503   Body* new_body = NULL;
17504   new_body = GeometryQueryTool::instance()->make_Body( new_smbody );
17505   if( new_body )
17506   {
17507     if (CubitUndo::get_undo_enabled())
17508       CubitUndo::note_result_body(new_body);
17509 
17510     return CUBIT_SUCCESS;
17511   }
17512   else
17513   {
17514     if (CubitUndo::get_undo_enabled())
17515       CubitUndo::remove_last_undo();
17516 
17517     return CUBIT_FAILURE;
17518   }
17519 }
17520 
17521 //-----------------------------------------------------------------------------
17522 // Purpose       : This function creates a sheet body or bodies by offsetting
17523 //                 the given faces. An optional additional face list and double
17524 //                 list (must be same length) allow different offset distances
17525 //                 for different faces. Adjoining faces are extended or trimmed
17526 //                 to remain joined in the new sheet body.  Radial faces that
17527 //                 cannot be so offset are removed and the resulting wound
17528 //                 healed by the surrounding faces.
17529 //
17530 // Special Notes :
17531 //
17532 // Creator       : Steve Storm
17533 //
17534 // Creation Date : 05/04/08
17535 //-----------------------------------------------------------------------------
17536 CubitStatus
17537 GeometryModifyTool::create_offset_sheet( DLIList<RefFace*> &ref_face_list,
17538                                          double offset_distance,
17539                                          DLIList<RefFace*> *add_ref_face_list_ptr,
17540                                          DLIList<double> *add_offset_list_ptr,
17541                                          DLIList<Body*> &new_body_list,
17542                                          CubitBoolean preview )
17543 {
17544   if( !ref_face_list.size() )
17545   {
17546     return CUBIT_SUCCESS;
17547   }
17548   else
17549   {
17550     for (int i = 0; i < ref_face_list.size(); i++)
17551     {
17552       RefFace *temp = ref_face_list.get_and_step();
17553       if (temp->get_surface_ptr()->is_cylindrical() == 16)
17554       {
17555         DLIList<Curve*> curves;
17556         CubitVector loc;
17557         double rad;
17558         temp->get_surface_ptr()->curves(curves);
17559         curves.reset();
17560         int j = 0;
17561         while (curves.get()->geometry_type() != ELLIPSE_CURVE_TYPE && curves.get()->geometry_type() != ARC_CURVE_TYPE)
17562         {
17563           curves.step();
17564           if (j == curves.size())
17565           {
17566               break;
17567           }
17568           j++;
17569         }
17570         curves.get()->get_center_radius(loc, rad);
17571         if (offset_distance >= rad)
17572         {
17573           CubitVector norm, close, result;
17574           double angle;
17575           temp->get_surface_ptr()->closest_point(loc, &close, &norm);
17576           result.set(loc.x()-close.x(), loc.y()-close.y(), loc.z()-close.z());
17577           angle = result.interior_angle(norm);
17578           if (angle < GEOMETRY_RESABS && angle > -GEOMETRY_RESABS)
17579           {
17580             PRINT_ERROR("Offset is greater than the radius of curvature for surface %i.\n", temp->id());
17581             PRINT_WARNING("No body will be created for surface %i.\n", temp->id());
17582             if (ref_face_list.size() > 1)
17583             {
17584               ref_face_list.remove_all_with_value(temp);
17585             }
17586             else
17587             {
17588               return CUBIT_FAILURE;
17589             }
17590           }
17591         }
17592       }
17593     }
17594     for (int i = 0; i < add_ref_face_list_ptr->size(); i++)
17595     {
17596       RefFace *temp = ref_face_list.get_and_step();
17597       if (temp->get_surface_ptr()->is_cylindrical() == 16)
17598       {
17599         DLIList<Curve*> curves;
17600         CubitVector loc;
17601         double rad;
17602         temp->get_surface_ptr()->curves(curves);
17603         curves.reset();
17604         while (curves.get()->geometry_type() != ELLIPSE_CURVE_TYPE && curves.get()->geometry_type() != ARC_CURVE_TYPE)
17605         {
17606           curves.step();
17607         }
17608         curves.get()->get_center_radius(loc, rad);
17609         if (offset_distance >= rad)
17610         {
17611           CubitVector norm, close, result;
17612           double angle;
17613           temp->get_surface_ptr()->closest_point(loc, &close, &norm);
17614           result.set(loc.x()-close.x(), loc.y()-close.y(), loc.z()-close.z());
17615           angle = result.interior_angle(norm);
17616           if (angle < GEOMETRY_RESABS && angle > -GEOMETRY_RESABS)
17617           {
17618             PRINT_ERROR("Offset is greater than the radius of curvature for surface %i.\n", temp->id());
17619             PRINT_WARNING("No body will be created for surface %i.\n", temp->id());
17620             add_ref_face_list_ptr->remove_all_with_value(temp);
17621           }
17622         }
17623       }
17624     }
17625   }
17626 
17627   DLIList<RefFace*> all_ref_face_list(ref_face_list.size());
17628   all_ref_face_list = ref_face_list;
17629   if( add_ref_face_list_ptr->size() )
17630     all_ref_face_list += *add_ref_face_list_ptr;
17631 
17632   // Check for virtual geometry
17633   DLIList<RefEntity*> ref_ent_list;
17634   CAST_LIST_TO_PARENT(all_ref_face_list, ref_ent_list);
17635   if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
17636   {
17637     PRINT_ERROR("OFFSETTING surfaces containing virtual geometry is not\n"
17638       "       allowed. Delete virtual geometry on these surfaces\n"
17639       "       before operation.\n" );
17640     return CUBIT_FAILURE;
17641   }
17642 
17643   // Look for a common GeometryModifyEngine for all of the RefFaces
17644   int count = all_ref_face_list.size();
17645   DLIList<TopologyBridge*> bridge_list(count);
17646   DLIList<TopologyEntity*> entity_list(count);
17647   CAST_LIST_TO_PARENT( all_ref_face_list, entity_list );
17648 
17649   GeometryModifyEngine* GME_ptr =
17650     common_modify_engine( entity_list, bridge_list );
17651   if(! GME_ptr )
17652   {
17653      PRINT_ERROR("Cannot construct offset sheet(s) using surfaces that\n"
17654                  "       do not share a common geometry engine.\n");
17655      return CUBIT_FAILURE;
17656   }
17657 
17658   // Get Surfaces from the RefFaces
17659   DLIList<Surface*> surface_list(ref_face_list.size());
17660   int i;
17661   RefFace *ref_face_ptr;
17662   for( i=ref_face_list.size(); i--; )
17663   {
17664     ref_face_ptr = ref_face_list.get_and_step();
17665     surface_list.append( ref_face_ptr->get_surface_ptr() );
17666   }
17667 
17668   DLIList<Surface*> add_surf_list;
17669   if( add_ref_face_list_ptr->size() )
17670   {
17671     for( i=add_ref_face_list_ptr->size(); i--; )
17672     {
17673       ref_face_ptr = add_ref_face_list_ptr->get_and_step();
17674       add_surf_list.append( ref_face_ptr->get_surface_ptr() );
17675     }
17676   }
17677   
17678   if (CubitUndo::get_undo_enabled() && !preview )
17679     CubitUndo::save_state();
17680 
17681   CubitStatus status;
17682   DLIList<BodySM*> BodySM_list;
17683   if( add_surf_list.size() )
17684   {
17685     status = GME_ptr->create_offset_sheet( surface_list, offset_distance, &add_surf_list,
17686       add_offset_list_ptr, BodySM_list, preview );      
17687   }
17688   else
17689   {
17690     status = GME_ptr->create_offset_sheet( surface_list, offset_distance, NULL,
17691       NULL, BodySM_list, preview );      
17692   }
17693 
17694   if( status == CUBIT_FAILURE || !BodySM_list.size() )
17695   {
17696     if(CubitUndo::get_undo_enabled() && !preview )
17697       CubitUndo::remove_last_undo();
17698     return CUBIT_FAILURE;
17699   }
17700 
17701   BodySM *bodysm_ptr;
17702   Body* body_ptr;
17703   for( i=BodySM_list.size(); i--; )
17704   {
17705     DLIList<Surface*> surfs;
17706     bodysm_ptr = BodySM_list.get_and_step();
17707     bodysm_ptr->surfaces(surfs);
17708     if (!surfs.size())
17709     {
17710       PRINT_WARNING("Empty body created.  Body deleted.\n");
17711       PRINT_WARNING("Empty body likely due to an offset larger than the radius of curvature of a surface.\n");
17712       bodysm_ptr->get_geometry_query_engine()->delete_solid_model_entities(bodysm_ptr);
17713       break;
17714     }
17715 
17716     body_ptr = GeometryQueryTool::instance()->make_Body( bodysm_ptr );
17717     if( body_ptr )
17718       new_body_list.append( body_ptr );
17719   }
17720 
17721   if( new_body_list.size() )
17722   {
17723     if(CubitUndo::get_undo_enabled() && !preview )
17724       CubitUndo::note_result_bodies(new_body_list);
17725     return CUBIT_SUCCESS;
17726   }
17727   else
17728   {
17729     if(CubitUndo::get_undo_enabled() && !preview )
17730       CubitUndo::remove_last_undo();
17731     return CUBIT_FAILURE;
17732   }
17733 }
17734 
17735 CubitStatus
17736 GeometryModifyTool::create_offset_body( Body *body_ptr, Body *&new_body,
17737                                         double offset_distance )
17738 {
17739   GeometryModifyEngine* GMEPtr = get_engine(body_ptr);
17740 
17741   BodySM *body_sm = body_ptr->get_body_sm_ptr();
17742   if (!body_sm)
17743   {
17744     PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n", body_ptr->id());
17745     return CUBIT_FAILURE;
17746   }
17747 
17748   BodySM *new_body_sm;
17749   if( !GMEPtr->create_offset_body( body_sm, new_body_sm, offset_distance ) )
17750     return CUBIT_FAILURE;
17751 
17752   if (CubitUndo::get_undo_enabled())
17753     CubitUndo::save_state();
17754 
17755   new_body = GeometryQueryTool::instance()->make_Body( new_body_sm );
17756 
17757   if( new_body )
17758   {
17759     if (CubitUndo::get_undo_enabled())
17760       CubitUndo::note_result_body(new_body);
17761 
17762     return CUBIT_SUCCESS;
17763   }
17764   else
17765   {
17766     if (CubitUndo::get_undo_enabled())
17767       CubitUndo::remove_last_undo();
17768 
17769     return CUBIT_FAILURE;
17770   }
17771 }
17772 
17773 CubitStatus GeometryModifyTool::create_skin_surface( DLIList<RefEdge*>& ref_edges, Body*& new_body,
17774                                                      DLIList<RefEdge*>& guides)
17775 {
17776   DLIList<TopologyBridge*> bridge_list;
17777   DLIList<TopologyEntity*> entity_list;
17778   CAST_LIST_TO_PARENT( ref_edges, entity_list );
17779 
17780   DLIList<TopologyBridge*> guide_bridge_list;
17781   DLIList<TopologyEntity*> guide_entity_list;
17782   CAST_LIST_TO_PARENT(guides, guide_entity_list);
17783 
17784   if (ref_edges.size() < 2)
17785   {
17786      PRINT_ERROR("Must specify at least 2 curves to create a skinned surface.\n");
17787      return CUBIT_FAILURE;
17788   }
17789 
17790   GeometryModifyEngine* GME_ptr =
17791     common_modify_engine( entity_list, bridge_list );
17792   if(! GME_ptr )
17793   {
17794      PRINT_ERROR("Cannot construct a Surface using entities that do "
17795                  "not share a common GeometryModifyEngine.\n");
17796      return CUBIT_FAILURE;
17797   }
17798 
17799   if (guides.size() > 0)
17800   {
17801       GeometryModifyEngine* GME_ptr2 =
17802           common_modify_engine( guide_entity_list, guide_bridge_list );
17803       if (GME_ptr != GME_ptr2)
17804       {
17805           PRINT_ERROR("Performing create skin with geometry from\n"
17806             "different modeling engines is not allowed.\n");
17807           return CUBIT_FAILURE;
17808       }
17809   }
17810 
17811   DLIList<Curve*> curves_to_skin(bridge_list.size());
17812   CAST_LIST( bridge_list, curves_to_skin, Curve );
17813 
17814   DLIList<Curve*> guide_curves(guide_bridge_list.size());
17815   CAST_LIST(guide_bridge_list, guide_curves, Curve);
17816 
17817   BodySM *new_body_sm = NULL;
17818   if( !GME_ptr->create_skin_surface( curves_to_skin, new_body_sm, guide_curves ) )
17819     return CUBIT_FAILURE;
17820 
17821   if (CubitUndo::get_undo_enabled())
17822     CubitUndo::save_state();
17823 
17824   new_body = NULL;
17825   new_body = GeometryQueryTool::instance()->make_Body( new_body_sm );
17826 
17827   if( new_body )
17828   {
17829     if (CubitUndo::get_undo_enabled())
17830       CubitUndo::note_result_body(new_body);
17831 
17832     return CUBIT_SUCCESS;
17833   }
17834   else
17835   {
17836     if (CubitUndo::get_undo_enabled())
17837       CubitUndo::remove_last_undo();
17838 
17839     return CUBIT_FAILURE;
17840   }
17841 }
17842 CubitStatus GeometryModifyTool::loft_surfaces_to_body(DLIList<RefFace*> &surfaces,
17843                                                       DLIList<double> &takeoff_factor_list,
17844                                                       DLIList<RefFace*> &takeoff_vector_surface_list,
17845                                                       DLIList<CubitVector> &surface_takeoff_vector_list,
17846                                                       DLIList<RefEdge*> &takeoff_vector_curve_list,
17847                                                       DLIList<CubitVector> &curve_takeoff_vector_list,
17848                                                       DLIList<RefEdge*> &guides,
17849                                                       DLIList<RefVertex*> &match_vertices_list,
17850                                                       Body*& new_body,
17851                                                       CubitBoolean global_guides,
17852                                                       CubitBoolean closed,
17853                                                       CubitBoolean show_matching_curves,
17854                                                       CubitBoolean preview
17855                                                       )
17856 {
17857     DLIList<Surface*> loft_surfaces;
17858 
17859     // Get engine and correspoding geom entities
17860     GeometryModifyEngine* result_ptr;
17861     result_ptr = common_modify_engine( surfaces, loft_surfaces );
17862     if (!result_ptr)
17863     {
17864         PRINT_ERROR("Loft surfaces on volumes containing surfaces from different\n"
17865             "       geometry engines is not allowed.\n");
17866         return CUBIT_FAILURE;
17867     }
17868 
17869 
17870     DLIList<Curve*> loft_guide_curves;
17871     // Get engine and correspoding geom entities
17872     if(guides.size())
17873     {
17874       result_ptr = common_modify_engine( guides, loft_guide_curves );
17875       if (!result_ptr)
17876       {
17877         PRINT_ERROR("Loft guide curves containing curves from different\n"
17878           "       geometry engines is not allowed.\n");
17879         return CUBIT_FAILURE;
17880       }
17881     }
17882 
17883 
17884 
17885     DLIList<TBPoint*> loft_matched_points;
17886     // Get engine and correspoding geom entities
17887     if(match_vertices_list.size())
17888     {
17889       result_ptr = common_modify_engine( match_vertices_list, loft_matched_points );
17890       if (!result_ptr)
17891       {
17892         PRINT_ERROR("Loft matched vertices containing points from different\n"
17893           "       geometry engines is not allowed.\n");
17894         return CUBIT_FAILURE;
17895       }
17896     }
17897 
17898     DLIList<Surface*> loft_takeoff_surfaces;
17899 
17900     if(takeoff_vector_surface_list.size())
17901     {
17902       // Get engine and correspoding geom entities
17903       GeometryModifyEngine* result_ptr;
17904       result_ptr = common_modify_engine( takeoff_vector_surface_list, loft_takeoff_surfaces );
17905       if (!result_ptr)
17906       {
17907         PRINT_ERROR("Loft takeoff surfaces on volumes containing surfaces from different\n"
17908           "       geometry engines is not allowed.\n");
17909         return CUBIT_FAILURE;
17910       }
17911     }
17912 
17913     DLIList<Curve*> loft_takeoff_curves;
17914 
17915     if(takeoff_vector_curve_list.size())
17916     {
17917       // Get engine and correspoding geom entities
17918       GeometryModifyEngine* result_ptr;
17919       result_ptr = common_modify_engine( takeoff_vector_curve_list, loft_takeoff_curves );
17920       if (!result_ptr)
17921       {
17922         PRINT_ERROR("Loft takeoff surfaces on volumes containing surfaces from different\n"
17923           "       geometry engines is not allowed.\n");
17924         return CUBIT_FAILURE;
17925       }
17926     }
17927 
17928 
17929     BodySM* new_body_sm = 0;
17930 
17931     if( CubitUndo::get_undo_enabled() )
17932       CubitUndo::save_state();
17933 
17934     CubitStatus result = result_ptr->loft_surfaces_to_body(
17935         loft_surfaces,
17936         takeoff_factor_list,
17937         loft_takeoff_surfaces,
17938         surface_takeoff_vector_list,
17939         loft_takeoff_curves,
17940         curve_takeoff_vector_list,
17941         loft_guide_curves,
17942         loft_matched_points,
17943         new_body_sm,
17944         global_guides,
17945         closed,
17946         show_matching_curves,
17947         preview);
17948 
17949     if(result && new_body_sm)
17950     {
17951         new_body = GeometryQueryTool::instance()->make_Body(new_body_sm);
17952 
17953         if( CubitUndo::get_undo_enabled() )
17954           CubitUndo::note_result_body(new_body);
17955     }
17956     else
17957     {
17958       if( CubitUndo::get_undo_enabled() )
17959         CubitUndo::remove_last_undo();
17960     }
17961    return result;
17962 }
17963 
17964 
17965 //CubitStatus GeometryModifyTool::loft_surfaces_to_body( RefFace *face1, const double &takeoff1,
17966 //                                                      RefFace *face2, const double &takeoff2,
17967 //                                                      DLIList<RefEdge*> &guides,
17968 //                                                      Body*& new_body,
17969 //                                                      CubitBoolean arc_length_option, CubitBoolean twist_option,
17970 //                                                      CubitBoolean align_direction, CubitBoolean perpendicular,
17971 //                                                      CubitBoolean simplify_option)
17972 //{
17973 //
17974 //    DLIList<RefFace*> loft_faces;
17975 //    loft_faces.append(face1);
17976 //    loft_faces.append(face2);
17977 //    DLIList<Surface*> loft_surfaces;
17978 //
17979 //    // Get engine and correspoding geom entities
17980 //    GeometryModifyEngine* result_ptr;
17981 //    result_ptr = common_modify_engine( loft_faces, loft_surfaces );
17982 //    if (!result_ptr)
17983 //    {
17984 //        PRINT_ERROR("Loft surfaces on volumes containing surfaces from different\n"
17985 //            "       geometry engines is not allowed.\n");
17986 //        return CUBIT_FAILURE;
17987 //    }
17988 //
17989 //    if(2!=loft_surfaces.size())
17990 //        return CUBIT_FAILURE;
17991 //
17992 //
17993 //
17994 //    DLIList<Curve*> loft_curves;
17995 //
17996 //    // Get engine and correspoding geom entities
17997 //    result_ptr = common_modify_engine( guides, loft_curves );
17998 //    if (!result_ptr)
17999 //    {
18000 //        PRINT_ERROR("Loft surfaces on volumes containing surfaces from different\n"
18001 //            "       geometry engines is not allowed.\n");
18002 //        return CUBIT_FAILURE;
18003 //    }
18004 //
18005 //
18006 //    std::vector<Curve*> guide_edges;
18007 //    for(int i=0;i<loft_curves.size();i++)
18008 //    {
18009 //      guide_edges.push_back(loft_curves[i]);
18010 //    }
18011 //
18012 //
18013 //
18014 //
18015 //    loft_surfaces.reset();
18016 //    BodySM* new_body_sm = 0;
18017 //
18018 //    if( CubitUndo::get_undo_enabled() )
18019 //      CubitUndo::save_state();
18020 //
18021 //    CubitStatus result = result_ptr->loft_surfaces_to_body(
18022 //        loft_surfaces.get_and_step(),
18023 //        takeoff1,
18024 //        loft_surfaces.get_and_step(),
18025 //        takeoff2,
18026 //        guide_edges,
18027 //        new_body_sm,
18028 //        arc_length_option,
18029 //        twist_option,
18030 //        align_direction,
18031 //        perpendicular,
18032 //        simplify_option);
18033 //
18034 //    if(result && new_body_sm)
18035 //    {
18036 //        new_body = GeometryQueryTool::instance()->make_Body(new_body_sm);
18037 //
18038 //        if( CubitUndo::get_undo_enabled() )
18039 //          CubitUndo::note_result_body(new_body);
18040 //    }
18041 //    else
18042 //    {
18043 //      if( CubitUndo::get_undo_enabled() )
18044 //        CubitUndo::remove_last_undo();
18045 //    }
18046 //   return result;
18047 //}
18048 //
18049 //
18050 
18051 //CubitStatus GeometryModifyTool::loft_surfaces_to_body( RefFace *face1, const double &takeoff1,
18052 //                                                      RefFace *face2, const double &takeoff2,
18053 //                                                      Body*& new_body,
18054 //                                                      CubitBoolean arc_length_option, CubitBoolean twist_option,
18055 //                                                      CubitBoolean align_direction, CubitBoolean perpendicular,
18056 //                                                      CubitBoolean simplify_option)
18057 //{
18058 //
18059 //    DLIList<RefFace*> loft_faces;
18060 //    loft_faces.append(face1);
18061 //    loft_faces.append(face2);
18062 //    DLIList<Surface*> loft_surfaces;
18063 //
18064 //    // Get engine and correspoding geom entities
18065 //    GeometryModifyEngine* result_ptr;
18066 //    result_ptr = common_modify_engine( loft_faces, loft_surfaces );
18067 //    if (!result_ptr)
18068 //    {
18069 //        PRINT_ERROR("Loft surfaces on volumes containing surfaces from different\n"
18070 //            "       geometry engines is not allowed.\n");
18071 //        return CUBIT_FAILURE;
18072 //    }
18073 //
18074 //    if(2!=loft_surfaces.size())
18075 //        return CUBIT_FAILURE;
18076 //
18077 //    loft_surfaces.reset();
18078 //    BodySM* new_body_sm = 0;
18079 //
18080 //    if( CubitUndo::get_undo_enabled() )
18081 //      CubitUndo::save_state();
18082 //
18083 //
18084 //  CubitStatus result = result_ptr->loft_surfaces_to_body(
18085 //        loft_surfaces[0],
18086 //        takeoff1,
18087 //        loft_surfaces[1],
18088 //        takeoff2,
18089 //        new_body_sm,
18090 //        arc_length_option,
18091 //        twist_option,
18092 //        align_direction,
18093 //        perpendicular,
18094 //        simplify_option);
18095 //
18096 //
18097 //
18098 //    if(result && new_body_sm)
18099 //    {
18100 //        new_body = GeometryQueryTool::instance()->make_Body(new_body_sm);
18101 //
18102 //        if( CubitUndo::get_undo_enabled() )
18103 //          CubitUndo::note_result_body(new_body);
18104 //    }
18105 //    else
18106 //    {
18107 //      if( CubitUndo::get_undo_enabled() )
18108 //        CubitUndo::remove_last_undo();
18109 //    }
18110 //   return result;
18111 //}
18112 
18113 CubitStatus GeometryModifyTool::create_surface( DLIList<RefVertex*> &vert_list,
18114                                                 Body *&new_body, RefFace *on_surface )
18115 {
18116    //determine which vertices are free and which are not...
18117    //copy ones that are not
18118    vert_list.reset();
18119    DLIList<TBPoint*> points;
18120    GeometryModifyEngine *GMEPtr = get_engine( vert_list.get()->get_point_ptr() );
18121 
18122    DLIList<RefVertex*> free_ref_vertices;
18123    int i;
18124    for( i=vert_list.size(); i--; )
18125    {
18126      RefVertex *tmp_vert = vert_list.get_and_step();
18127 
18128      if( tmp_vert->num_parent_ref_entities() == 0 )
18129        free_ref_vertices.append( tmp_vert );
18130 
18131      TBPoint *tmp_point = tmp_vert->get_point_ptr();
18132      if( GMEPtr != get_engine( tmp_point ) )
18133      {
18134        PRINT_INFO("Vertices are not from same modeling engine.\n");
18135        return CUBIT_FAILURE;
18136      }
18137 
18138      if( tmp_vert->get_parents() == 0 )
18139      {
18140        points.append( tmp_point );
18141      }
18142      else
18143      {
18144        TBPoint *new_point = GMEPtr->make_Point( tmp_vert->coordinates() );
18145        points.append( new_point );
18146      }
18147    }
18148 
18149    if( on_surface )
18150    {
18151      if( GMEPtr != get_engine( on_surface->get_surface_ptr() ) )
18152      {
18153        PRINT_INFO("Surface and Vertices are not from same modeling engine.\n");
18154        return CUBIT_FAILURE;
18155      }
18156    }
18157 
18158    if(CubitUndo::get_undo_enabled())
18159    {
18160      if( free_ref_vertices.size() )
18161        CubitUndo::save_state_with_cubit_file( free_ref_vertices );
18162      else
18163        CubitUndo::save_state();
18164    }
18165 
18166 
18167    BodySM* body_sm = NULL;
18168    Surface *on_surf = NULL;
18169 
18170    if( on_surface )
18171      on_surf = on_surface->get_surface_ptr();
18172 
18173    CubitStatus stat = GMEPtr->create_surface( points, body_sm, on_surf );
18174 
18175    if( stat == CUBIT_FAILURE )
18176    {
18177      if (CubitUndo::get_undo_enabled())
18178        CubitUndo::remove_last_undo();
18179      return stat;
18180    }
18181 
18182    if( body_sm )
18183      new_body = GeometryQueryTool::instance()->make_Body(body_sm);
18184 
18185    if (new_body)
18186    {
18187      if (CubitUndo::get_undo_enabled())
18188        CubitUndo::note_result_body(new_body);
18189 
18190      stat = CUBIT_SUCCESS;
18191    }
18192    else
18193    {
18194      if (CubitUndo::get_undo_enabled())
18195        CubitUndo::remove_last_undo();
18196 
18197      stat = CUBIT_FAILURE;
18198    }
18199 
18200    for( i=free_ref_vertices.size(); i--; )
18201    {
18202      RefVertex *free_vertex = free_ref_vertices.get_and_step();
18203      AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOP_LEVEL_ENTITY_DESTRUCTED, free_vertex));
18204      CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, free_vertex );
18205      GeometryQueryTool::instance()->history().add_event(evt);
18206    }
18207 
18208    return stat;
18209 }
18210 
18211 CubitStatus GeometryModifyTool::create_surface( DLIList<CubitVector*>& vec_list,
18212                                                 Body *&new_body,
18213                                                 RefFace *ref_face_ptr,
18214                                                 CubitBoolean project_points )
18215 {
18216    GeometryModifyEngine* GMEPtr = gmeList.get();
18217    if( ref_face_ptr )
18218    {
18219      if( GMEPtr != get_engine(ref_face_ptr) )
18220      {
18221        PRINT_ERROR("Geometry engine of Surface %d is not the active geometry engine.\n", ref_face_ptr->id() );
18222        PRINT_INFO("      Use command \"Set Geometry Engine ...\" to set to correct engine.\n");
18223        return CUBIT_FAILURE;
18224      }
18225    }
18226    BodySM* body_sm = NULL;
18227    Surface *project_to_surface = NULL;
18228    if( ref_face_ptr )
18229      project_to_surface = ref_face_ptr->get_surface_ptr();
18230    CubitStatus stat = GMEPtr->create_surface( vec_list, body_sm, project_to_surface, project_points );
18231 
18232    if( stat == CUBIT_FAILURE )
18233      return stat;
18234 
18235    if (CubitUndo::get_undo_enabled())
18236      CubitUndo::save_state();
18237 
18238    if( body_sm )
18239      new_body = GeometryQueryTool::instance()->make_Body(body_sm);
18240 
18241    if (new_body)
18242    {
18243      if (CubitUndo::get_undo_enabled())
18244        CubitUndo::note_result_body(new_body);
18245 
18246      stat = CUBIT_SUCCESS;
18247    }
18248    else
18249    {
18250      if (CubitUndo::get_undo_enabled())
18251        CubitUndo::remove_last_undo();
18252 
18253      stat = CUBIT_FAILURE;
18254    }
18255    return stat;
18256 }
18257 
18258 CubitStatus GeometryModifyTool::create_weld_surface( CubitVector &root,
18259                                                     RefFace *ref_face1,
18260                                                     double leg1,
18261                                                     RefFace *ref_face2,
18262                                                     double leg2,
18263                                                     Body *&new_body )
18264 {
18265     GeometryModifyEngine* GMEPtr;
18266     DLIList<RefFace*> ref_faces;
18267     ref_faces.append(ref_face1);
18268     ref_faces.append(ref_face2);
18269     DLIList<Surface*> surfaces;
18270 
18271     GMEPtr = common_modify_engine(ref_faces, surfaces);
18272     if (!GMEPtr)
18273     {
18274         PRINT_ERROR("Loft surfaces on volumes containing surfaces from different\n"
18275             "       geometry engines is not allowed.\n");
18276         return CUBIT_FAILURE;
18277     }
18278 
18279     if (CubitUndo::get_undo_enabled())
18280       CubitUndo::save_state();
18281 
18282     surfaces.reset();
18283     BodySM* new_body_sm = 0;
18284     CubitStatus result = GMEPtr->create_weld_surface(
18285         root,
18286         surfaces.get_and_step(),
18287         leg1,
18288         surfaces.get_and_step(),
18289         leg2,
18290         new_body_sm );
18291 
18292     if(result && new_body_sm)
18293     {
18294         new_body = GeometryQueryTool::instance()->make_Body(new_body_sm);
18295         if (new_body)
18296         {
18297           if (CubitUndo::get_undo_enabled())
18298             CubitUndo::note_result_body(new_body);
18299         }
18300         else
18301         {
18302           if (CubitUndo::get_undo_enabled())
18303             CubitUndo::remove_last_undo();
18304         }
18305     }
18306     return result;
18307 }
18308 //end of surface tool operations ******************************************************
18309 
18310 //-------------------------------------------------------------------------
18311 // Purpose       : Remove entity names from dead entities.
18312 //
18313 // Special Notes :
18314 //
18315 // Creator       : Jason Kraftcheck
18316 //
18317 // Creation Date : 12/08/03
18318 //-------------------------------------------------------------------------
18319 void GeometryModifyTool::remove_dead_entity_names( RefEntity* entity ) const
18320 {
18321   TopologyEntity* topo_ent = dynamic_cast<TopologyEntity*>(entity);
18322   if (topo_ent->bridge_manager()->topology_bridge() == NULL)
18323     RefEntityName::instance()->remove_refentity_name( entity, CUBIT_TRUE );
18324 
18325   DLIList<RefEntity*> children;
18326   entity->get_child_ref_entities(children);
18327   children.last();
18328   for (int i = children.size(); i--; )
18329   {
18330     //PRINT_INFO("Removing dead entity on %s %d\n", children.get()->class_name(), children.get()->id() );
18331     remove_dead_entity_names( children.step_and_get() );
18332   }
18333 }
18334 
18335 //-------------------------------------------------------------------------
18336 // Purpose       : Destroy or update modified body, as appropriate.
18337 //
18338 // Special Notes :
18339 //
18340 // Creator       : Jason Kraftcheck
18341 //
18342 // Creation Date : 12/08/03
18343 //-------------------------------------------------------------------------
18344 Body* GeometryModifyTool::update_body( Body* body ) const
18345 {
18346   BodySM* body_sm = body->get_body_sm_ptr();
18347   if (body_sm)
18348     return GeometryQueryTool::instance()->make_Body(body_sm);
18349 
18350   GeometryQueryTool::instance()->destroy_dead_entity(body);
18351   return 0;
18352 }
18353 
18354 CubitStatus GeometryModifyTool::tolerant_imprint( DLIList<RefFace*> &ref_faces,
18355                                                   DLIList<RefEdge*> &ref_edge_list,
18356                                                   DLIList<Body*> &new_bodies,
18357                                                   bool merge )
18358 {
18359   if( ref_faces.size() > 2 )
18360     return CUBIT_FAILURE;
18361 
18362   ref_faces.reset();
18363   RefFace *face1 = ref_faces.get_and_step();
18364   RefFace *face2 = ref_faces.get_and_step();
18365 
18366   if(ref_edge_list.size() > 0)
18367   {
18368     //collect all the bodies containing any edge on these 2 surfaces
18369     //so you can merge them afterward
18370     DLIList<Body*> bodies_to_merge;
18371     if( merge )
18372     {
18373       DLIList<RefEdge*> tmp_edges;
18374       face1->ref_edges( tmp_edges);
18375 
18376       int j;
18377       for( j=tmp_edges.size(); j--; )
18378       {
18379         RefEdge *tmp_edge = tmp_edges.get_and_step();
18380         DLIList<Body*> body_list;
18381         tmp_edge->bodies( body_list );
18382         bodies_to_merge += body_list;
18383       }
18384 
18385       for( j=ref_edge_list.size(); j--; )
18386       {
18387         RefEdge *tmp_edge = ref_edge_list.get_and_step();
18388         DLIList<Body*> body_list;
18389         tmp_edge->bodies( body_list );
18390         bodies_to_merge += body_list;
18391       }
18392 
18393       tmp_edges.clean_out();
18394       face2->ref_edges( tmp_edges );
18395 
18396       for( j=tmp_edges.size(); j--; )
18397       {
18398         RefEdge *tmp_edge = tmp_edges.get_and_step();
18399         DLIList<Body*> body_list;
18400         tmp_edge->bodies( body_list );
18401         bodies_to_merge += body_list;
18402       }
18403       bodies_to_merge.uniquify_ordered();
18404     }
18405 
18406     DLIList<RefEdge*> edges_to_imprint_onto_face1;
18407     DLIList<RefEdge*> edges_to_imprint_onto_face2;
18408 
18409     //sort edges...
18410     //edges on face1 and not on face2 will be imprinted on face2
18411     //edges on face2 and not on face1 will be imprinted on face1
18412     int i;
18413     for(i=ref_edge_list.size(); i--; )
18414     {
18415       RefEdge *tmp_edge = ref_edge_list.get_and_step();
18416       DLIList<RefFace*> tmp_faces;
18417       tmp_edge->ref_faces( tmp_faces );
18418 
18419       if( tmp_faces.move_to( face1 ) && !tmp_faces.move_to( face2 ) )
18420         edges_to_imprint_onto_face2.append( tmp_edge );
18421       else if( tmp_faces.move_to( face2 ) && !tmp_faces.move_to( face1 ) )
18422         edges_to_imprint_onto_face1.append( tmp_edge );
18423       else
18424         PRINT_ERROR("Will not imprint curve %d onto either surface.\n", tmp_edge->id() );
18425     }
18426 
18427     //if there are edges to impint onto both surfaces
18428     if( edges_to_imprint_onto_face1.size() &&
18429         edges_to_imprint_onto_face2.size() )
18430     {
18431       //get the modify engine
18432       DLIList<Surface*> surf_list( 1 );
18433       DLIList<Curve*> curve_list( edges_to_imprint_onto_face2.size() );
18434       DLIList<RefFace*> ref_face_list( 1 );
18435       ref_face_list.append( face2 );
18436       GeometryModifyEngine* gme = common_modify_engine( ref_face_list,
18437                                                         edges_to_imprint_onto_face2,
18438                                                         surf_list,
18439                                                         curve_list );
18440       if ( !gme )
18441       {
18442         PRINT_ERROR("Performing IMPRINT with entities containing geometry from\n"
18443                     "different modeling engines is not allowed.\n" );
18444         return CUBIT_FAILURE;
18445       }
18446 
18447       //copy the specified boundary curves of face1 to imprint onto face2...
18448       //these could be stale after we imprint face1
18449       DLIList<Curve*> copied_curves;
18450       for(i=curve_list.size(); i--; )
18451       {
18452         Curve *copied_curve = gme->make_Curve( curve_list.get_and_step() );
18453         copied_curves.append( copied_curve );
18454       }
18455 
18456     if( CubitUndo::get_undo_enabled() )
18457       CubitUndo::save_state_with_cubit_file( ref_faces );
18458 
18459       //do the imprint onto face1
18460       Body *new_body = NULL;
18461       CubitStatus status;
18462       status = tolerant_imprint( face1, edges_to_imprint_onto_face1, new_body );
18463 
18464       //if we failed...get out
18465       if( status == CUBIT_FAILURE )
18466       {
18467         //delete the copied curves
18468         for( i=copied_curves.size(); i--; )
18469           gme->get_gqe()->delete_solid_model_entities( copied_curves.get_and_step() );
18470 
18471         if( CubitUndo::get_undo_enabled() )
18472           CubitUndo::remove_last_undo();
18473 
18474         return CUBIT_FAILURE;
18475       }
18476 
18477       DLIList<Body*> original_body_list;
18478       face2->bodies( original_body_list );
18479 
18480       //get the Surface* ptr
18481       Surface *surface2 = face2->get_surface_ptr();
18482 
18483       DLIList<BodySM*> body_sm_list;
18484       for(i=original_body_list.size(); i--;)
18485         body_sm_list.append(original_body_list.get_and_step()->get_body_sm_ptr());
18486 
18487       int process_composites = 0;
18488       if(contains_composites(original_body_list))
18489         process_composites = 1;
18490 
18491       if(process_composites)
18492       {
18493         // Push virtual attributes down to solid model topology before
18494         // doing the imprint.
18495         do_attribute_setup();
18496         push_attributes_before_modify(body_sm_list);
18497         // This must be done after pushing the vg atts because it uses them.
18498         push_imprint_attributes_before_modify(body_sm_list);
18499       }
18500 
18501       //do the imprint onto face2
18502       BodySM *new_bodysm = NULL;
18503       DLIList<TopologyBridge*> temporary_bridges;
18504       status = gme->tolerant_imprint_surface_with_curves( surface2, copied_curves, temporary_bridges, new_bodysm);
18505       temporary_bridges.uniquify_ordered();
18506       while(temporary_bridges.size())
18507       {
18508         TopologyBridge* bridge = temporary_bridges.pop();
18509         bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
18510       }
18511 
18512       DLIList<BodySM*> new_body_list;
18513       if(new_bodysm)
18514         new_body_list.append(new_bodysm);
18515 
18516 
18517       //delete the copied curves
18518       for( i=copied_curves.size(); i--; )
18519         gme->get_gqe()->delete_solid_model_entities( copied_curves.get_and_step() );
18520 
18521       if( status == CUBIT_FAILURE )
18522       {
18523         if( CubitUndo::get_undo_enabled() )
18524           CubitUndo::remove_last_undo();
18525 
18526         if(process_composites)
18527         {
18528           remove_pushed_attributes(new_body_list, original_body_list);
18529           do_attribute_cleanup();
18530         }
18531 
18532         return CUBIT_FAILURE;
18533       }
18534       else
18535       {
18536         if(process_composites)
18537         {
18538           // Analyze the results and adjust virtual attributes as necessary.
18539         DLIList<TopologyBridge*> tb_list;
18540         CAST_LIST(new_body_list, tb_list, TopologyBridge);
18541           GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, original_body_list);
18542 
18543           // Clean up attributes.
18544           remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
18545 
18546           // Restore the virtual geometry.
18547           restore_vg_after_modify(new_body_list, original_body_list, gme);
18548           remove_pushed_attributes(new_body_list, original_body_list);
18549         }
18550       }
18551 
18552       DLIList<BodySM*> new_bodies;
18553       new_bodies.append( new_bodysm );
18554       DLIList<Body*> result_bodies;
18555       status = finish_sm_op( original_body_list, new_bodies, result_bodies );
18556 
18557       if(process_composites)
18558         do_attribute_cleanup();
18559 
18560       if( status == CUBIT_FAILURE )
18561       {
18562         if( CubitUndo::get_undo_enabled() )
18563           CubitUndo::remove_last_undo();
18564         return CUBIT_FAILURE;
18565       }
18566     }
18567     //user specified edges that will only imprint onto face1...do it anyway
18568     else if( edges_to_imprint_onto_face1.size() )
18569     {
18570       if( CubitUndo::get_undo_enabled() )
18571       {
18572         DLIList<RefFace*> tmp_faces(1);
18573         tmp_faces.append( face1 );
18574         CubitUndo::save_state_with_cubit_file( tmp_faces );
18575       }
18576 
18577       bool undo_enabled = CubitUndo::get_undo_enabled();
18578       CubitUndo::set_undo_enabled( false );
18579 
18580       Body *new_body = NULL;
18581       CubitStatus stat = tolerant_imprint( face1, edges_to_imprint_onto_face1,
18582                                           new_body, merge );
18583 
18584     if( undo_enabled )
18585       CubitUndo::set_undo_enabled( true );
18586 
18587     if( CubitUndo::get_undo_enabled() )
18588     {
18589       if( stat == CUBIT_FAILURE )
18590         CubitUndo::remove_last_undo();
18591     }
18592 
18593       return stat;
18594     }
18595     //user specified edges that will only imprint onto face2...do it anyway
18596     else if( edges_to_imprint_onto_face2.size() )
18597     {
18598       if( CubitUndo::get_undo_enabled() )
18599       {
18600         DLIList<RefFace*> tmp_faces(1);
18601         tmp_faces.append( face2 );
18602         CubitUndo::save_state_with_cubit_file( tmp_faces );
18603       }
18604 
18605       bool undo_enabled = CubitUndo::get_undo_enabled();
18606       CubitUndo::set_undo_enabled( false );
18607 
18608       Body *new_body = NULL;
18609       CubitStatus stat = tolerant_imprint( face2, edges_to_imprint_onto_face2,
18610                                           new_body, merge );
18611 
18612       if( undo_enabled )
18613         CubitUndo::set_undo_enabled( true );
18614 
18615       if( CubitUndo::get_undo_enabled() )
18616       {
18617         if( stat == CUBIT_FAILURE )
18618           CubitUndo::remove_last_undo();
18619       }
18620 
18621       return stat;
18622     }
18623 
18624     if( merge )
18625       MergeTool::instance()->merge_bodies( bodies_to_merge );
18626   }
18627   else
18628   {
18629     DLIList<RefFace*> faces_not_to_merge;
18630     Body *body1 = face1->body();
18631     Body *body2 = face2->body();
18632 
18633     if(merge)
18634     {
18635       DLIList<RefFace*> tmp_faces;
18636       body1->ref_faces(tmp_faces);
18637       if(tmp_faces.move_to(face1))
18638         tmp_faces.extract();
18639       faces_not_to_merge = tmp_faces;
18640 
18641       tmp_faces.clean_out();
18642       body2->ref_faces(tmp_faces);
18643       if(tmp_faces.move_to(face2))
18644         tmp_faces.extract();
18645       faces_not_to_merge += tmp_faces;
18646     }
18647 
18648     //get the modify engine
18649     DLIList<Surface*> surf_list( 1 );
18650     DLIList<RefFace*> ref_face_list( 2 );
18651     ref_face_list.append( face1 );
18652     ref_face_list.append( face2 );
18653     GeometryModifyEngine* gme = common_modify_engine( ref_face_list, surf_list);
18654 
18655     if ( !gme )
18656     {
18657       PRINT_ERROR("Performing IMPRINT with entities containing geometry from\n"
18658                   "different modeling engines is not allowed.\n" );
18659       return CUBIT_FAILURE;
18660     }
18661 
18662     if( CubitUndo::get_undo_enabled() )
18663       CubitUndo::save_state_with_cubit_file( ref_faces );
18664 
18665     //do the imprint onto face1
18666     DLIList<BodySM*> new_bodysm_list;
18667     CubitStatus status = gme->tolerant_imprint(surf_list, new_bodysm_list);
18668 
18669     //if we failed...get out
18670     if( status == CUBIT_FAILURE )
18671     {
18672       if( CubitUndo::get_undo_enabled() )
18673         CubitUndo::remove_last_undo();
18674 
18675       return CUBIT_FAILURE;
18676     }
18677 
18678     DLIList<Body*> result_bodies;
18679     DLIList<Body*> original_body_list;
18680     original_body_list.append(body1);
18681     original_body_list.append(body2);
18682     status = finish_sm_op( original_body_list, new_bodysm_list, result_bodies );
18683 
18684 
18685     if( merge )
18686     {
18687       DLIList<RefFace*> faces_to_merge, tmp_faces;
18688       body1->ref_faces(faces_to_merge);
18689       body2->ref_faces(tmp_faces);
18690       faces_to_merge += tmp_faces;
18691       faces_to_merge -= faces_not_to_merge;
18692       if(faces_to_merge.size() > 1)
18693       {
18694         MergeTool::instance()->merge_reffaces(faces_to_merge);
18695       }
18696     }
18697   }
18698 
18699   return CUBIT_SUCCESS;
18700 }
18701 
18702 
18703 CubitStatus GeometryModifyTool::tolerant_imprint( RefFace *ref_face,
18704                                                   DLIList<RefEdge*> &ref_edge_list,
18705                                                   Body *&new_body,
18706                                                   bool merge )
18707 {
18708   int i;
18709   DLIList<Body*> bodies_to_merge;
18710   DLIList<Body*> blank_bodies;
18711   
18712   DLIList<RefEdge*> tmp_edges;
18713   ref_face->ref_edges( tmp_edges );
18714 
18715   for( i=tmp_edges.size(); i--; )
18716   {
18717     RefEdge *tmp_edge = tmp_edges.get_and_step();
18718     DLIList<Body*> body_list;
18719     tmp_edge->bodies( body_list );    
18720     blank_bodies += body_list;
18721   }
18722 
18723   if( merge )
18724   {
18725     bodies_to_merge += blank_bodies;
18726   
18727     for( i=ref_edge_list.size(); i--; )
18728     {
18729       RefEdge *tmp_edge = ref_edge_list.get_and_step();
18730       DLIList<Body*> body_list;
18731       tmp_edge->bodies( body_list );
18732       bodies_to_merge += body_list;
18733     }
18734 
18735     bodies_to_merge.uniquify_ordered();
18736   }  
18737 
18738   DLIList<Body*> original_body_list;
18739   ref_face->bodies( original_body_list );
18740 
18741   DLIList<Surface*> surf_list( 1 );
18742   DLIList<Curve*> curve_list(ref_edge_list.size());
18743   DLIList<RefFace*> ref_face_list( 1 );
18744   ref_face_list.append( ref_face );
18745 
18746   //prohibit imprinting on partition bodies
18747   for( int k=0; k<blank_bodies.size(); k++ )  
18748   {
18749     if( NULL == get_engine( blank_bodies[k]->bridge_manager()->topology_bridge() ) )
18750     {
18751        PRINT_ERROR("Performing IMPRINT on entities with partitions\n"
18752                    "       is not allowed.\n" );
18753        return CUBIT_FAILURE;
18754     }
18755   } 
18756 
18757   GeometryModifyEngine* gme = common_modify_engine( ref_face_list,
18758                                                     ref_edge_list,
18759                                                     surf_list,
18760                                                     curve_list,
18761                                                     true);
18762   if ( !gme )
18763   {
18764     PRINT_ERROR("Performing IMPRINT with entities containing geometry from\n"
18765                 "different modeling engines is not allowed.\n" );
18766     return CUBIT_FAILURE;
18767   }
18768 
18769 
18770   if( CubitUndo::get_undo_enabled() )
18771   {
18772     DLIList<RefFace*> ref_faces(1);
18773     ref_faces.append( ref_face );
18774     CubitUndo::save_state_with_cubit_file( ref_faces );
18775   }
18776 
18777   DLIList<BodySM*> body_sm_list;
18778   for(i=original_body_list.size(); i--;)
18779     body_sm_list.append(original_body_list.get_and_step()->get_body_sm_ptr());
18780 
18781   int process_composites = 0;
18782   if(contains_composites(original_body_list))
18783     process_composites = 1;
18784 
18785   DLIList<TopologyBridge*> tb_list;
18786   if(process_composites)
18787   {
18788     // Turn certain attributes on.
18789     do_attribute_setup();
18790     // Push virtual attributes down to solid model topology before
18791     // doing the imprint.
18792     push_attributes_before_modify(body_sm_list);
18793     DLIList<TopologyBridge*> tmp_tb_list;
18794     CAST_LIST(surf_list, tmp_tb_list, TopologyBridge);
18795     // Put "ORIGINAL" attributes on the bodies being imprinted and
18796     // the curves as these originally existed.
18797     push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
18798     CAST_LIST(curve_list, tb_list, TopologyBridge);
18799     push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
18800     push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
18801   }
18802 
18803   CubitStatus status = CUBIT_FAILURE;
18804   DLIList<BodySM*> new_body_list;
18805   // The bridges doing the imprinting often get split during the process but
18806   // because of the way we are making copies, the IMPRINTER attribute doesn't
18807   // get propagated to them.  temporary_bridges will be filled in with any
18808   // additional IMPRINTER bridges we need to consider below when deciding whether to
18809   // keep composite attributes.
18810   DLIList<TopologyBridge*> temporary_bridges;
18811   for(i=surf_list.size(); i>0; i--)
18812   {
18813     Surface *cur_surf = surf_list.get_and_step();
18814     BodySM *new_body_sm = NULL;
18815     CubitStatus tmp_status = gme->tolerant_imprint_surface_with_curves(
18816                                                 cur_surf, curve_list,
18817                                                 temporary_bridges,
18818                                                 new_body_sm);
18819     if(new_body_sm)
18820       new_body_list.append(new_body_sm);
18821     if(tmp_status == CUBIT_SUCCESS)
18822       status = tmp_status;
18823   }
18824 
18825   temporary_bridges.uniquify_ordered();
18826 
18827   if( status == CUBIT_FAILURE )
18828   {
18829     if( CubitUndo::get_undo_enabled() )
18830       CubitUndo::remove_last_undo();
18831 
18832     if(process_composites)
18833     {
18834       remove_pushed_attributes(new_body_list, original_body_list);
18835       do_attribute_cleanup();
18836     }
18837 
18838     while(temporary_bridges.size())
18839     {
18840       TopologyBridge* bridge = temporary_bridges.pop();
18841       bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
18842     }
18843 
18844     return CUBIT_FAILURE;
18845   }
18846   else
18847   {
18848     if(process_composites)
18849     {
18850       // Analyze the results and adjust virtual attributes as necessary.
18851       DLIList<TopologyBridge*> tmp_tb_list;
18852       CAST_LIST(new_body_list, tmp_tb_list, TopologyBridge);
18853       tb_list.merge_unique(tmp_tb_list);
18854       // The bridges coming back in temporary_bridges may not have IMPRINTER
18855       // attributes on them becuase of the way they were generated below.  Make
18856       // sure they get IMPRINTER attributes.
18857       push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
18858       tb_list += temporary_bridges;
18859       GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, original_body_list);
18860 
18861 
18862       // Clean up attributes.
18863       remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
18864 
18865       // Restore the virtual geometry.
18866       restore_vg_after_modify(new_body_list, original_body_list, gme);
18867       remove_pushed_attributes(new_body_list, original_body_list);
18868     }
18869   }
18870   // cleanup temp bridges
18871   while(temporary_bridges.size())
18872   {
18873     TopologyBridge* bridge = temporary_bridges.pop();
18874     bridge->get_geometry_query_engine()->delete_topology_bridge(bridge);
18875   }
18876 
18877   DLIList<Body*> result_bodies;
18878   status = finish_sm_op( original_body_list, new_body_list, result_bodies );
18879 
18880   if(process_composites)
18881     do_attribute_cleanup();
18882 
18883   if( status == CUBIT_FAILURE )
18884   {
18885     if( CubitUndo::get_undo_enabled() )
18886       CubitUndo::remove_last_undo();
18887     return CUBIT_FAILURE;
18888   }
18889 
18890   if( merge )
18891     MergeTool::instance()->merge_bodies( bodies_to_merge );
18892 
18893   if( result_bodies.size() == 1 )
18894     new_body = result_bodies.get();
18895   else
18896     return CUBIT_FAILURE;
18897 
18898   return status;
18899 }
18900 
18901 CubitStatus GeometryModifyTool::unmerge_and_return_merge_partners(RefEdge *input_curve,
18902                                                                   DLIList<DLIList<RefEdge*>*> &curve_merge_lists,
18903                                                                   DLIList<DLIList<RefFace*>*> &surf_merge_lists)
18904 {
18905   if(!input_curve->is_merged())
18906     return CUBIT_FAILURE;
18907 
18908   DLIList<RefFace*> vert_surfs;
18909   input_curve->start_vertex()->ref_faces(vert_surfs);
18910   input_curve->end_vertex()->ref_faces(vert_surfs);
18911   vert_surfs.uniquify_unordered();
18912   for(int i=vert_surfs.size(); i>0; i--)
18913   {
18914     RefFace *cur_surf = vert_surfs.get_and_step();
18915     if(cur_surf->is_merged())
18916     {
18917       DLIList<RefVolume*> surf_vols;
18918       DLIList<RefFace*> all_surfs_on_both_vols;
18919       cur_surf->ref_volumes(surf_vols);
18920       for(int j=surf_vols.size(); j>0; j--)
18921       {
18922         RefVolume *cur_vol = surf_vols.get_and_step();
18923         cur_vol->ref_faces(all_surfs_on_both_vols);
18924       }
18925       all_surfs_on_both_vols.uniquify_unordered();
18926       DLIList<RefFace*> all_surfs_on_both_vols_after_unmerge;
18927       OldUnmergeCode::instance().unmerge(cur_surf, false);
18928       for(int j=surf_vols.size(); j>0; j--)
18929       {
18930         RefVolume *cur_vol = surf_vols.get_and_step();
18931         cur_vol->ref_faces(all_surfs_on_both_vols_after_unmerge);
18932       }
18933       all_surfs_on_both_vols_after_unmerge.uniquify_unordered();
18934       all_surfs_on_both_vols_after_unmerge -= all_surfs_on_both_vols;
18935       if(all_surfs_on_both_vols_after_unmerge.size() != 1)
18936         return CUBIT_FAILURE;
18937       all_surfs_on_both_vols_after_unmerge.append(cur_surf);
18938       DLIList<RefFace*> *new_list = new DLIList<RefFace*>();
18939       for(int r=all_surfs_on_both_vols_after_unmerge.size(); r>0; r--)
18940       {
18941         RefFace *cur_surf = all_surfs_on_both_vols_after_unmerge.get_and_step();
18942         new_list->append(cur_surf);
18943       }
18944       surf_merge_lists.append(new_list);
18945     }
18946   }
18947   DLIList<RefEdge*> vert_curves;
18948   input_curve->start_vertex()->ref_edges(vert_curves);
18949   input_curve->end_vertex()->ref_edges(vert_curves);
18950   vert_curves.uniquify_unordered();
18951   for(int i=vert_curves.size(); i>0; i--)
18952   {
18953     RefEdge *cur_curve = vert_curves.get_and_step();
18954     if(cur_curve->is_merged())
18955     {
18956       DLIList<RefFace*> curve_surfs;
18957       DLIList<RefEdge*> all_curves_on_all_surfs;
18958       cur_curve->ref_faces(curve_surfs);
18959       for(int j=curve_surfs.size(); j>0; j--)
18960       {
18961         RefFace *cur_surf = curve_surfs.get_and_step();
18962         cur_surf->ref_edges(all_curves_on_all_surfs);
18963       }
18964       all_curves_on_all_surfs.uniquify_unordered();
18965       DLIList<RefEdge*> all_curves_on_all_surfs_after_unmerge;
18966       OldUnmergeCode::instance().unmerge(cur_curve, true);
18967       for(int j=curve_surfs.size(); j>0; j--)
18968       {
18969         RefFace *cur_surf = curve_surfs.get_and_step();
18970         cur_surf->ref_edges(all_curves_on_all_surfs_after_unmerge);
18971       }
18972       all_curves_on_all_surfs_after_unmerge.uniquify_unordered();
18973       all_curves_on_all_surfs_after_unmerge -= all_curves_on_all_surfs;
18974       if(all_curves_on_all_surfs_after_unmerge.size() < 1)
18975         return CUBIT_FAILURE;
18976       all_curves_on_all_surfs_after_unmerge.append_unique(cur_curve);
18977       DLIList<RefEdge*> *new_list = new DLIList<RefEdge*>();
18978       for(int r=all_curves_on_all_surfs_after_unmerge.size(); r>0; r--)
18979       {
18980         RefEdge *cur_edge = all_curves_on_all_surfs_after_unmerge.get_and_step();
18981         new_list->append(cur_edge);
18982       }
18983       curve_merge_lists.append(new_list);
18984     }
18985   }
18986   return CUBIT_SUCCESS;
18987 }
18988 
18989 CubitStatus GeometryModifyTool::unmerge_and_return_merge_partners(RefVertex *input_vertex,
18990                                                                   DLIList<DLIList<RefVertex*>*> &vert_merge_lists,
18991                                                                   DLIList<DLIList<RefEdge*>*> &curve_merge_lists,
18992                                                                   DLIList<DLIList<RefFace*>*> &surf_merge_lists)
18993 {
18994   if(!input_vertex->is_merged())
18995     return CUBIT_FAILURE;
18996 
18997   DLIList<RefFace*> vert_surfs;
18998   input_vertex->ref_faces(vert_surfs);
18999   for(int i=vert_surfs.size(); i>0; i--)
19000   {
19001     RefFace *cur_surf = vert_surfs.get_and_step();
19002     if(cur_surf->is_merged())
19003     {
19004       DLIList<RefVolume*> surf_vols;
19005       DLIList<RefFace*> all_surfs_on_both_vols;
19006       cur_surf->ref_volumes(surf_vols);
19007       for(int j=surf_vols.size(); j>0; j--)
19008       {
19009         RefVolume *cur_vol = surf_vols.get_and_step();
19010         cur_vol->ref_faces(all_surfs_on_both_vols);
19011       }
19012       all_surfs_on_both_vols.uniquify_unordered();
19013       DLIList<RefFace*> all_surfs_on_both_vols_after_unmerge;
19014       OldUnmergeCode::instance().unmerge(cur_surf, false);
19015       for(int j=surf_vols.size(); j>0; j--)
19016       {
19017         RefVolume *cur_vol = surf_vols.get_and_step();
19018         cur_vol->ref_faces(all_surfs_on_both_vols_after_unmerge);
19019       }
19020       all_surfs_on_both_vols_after_unmerge.uniquify_unordered();
19021       all_surfs_on_both_vols_after_unmerge -= all_surfs_on_both_vols;
19022       if(all_surfs_on_both_vols_after_unmerge.size() != 1)
19023         return CUBIT_FAILURE;
19024       all_surfs_on_both_vols_after_unmerge.append(cur_surf);
19025       DLIList<RefFace*> *new_list = new DLIList<RefFace*>();
19026       for(int r=all_surfs_on_both_vols_after_unmerge.size(); r>0; r--)
19027       {
19028         RefFace *cur_surf = all_surfs_on_both_vols_after_unmerge.get_and_step();
19029         new_list->append(cur_surf);
19030       }
19031       surf_merge_lists.append(new_list);
19032     }
19033   }
19034   DLIList<RefEdge*> vert_curves;
19035   input_vertex->ref_edges(vert_curves);
19036   for(int i=vert_curves.size(); i>0; i--)
19037   {
19038     RefEdge *cur_curve = vert_curves.get_and_step();
19039     if(cur_curve->is_merged())
19040     {
19041       DLIList<RefFace*> curve_surfs;
19042       DLIList<RefEdge*> all_curves_on_all_surfs;
19043       cur_curve->ref_faces(curve_surfs);
19044       for(int j=curve_surfs.size(); j>0; j--)
19045       {
19046         RefFace *cur_surf = curve_surfs.get_and_step();
19047         cur_surf->ref_edges(all_curves_on_all_surfs);
19048       }
19049       all_curves_on_all_surfs.uniquify_unordered();
19050       DLIList<RefEdge*> all_curves_on_all_surfs_after_unmerge;
19051       OldUnmergeCode::instance().unmerge(cur_curve, false);
19052       for(int j=curve_surfs.size(); j>0; j--)
19053       {
19054         RefFace *cur_surf = curve_surfs.get_and_step();
19055         cur_surf->ref_edges(all_curves_on_all_surfs_after_unmerge);
19056       }
19057       all_curves_on_all_surfs_after_unmerge.uniquify_unordered();
19058       all_curves_on_all_surfs_after_unmerge -= all_curves_on_all_surfs;
19059       if(all_curves_on_all_surfs_after_unmerge.size() < 1)
19060         return CUBIT_FAILURE;
19061       all_curves_on_all_surfs_after_unmerge.append_unique(cur_curve);
19062       DLIList<RefEdge*> *new_list = new DLIList<RefEdge*>();
19063       for(int r=all_curves_on_all_surfs_after_unmerge.size(); r>0; r--)
19064       {
19065         RefEdge *cur_edge = all_curves_on_all_surfs_after_unmerge.get_and_step();
19066         new_list->append(cur_edge);
19067       }
19068       curve_merge_lists.append(new_list);
19069     }
19070   }
19071   vert_curves.clean_out();
19072   input_vertex->ref_edges(vert_curves);
19073   DLIList<RefVertex*> curve_verts;
19074   for(int i=vert_curves.size(); i>0; i--)
19075   {
19076     RefEdge *cur_curve = vert_curves.get_and_step();
19077     cur_curve->ref_vertices(curve_verts);
19078   }
19079   curve_verts.uniquify_unordered();
19080   DLIList<RefVertex*> verts_after_unmerge;
19081   OldUnmergeCode::instance().unmerge(input_vertex);
19082   for(int j=vert_curves.size(); j>0; j--)
19083   {
19084     RefEdge *cur_curve = vert_curves.get_and_step();
19085     cur_curve->ref_vertices(verts_after_unmerge);
19086   }
19087   verts_after_unmerge.uniquify_unordered();
19088   verts_after_unmerge -= curve_verts;
19089   if(verts_after_unmerge.size() < 1)
19090     return CUBIT_FAILURE;
19091   verts_after_unmerge.append_unique(input_vertex);
19092   DLIList<RefVertex*> *new_list = new DLIList<RefVertex*>();
19093   for(int r=verts_after_unmerge.size(); r>0; r--)
19094   {
19095     RefVertex *cur_vert = verts_after_unmerge.get_and_step();
19096     new_list->append(cur_vert);
19097   }
19098   vert_merge_lists.append(new_list);
19099 
19100   return CUBIT_SUCCESS;
19101 }
19102 
19103 CubitStatus GeometryModifyTool::unmerge_input(RefEdge *curve1,
19104                                               RefEdge *curve2,
19105                                               DLIList<DLIList<RefEdge*>*> &curve_merge_lists,
19106                                               DLIList<DLIList<RefFace*>*> &surf_merge_lists)
19107 {
19108   if(curve1->is_merged())
19109   {
19110     this->unmerge_and_return_merge_partners(curve1, curve_merge_lists, surf_merge_lists);
19111   }
19112   if(curve2->is_merged())
19113   {
19114     this->unmerge_and_return_merge_partners(curve2, curve_merge_lists, surf_merge_lists);
19115   }
19116   return CUBIT_SUCCESS;
19117 }
19118 
19119 CubitStatus GeometryModifyTool::find_best_curves_to_merge(DLIList<RefEdge*> *&curves_from_curve1,
19120                                                           DLIList<RefEdge*> *&curves_from_curve2,
19121                                                           RefEdge *&curve1,
19122                                                           RefEdge *&curve2)
19123 {
19124   /*
19125   for(int i=curves_from_curve1.size(); i>0; i--)
19126   {
19127      if found better curve than curve1 set curve1 to be this curve
19128   }
19129   for(int i=curves_from_curve2.size(); i>0; i--)
19130   {
19131      if found better curve than curve2 set curve2 to be this curve
19132   }
19133   */
19134   return CUBIT_SUCCESS;
19135 }
19136 
19137 CubitStatus GeometryModifyTool::imprint_and_merge_curves(RefEdge *input_curve1,
19138                                                          RefEdge *input_curve2,
19139                                                          DLIList<RefVertex*> &vert_list,
19140                                                          double divergence_angle,
19141                                                          DLIList<DLIList<RefEdge*>*> &curves_to_merge1,
19142                                                          DLIList<DLIList<RefEdge*>*> &curves_to_merge2,
19143                                                          DLIList<DLIList<RefEdge*>*> &prev_curve_merge_lists,
19144                                                          DLIList<DLIList<RefFace*>*> &prev_surf_merge_lists)
19145 {
19146   CubitStatus status;
19147   status = this->unmerge_input(input_curve1, input_curve2, prev_curve_merge_lists, prev_surf_merge_lists);
19148   if(status == CUBIT_FAILURE)
19149     return status;
19150   RefEdge *curve1, *curve2;
19151   DLIList<RefEdge*> *curves_from_curve1 = new DLIList<RefEdge*>();
19152   DLIList<RefEdge*> *curves_from_curve2 = new DLIList<RefEdge*>();
19153   for(int i=prev_curve_merge_lists.size(); i>0; i--)
19154   {
19155     DLIList<RefEdge*> *cur_list = prev_curve_merge_lists.get_and_step();
19156 //    DLIList<RefEdge*> cur_list = prev_curve_merge_lists.get();
19157     if(cur_list->move_to(input_curve1))
19158     {
19159       *curves_from_curve1 = *cur_list;
19160      // prev_curve_merge_lists.remove();
19161     }
19162     else if(cur_list->move_to(input_curve2))
19163     {
19164       *curves_from_curve2 = *cur_list;
19165      // prev_curve_merge_lists.remove();
19166     }
19167 //    else
19168  //     prev_curve_merge_lists.step();
19169   }
19170   // Make sure at least the input curves are in the lists.
19171   if(curves_from_curve1->size() == 0)
19172     curves_from_curve1->append(input_curve1);
19173   if(curves_from_curve2->size() == 0)
19174     curves_from_curve2->append(input_curve2);
19175 
19176   curve1 = input_curve1;
19177   curve2 = input_curve2;
19178   status = this->find_best_curves_to_merge(curves_from_curve1, curves_from_curve2, curve1, curve2);
19179   if(CUBIT_FAILURE == status)
19180     return status;
19181 
19182   DLIList<CubitVector> merge_end_points_on_curve1, merge_end_points_on_curve2;
19183   DLIList<CubitBoolean> split_flags1, split_flags2;
19184   this->calculate_split_points_for_merge(curve1, curve2, vert_list, NULL,
19185     merge_end_points_on_curve1, merge_end_points_on_curve2, split_flags1, split_flags2, divergence_angle);
19186 
19187   merge_end_points_on_curve1.reset();
19188   split_flags1.reset();
19189   for(int k=merge_end_points_on_curve1.size(); k>0; k=k-2)
19190   {
19191     CubitVector end_point1 = merge_end_points_on_curve1.get_and_step();
19192     CubitVector end_point2 = merge_end_points_on_curve1.get_and_step();
19193     bool split_flag_end = split_flags1.get_and_step();
19194     if(split_flag_end)
19195     {
19196       DLIList<RefEdge*> *cur_merge_list = new DLIList<RefEdge*>();
19197       for(int n=curves_from_curve1->size(); n>0; n--)
19198       {
19199         RefEdge *curve_to_split = curves_from_curve1->get();
19200         CubitVector mid = (end_point1 + end_point2)/2.0;
19201         CubitVector pos_for_identifying;
19202         curve_to_split->closest_point_trimmed(mid, pos_for_identifying);
19203 
19204         DLIList<CubitVector> loc_list;
19205         loc_list.append(end_point2);
19206         CubitStatus loc_status;
19207 
19208         int expected_edge_id_1 = RefEntityFactory::instance()->current_edge_id() + 1;
19209         int expected_edge_id_2 = expected_edge_id_1 + 1;
19210 
19211         if(curve_to_split->body())
19212         {
19213           DLIList<Body*> edge_bodies, new_bodies;
19214           edge_bodies.append(curve_to_split->body());  // for now just handle single body case
19215 
19216           loc_status = this->imprint( edge_bodies, loc_list, new_bodies );
19217         }
19218         else
19219         {
19220           DLIList<RefEdge*> new_ref_edges;
19221           loc_status = this->split_free_curve( curve_to_split, loc_list, new_ref_edges );
19222         }
19223 
19224         if(loc_status == CUBIT_FAILURE)
19225         {
19226           return CUBIT_FAILURE;
19227         }
19228 
19229         RefEdge *new_edge_1 = RefEntityFactory::instance()->get_ref_edge(expected_edge_id_1);
19230         RefEdge *new_edge_2 = RefEntityFactory::instance()->get_ref_edge(expected_edge_id_2);
19231 
19232         if(!new_edge_1 || !new_edge_2)
19233         {
19234           return CUBIT_FAILURE;
19235         }
19236 
19237         CubitVector closest;
19238         new_edge_1->closest_point_trimmed(pos_for_identifying, closest);
19239         if(closest.about_equal(pos_for_identifying))
19240         {
19241           cur_merge_list->append(new_edge_1);
19242           RefEdge *edge_that_was_split = curves_from_curve1->get();
19243           curves_from_curve1->change_to(new_edge_2);
19244           for(int w=prev_curve_merge_lists.size(); w>0; w--)
19245           {
19246             DLIList<RefEdge*> *cur_list = prev_curve_merge_lists.get_and_step();
19247             if(cur_list->move_to(edge_that_was_split))
19248             {
19249               cur_list->change_to(new_edge_2);
19250               w=0;
19251             }
19252           }
19253         }
19254         else
19255         {
19256           cur_merge_list->append(new_edge_2);
19257           RefEdge *edge_that_was_split = curves_from_curve1->get();
19258           curves_from_curve1->change_to(new_edge_1);
19259           for(int w=prev_curve_merge_lists.size(); w>0; w--)
19260           {
19261             DLIList<RefEdge*> *cur_list = prev_curve_merge_lists.get_and_step();
19262             if(cur_list->move_to(edge_that_was_split))
19263             {
19264               cur_list->change_to(new_edge_1);
19265               w=0;
19266             }
19267           }
19268         }
19269         curves_from_curve1->step();
19270       }
19271       curves_to_merge1.append(cur_merge_list);
19272     }
19273     else
19274     {
19275       curves_to_merge1.append(curves_from_curve1);
19276     }
19277   }
19278 
19279   merge_end_points_on_curve2.reset();
19280   split_flags2.reset();
19281   for(int k=merge_end_points_on_curve2.size(); k>0; k=k-2)
19282   {
19283     CubitVector end_point1 = merge_end_points_on_curve2.get_and_step();
19284     CubitVector end_point2 = merge_end_points_on_curve2.get_and_step();
19285     bool split_flag_end = split_flags2.get_and_step();
19286     if(split_flag_end)
19287     {
19288       DLIList<RefEdge*> *cur_merge_list = new DLIList<RefEdge*>();
19289       for(int n=curves_from_curve2->size(); n>0; n--)
19290       {
19291         RefEdge *curve_to_split = curves_from_curve2->get();
19292         CubitVector mid = (end_point1 + end_point2)/2.0;
19293         CubitVector pos_for_identifying;
19294         curve_to_split->closest_point_trimmed(mid, pos_for_identifying);
19295 
19296         DLIList<CubitVector> loc_list;
19297         loc_list.append(end_point2);
19298         CubitStatus loc_status;
19299 
19300         int expected_edge_id_1 = RefEntityFactory::instance()->current_edge_id() + 1;
19301         int expected_edge_id_2 = expected_edge_id_1 + 1;
19302 
19303         if(curve_to_split->body())
19304         {
19305           DLIList<Body*> edge_bodies, new_bodies;
19306           edge_bodies.append(curve_to_split->body());  // for now just handle single body case
19307 
19308           loc_status = this->imprint( edge_bodies, loc_list, new_bodies );
19309         }
19310         else
19311         {
19312           DLIList<RefEdge*> new_ref_edges;
19313           loc_status = this->split_free_curve( curve_to_split, loc_list, new_ref_edges );
19314         }
19315 
19316         if(loc_status == CUBIT_FAILURE)
19317         {
19318           return CUBIT_FAILURE;
19319         }
19320 
19321         RefEdge *new_edge_1 = RefEntityFactory::instance()->get_ref_edge(expected_edge_id_1);
19322         RefEdge *new_edge_2 = RefEntityFactory::instance()->get_ref_edge(expected_edge_id_2);
19323 
19324         if(!new_edge_1 || !new_edge_2)
19325         {
19326           return CUBIT_FAILURE;
19327         }
19328 
19329         CubitVector closest;
19330         new_edge_1->closest_point_trimmed(pos_for_identifying, closest);
19331         if(closest.about_equal(pos_for_identifying))
19332         {
19333           cur_merge_list->append(new_edge_1);
19334           RefEdge *edge_that_was_split = curves_from_curve2->get();
19335           curves_from_curve2->change_to(new_edge_2);
19336           for(int w=prev_curve_merge_lists.size(); w>0; w--)
19337           {
19338             DLIList<RefEdge*> *cur_list = prev_curve_merge_lists.get_and_step();
19339             if(cur_list->move_to(edge_that_was_split))
19340             {
19341               cur_list->change_to(new_edge_2);
19342               w=0;
19343             }
19344           }
19345         }
19346         else
19347         {
19348           cur_merge_list->append(new_edge_2);
19349           RefEdge *edge_that_was_split = curves_from_curve2->get();
19350           curves_from_curve2->change_to(new_edge_1);
19351           for(int w=prev_curve_merge_lists.size(); w>0; w--)
19352           {
19353             DLIList<RefEdge*> *cur_list = prev_curve_merge_lists.get_and_step();
19354             if(cur_list->move_to(edge_that_was_split))
19355             {
19356               cur_list->change_to(new_edge_1);
19357               w=0;
19358             }
19359           }
19360         }
19361         curves_from_curve2->step();
19362       }
19363       curves_to_merge2.append(cur_merge_list);
19364     }
19365     else
19366     {
19367       curves_to_merge2.append(curves_from_curve2);
19368     }
19369   }
19370   return status;
19371 }
19372 
19373 
19374 CubitStatus GeometryModifyTool::find_overlap_region(RefEdge *c1,
19375                                                   RefEdge *c2,
19376                                                   RefVertex *v1,
19377                                                   RefVertex *v2,
19378                                                   bool forward_c1,
19379                                                   bool forward_c2,
19380                                                   bool &full_c1,
19381                                                   bool &full_c2,
19382                                                   double &c1_stop_param,
19383                                                   double &c2_stop_param,
19384                                                   double divergence_angle)
19385 {
19386   CubitStatus status = CUBIT_SUCCESS;
19387   double start_t, end_t, dt, cur_t;
19388   int num_segments = 20;
19389   double reverse_multiplier;
19390   double divergence_tol = cos(divergence_angle*CUBIT_PI/180.0);
19391   int i;
19392 
19393   if(forward_c1 != forward_c2)
19394     reverse_multiplier = -1.0;
19395   else
19396     reverse_multiplier = 1.0;
19397 
19398   // Start from the projection of v2 onto c1.
19399   CubitVector tmp_pos;
19400   c1->closest_point_trimmed(v2->coordinates(), tmp_pos);
19401   start_t = c1->u_from_position(tmp_pos);
19402   if(forward_c1)
19403   {
19404     end_t = c1->end_param();
19405     dt = (end_t-start_t)/(double)num_segments;
19406     cur_t = start_t + dt;
19407   }
19408   else
19409   {
19410     end_t = c1->start_param();
19411     dt = (end_t-start_t)/(double)num_segments;
19412     cur_t = start_t + dt;
19413   }
19414   // Check all of the interior points to see if the tangents
19415   // of the two curves are within tolerance.
19416   bool went_past_end_of_c2 = false;
19417   bool went_out_of_angle_tolerance = false;
19418   for(i=num_segments; i>0; i--)
19419 //  for(i=num_segments-1; i>0; i--)
19420   {
19421     if(i==1)
19422     {
19423       cur_t = end_t;
19424     }
19425     // Evaluate curve 1.
19426     CubitVector vec1, vec2, tangent1, tangent2;
19427     c1->position_from_u(cur_t, vec1);
19428     c1->tangent(vec1, tangent1);
19429     tangent1.normalize();
19430     // Project the point to curve 2 and get the tangent.
19431     c2->closest_point_trimmed(vec1, vec2);
19432     c2->tangent(vec2, tangent2);
19433     tangent2.normalize();
19434     if(((tangent1 % tangent2) * reverse_multiplier) > divergence_tol)
19435     {
19436       CubitVector check_vec = vec2-vec1;
19437       double dot_val = 0.0;
19438       if(check_vec.length() > 1e-6)
19439       {
19440         check_vec.normalize();
19441         dot_val = check_vec % tangent2;
19442       }
19443       if(dot_val > .001 || dot_val < -.001)
19444       {
19445         went_past_end_of_c2 = true;
19446       }
19447       else
19448       {
19449         // If we made it to the end of curve 1 check to see
19450         // if the end of curve 2 is within some tolerance of
19451         // the endpoint of curve 1 and if so set the
19452         // full_c2 flag to true.
19453         if(i==1)
19454         {
19455           RefVertex *c1_end, *c2_end;
19456           if(forward_c1)
19457             c1_end = c1->end_vertex();
19458           else
19459             c1_end = c1->start_vertex();
19460           if(forward_c2)
19461             c2_end = c2->end_vertex();
19462           else
19463             c2_end = c2->start_vertex();
19464           if(c1_end == c2_end) // verts are already merged
19465             full_c2 = true;
19466           else
19467           {
19468             CubitVector c2_end_pos;
19469             if(forward_c2)
19470               c2_end_pos = c2->end_coordinates();
19471             else
19472               c2_end_pos = c2->start_coordinates();
19473             double dist_sq_1 = (vec1-vec2).length_squared();
19474             double dist_sq_2 = (vec1-c2_end_pos).length_squared();
19475             if(dist_sq_2 < 2.25*dist_sq_1)
19476               full_c2 = true;
19477           }
19478         }
19479       }
19480     }
19481     else
19482     {
19483       went_out_of_angle_tolerance = true;
19484     }
19485     if(went_past_end_of_c2)
19486     {
19487       i=0;
19488       full_c2 = true;
19489       c1_stop_param = cur_t;
19490       // calculate split point on curve 1
19491     }
19492     else if(went_out_of_angle_tolerance)
19493     {
19494       if(i==num_segments)
19495         status = CUBIT_FAILURE;
19496       i=0;
19497       c1_stop_param = cur_t;
19498       c2_stop_param = c2->u_from_position(vec2);
19499     }
19500 
19501     cur_t += dt;
19502   }
19503 
19504   if(i==0)
19505   {
19506     full_c1 = true;
19507   }
19508 
19509   return status;
19510 }
19511 
19512 CubitStatus GeometryModifyTool::match_v1_to_c1(RefVertex *&v1,
19513                                              RefVertex *&v2,
19514                                              RefVertex *c1_v1,
19515                                              RefVertex *c1_v2,
19516                                              RefVertex *c2_v1,
19517                                              RefVertex *c2_v2)
19518 {
19519   CubitStatus status = CUBIT_SUCCESS;
19520 
19521   if(v1 == c1_v1 || v1 == c1_v2)
19522   {
19523     if(v2 == c2_v1 || v2 == c2_v2)
19524     {
19525       // everything is fine
19526     }
19527     else
19528       status = CUBIT_FAILURE;
19529   }
19530   else if(v1 == c2_v1 || v1 == c2_v2)
19531   {
19532     if(v2 == c1_v1 || v2 == c1_v2)
19533     {
19534       RefVertex *tmp = v1;
19535       v1 = v2;
19536       v2 = tmp;
19537     }
19538     else
19539       status = CUBIT_FAILURE;
19540   }
19541   else
19542     status = CUBIT_FAILURE;
19543 
19544   return status;
19545 }
19546 
19547 CubitStatus GeometryModifyTool::calculate_split_points_for_merge(RefEdge* c1,
19548                                                                RefEdge* c2,
19549                                                                DLIList<RefVertex*> &verts_to_merge,
19550                                                                double *merge_tolerance,
19551                                                                DLIList<CubitVector> &merge_end_points_on_curve1,
19552                                                                DLIList<CubitVector> &merge_end_points_on_curve2,
19553                                                                DLIList<CubitBoolean> &split_flags_for_curve1,
19554                                                                DLIList<CubitBoolean> &split_flags_for_curve2,
19555                                                                double divergence_angle)
19556 {
19557 
19558   CubitStatus status = CUBIT_SUCCESS;
19559   bool all_done = false;
19560 
19561   // Get the vertices of the two curves.
19562   RefVertex *c1_v1 = c1->start_vertex();
19563   RefVertex *c1_v2 = c1->end_vertex();
19564   RefVertex *c2_v1 = c2->start_vertex();
19565   RefVertex *c2_v2 = c2->end_vertex();
19566 
19567   // Check for closed curves.
19568   bool c1_closed = false;
19569   if(c1_v1 == c1_v2)
19570     c1_closed = true;
19571   bool merge_verts_at_both_ends = false;
19572 
19573   // If we are told that certain vertices need to merge
19574   // we will know that we do not need to split the curves there.
19575   bool full_c1=false, full_c2=false;
19576   int verts_to_merge_size = verts_to_merge.size();
19577   RefVertex *v1, *v2;
19578   if(verts_to_merge_size > 0)
19579   {
19580     // Verts to merge should always come in pairs.
19581     if(verts_to_merge_size % 2 != 0)
19582     {
19583       status = CUBIT_FAILURE;
19584     }
19585     else
19586     {
19587       if(verts_to_merge_size > 2 || c1_closed)
19588         merge_verts_at_both_ends = true;
19589 
19590       verts_to_merge.reset();
19591       // Process the first set of verts to merge.
19592       v1 = verts_to_merge.get_and_step();
19593       v2 = verts_to_merge.get_and_step();
19594       // Make sure v1 corresponds to c1 and v2 to c2.
19595       status = match_v1_to_c1(v1, v2, c1_v1, c1_v2, c2_v1, c2_v2);
19596     }
19597     if(status == CUBIT_SUCCESS)
19598     {
19599       // Determine whether the verts are at the
19600       // beginning or end of curves.
19601       bool forward_c1, forward_c2;
19602       if(v1 == c1_v1)
19603         forward_c1 = true;
19604       else
19605         forward_c1 = false;
19606       if(v2 == c2_v1)
19607         forward_c2 = true;
19608       else
19609         forward_c2 = false;
19610 
19611       double c1_stop_param, c2_stop_param;
19612 
19613       status = find_overlap_region(c1, c2, v1, v2, forward_c1, forward_c2, full_c1, full_c2,
19614         c1_stop_param, c2_stop_param, divergence_angle);
19615 
19616       if(status == CUBIT_SUCCESS)
19617       {
19618         merge_end_points_on_curve1.append(v1->coordinates());
19619         merge_end_points_on_curve2.append(v2->coordinates());
19620         split_flags_for_curve1.append(CUBIT_FALSE);
19621         split_flags_for_curve2.append(CUBIT_FALSE);
19622 
19623         // If we traversed the whole length of either curve and
19624         // we are told to merge the verts at both ends then
19625         // just add the verts at the other end and be done.
19626         if((full_c1 || full_c2) && merge_verts_at_both_ends)
19627         {
19628           split_flags_for_curve1.append(CUBIT_FALSE);
19629           split_flags_for_curve2.append(CUBIT_FALSE);
19630           if(c1_v1 == v1)
19631             merge_end_points_on_curve1.append(c1_v2->coordinates());
19632           else
19633             merge_end_points_on_curve1.append(c1_v1->coordinates());
19634           if(c2_v1 == v2)
19635             merge_end_points_on_curve2.append(c2_v2->coordinates());
19636           else
19637             merge_end_points_on_curve2.append(c2_v1->coordinates());
19638           all_done = true;
19639         }
19640         else
19641         {
19642           if(full_c2)
19643           {
19644             RefVertex *tmp_vert;
19645             if(c2_v1 == v2)
19646               tmp_vert = c2_v2;
19647             else
19648               tmp_vert = c2_v1;
19649             merge_end_points_on_curve2.append(tmp_vert->coordinates());
19650             split_flags_for_curve2.append(CUBIT_FALSE);
19651             if(!full_c1)
19652             {
19653               CubitVector pos1;
19654               c1->closest_point_trimmed(tmp_vert->coordinates(), pos1);
19655               merge_end_points_on_curve1.append(pos1);
19656               split_flags_for_curve1.append(CUBIT_TRUE);
19657             }
19658             else
19659             {
19660               if(c1_v1 == v1)
19661                 merge_end_points_on_curve1.append(c1_v2->coordinates());
19662               else
19663                 merge_end_points_on_curve1.append(c1_v1->coordinates());
19664               split_flags_for_curve1.append(CUBIT_FALSE);
19665             }
19666           }
19667           else
19668           {
19669             split_flags_for_curve2.append(CUBIT_TRUE);
19670             if(full_c1)
19671             {
19672               split_flags_for_curve1.append(CUBIT_FALSE);
19673               if(c1_v1 == v1)
19674               {
19675                 merge_end_points_on_curve1.append(c1_v2->coordinates());
19676                 // we need to imprint the end of c1 onto c2.
19677                 CubitVector pos2;
19678                 c2->closest_point_trimmed(c1_v2->coordinates(), pos2);
19679                 merge_end_points_on_curve2.append(pos2);
19680               }
19681               else
19682               {
19683                 merge_end_points_on_curve1.append(c1_v1->coordinates());
19684                 // we need to imprint the end of c1 onto c2.
19685                 CubitVector pos2;
19686                 c2->closest_point_trimmed(c1_v1->coordinates(), pos2);
19687                 merge_end_points_on_curve2.append(pos2);
19688               }
19689             }
19690             else
19691             {
19692               split_flags_for_curve1.append(CUBIT_TRUE);
19693               // we need to imprint the end of c2 onto c1.
19694               CubitVector pos1;
19695               c1->position_from_u(c1_stop_param, pos1);
19696               merge_end_points_on_curve1.append(pos1);
19697               // we need to imprint the end of c1 onto c2.
19698               CubitVector pos2;
19699               c2->closest_point_trimmed(pos1, pos2);
19700               merge_end_points_on_curve2.append(pos2);
19701             }
19702           }
19703         }
19704       }
19705     }
19706     if(status == CUBIT_SUCCESS && !all_done)
19707     {
19708       if(merge_verts_at_both_ends)
19709       {
19710         // Process the next set of verts to merge.
19711         v1 = verts_to_merge.get_and_step();
19712         v2 = verts_to_merge.get_and_step();
19713         // Make sure v1 corresponds to c1 and v2 to c2.
19714         status = match_v1_to_c1(v1, v2, c1_v1, c1_v2, c2_v1, c2_v2);
19715         if(status == CUBIT_SUCCESS)
19716         {
19717           // Determine whether the verts are at the
19718           // beginning or end of curves.
19719           bool forward_c1, forward_c2;
19720           if(v1 == c1_v1)
19721             forward_c1 = true;
19722           else
19723             forward_c1 = false;
19724           if(v2 == c2_v1)
19725             forward_c2 = true;
19726           else
19727             forward_c2 = false;
19728 
19729           double c1_stop_param, c2_stop_param;
19730           bool full_c1=false, full_c2=false;
19731 
19732           status = find_overlap_region(c1, c2, v1, v2, forward_c1, forward_c2, full_c1, full_c2,
19733             c1_stop_param, c2_stop_param, divergence_angle);
19734           if(status == CUBIT_SUCCESS)
19735           {
19736             merge_end_points_on_curve1.append(v1->coordinates());
19737             merge_end_points_on_curve2.append(v2->coordinates());
19738             split_flags_for_curve1.append(CUBIT_FALSE);
19739             split_flags_for_curve2.append(CUBIT_FALSE);
19740             split_flags_for_curve1.append(CUBIT_TRUE);
19741             split_flags_for_curve2.append(CUBIT_TRUE);
19742             // we need to imprint the end of c2 onto c1.
19743             CubitVector pos1;
19744             c1->position_from_u(c1_stop_param, pos1);
19745             merge_end_points_on_curve1.append(pos1);
19746             // we need to imprint the end of c1 onto c2.
19747             CubitVector pos2;
19748             c2->position_from_u(c2_stop_param, pos2);
19749             merge_end_points_on_curve2.append(pos2);
19750           }
19751         }
19752       }
19753     }
19754   }
19755 
19756   if(status == CUBIT_SUCCESS)
19757   {
19758   }
19759 
19760   return status;
19761 }
19762 
19763 CubitStatus GeometryModifyTool::tolerant_imprint( DLIList<Body*> &bodies,
19764                                       DLIList<Body*> &new_bodies, double overlap_tol,
19765                                       double imprint_tol, bool merge )
19766 {
19767   //make sure all bodies are from the same modify engine
19768   DLIList<BodySM*> body_sm_list;
19769   GeometryModifyEngine* gme = common_modify_engine(bodies, body_sm_list);
19770   if ( !gme )
19771   {
19772     PRINT_ERROR("Performing IMPRINT with volumes containing geometry\n"
19773                 "from different modeling engines is not allowed.\n"
19774                 "Delete uncommon geometry on these volumes before operation.\n\n");
19775     return CUBIT_FAILURE;
19776   }
19777 
19778 
19779   //make sure that merge tolerance is not inapproiate for model
19780   int i;
19781   CubitBox bounding_box( CubitVector(0,0,0),
19782                          CubitVector(CUBIT_DBL_MAX,
19783                                      CUBIT_DBL_MAX,
19784                                      CUBIT_DBL_MAX ) );
19785   for( i=bodies.size(); i--; )
19786   {
19787     CubitBox tmp_box = bodies.get_and_step()->bounding_box();
19788     if(bounding_box.max_x() == CUBIT_DBL_MAX)
19789       bounding_box = tmp_box;
19790     else if( tmp_box.diagonal().length_squared() <
19791         bounding_box.diagonal().length_squared() )
19792       bounding_box = tmp_box;
19793   }
19794 
19795   //get the merge tolerance
19796   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
19797 
19798   //if the merge tolerance is greater than 1/10th the length of the
19799   //diagonal of the bounding box of the smallest volume, fail!
19800   double tenth_smallest_bbox = 0.1*(bounding_box.diagonal().length());
19801   if( tolerance > tenth_smallest_bbox )
19802   {
19803     PRINT_ERROR("Merge tolerance is set excessively high.  Must be lower than %f\n",
19804                  tenth_smallest_bbox );
19805     PRINT_INFO("       (Merge tolerance must be less than than 1/10th of the diagonal\n"
19806                         "of the bounding box of the smallest volume)\n");
19807     return CUBIT_FAILURE;
19808   }
19809 
19810   if( CubitUndo::get_undo_enabled() )
19811     CubitUndo::save_state_with_cubit_file( bodies );
19812 
19813   // Propagate any merge tolerances on the bodies
19814 //  propagate_merge_tolerance(bodies);
19815 
19816   // Push the tolerance attributes
19817 //  push_tolerance_attribute(bodies);
19818 
19819   body_sm_list.clean_out();
19820   DLIList<Body*> old_body_list;
19821   old_body_list += bodies;
19822   bodies.reset();
19823   for( i=bodies.size(); i--; )
19824     body_sm_list.append( bodies.get_and_step()->get_body_sm_ptr() );
19825 
19826   int process_composites = 0;
19827   if(contains_composites(bodies))
19828     process_composites = 1;
19829 
19830   if(process_composites)
19831   {
19832     // Push virtual attributes down to solid model topology before
19833     // doing the imprint.
19834     do_attribute_setup();
19835     push_attributes_before_modify(body_sm_list);
19836     // This must be done after pushing the vg atts because it uses them.
19837     DLIList<TopologyBridge*> tb_list;
19838     CAST_LIST(body_sm_list, tb_list, TopologyBridge);
19839     push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
19840     push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
19841   }
19842 
19843   if (DEBUG_FLAG(95))
19844   {
19845     PRINT_DEBUG_95( "Calculating local tolerances for tolerant imprinting.\n");
19846 
19847 //#ifndef _NDEBUG
19848 //    LocalToleranceTool::instance()->print_local_tolerances( body_sm_list );
19849 //#endif
19850 
19851     // Calculate local tolerances at ref entities
19852     LocalToleranceTool::instance()->calculate_local_tolerances( body_sm_list );
19853 
19854 //#ifndef _NDEBUG
19855 //    LocalToleranceTool::instance()->print_local_tolerances( body_sm_list );
19856 //#endif
19857   }
19858 
19859   // Call tolerant imprint
19860   DLIList<BodySM*> new_body_list;
19861   CubitStatus result = gme->tolerant_imprint( body_sm_list, new_body_list, overlap_tol, imprint_tol);
19862 
19863 
19864   if(result == CUBIT_FAILURE)
19865   {
19866     if(process_composites)
19867     {
19868       remove_pushed_attributes(new_body_list, bodies);
19869       do_attribute_cleanup();
19870     }
19871     return result;
19872   }
19873   else
19874   {
19875     if(process_composites)
19876     {
19877       // Analyze the results and adjust virtual attributes as necessary.
19878        DLIList<TopologyBridge*> tb_list;
19879        CAST_LIST(new_body_list, tb_list, TopologyBridge);
19880       GeometryQueryTool::instance()->ige_attribute_after_imprinting(tb_list, bodies);
19881 
19882       // Clean up attributes.
19883       remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
19884 
19885       // Restore the virtual geometry.
19886       restore_vg_after_modify(new_body_list, bodies, gme);
19887       remove_pushed_attributes(new_body_list, bodies);
19888     }
19889   }
19890 
19891   // RANDY - HACK!!
19892   //for (int i = new_body_list.size(); i--;)
19893   //{
19894   //  clean_up_from_copy_failure(new_body_list.get_and_step());
19895   //}
19896 
19897   result = finish_sm_op( bodies, body_sm_list, new_bodies );
19898 
19899   if(process_composites)
19900     do_attribute_cleanup();
19901 
19902   if(result == CUBIT_FAILURE)
19903   {
19904     if( CubitUndo::get_undo_enabled() )
19905       CubitUndo::remove_last_undo();
19906     return CUBIT_FAILURE;
19907   }
19908 
19909   if( merge )
19910     MergeTool::instance()->merge_bodies( bodies );
19911 
19912   return CUBIT_SUCCESS;
19913 }
19914 
19915 CubitStatus GeometryModifyTool::remove_curve_slivers( DLIList<Body*> &bodies,
19916                                               double lengthlimit )
19917 {
19918   DLIList<BodySM*> body_sm_list;
19919   GeometryModifyEngine* gme = common_modify_engine(bodies, body_sm_list);
19920   if ( !gme )
19921   {
19922     PRINT_ERROR("Curve sliver removal only supported on  geometry\n");
19923     return CUBIT_FAILURE;
19924   }
19925 
19926   if( CubitUndo::get_undo_enabled() )
19927     CubitUndo::save_state_with_cubit_file( bodies );
19928 
19929   CubitStatus status = CUBIT_FAILURE;
19930   DLIList<BodySM*> modified_bodies;
19931   int i;
19932   for( i=body_sm_list.size(); i--; )
19933   {
19934     BodySM *tmp_body_sm = body_sm_list.get_and_step();
19935     if( gme->remove_curve_slivers( tmp_body_sm, lengthlimit ) == CUBIT_SUCCESS )
19936     {
19937       modified_bodies.append( tmp_body_sm );
19938       status = CUBIT_SUCCESS;
19939     }
19940   }
19941 
19942   if( status == CUBIT_FAILURE )
19943   {
19944     PRINT_WARNING("Did not remove any sliver curves\n");
19945     if( CubitUndo::get_undo_enabled() )
19946       CubitUndo::remove_last_undo();
19947     return CUBIT_FAILURE;
19948   }
19949 
19950   DLIList<Body*> dummy_list;
19951   status = finish_sm_op( bodies, modified_bodies, dummy_list );
19952   if( status == CUBIT_FAILURE )
19953   {
19954     PRINT_WARNING("Did not remove any sliver curves\n");
19955     if( CubitUndo::get_undo_enabled() )
19956       CubitUndo::remove_last_undo();
19957     return CUBIT_SUCCESS;
19958   }
19959 
19960   return status;
19961 }
19962 
19963 void GeometryModifyTool::split_surface_with_narrow_region(RefFace *face,
19964                                                       DLIList<CubitVector> &split_pos1_list,
19965                                                       DLIList<CubitVector> &split_pos2_list)
19966 {
19967   int k;
19968   if(split_pos1_list.size() > 0)
19969   {
19970     DLIList<DLIList<CubitVector*>*> vec_lists;
19971     DLIList<CubitVector*> pt_list;
19972     for(k=split_pos1_list.size(); k--;)
19973     {
19974       CubitVector split_pos1 = split_pos1_list.get_and_step();
19975       CubitVector split_pos2 = split_pos2_list.get_and_step();
19976       face->move_to_surface(split_pos1);
19977       face->move_to_surface(split_pos2);
19978       DLIList<CubitVector*> *vec_list = new DLIList<CubitVector*>;
19979       vec_list->append( new CubitVector(split_pos1));
19980       vec_list->append( new CubitVector(split_pos2));
19981       vec_lists.append( vec_list );
19982     }
19983 
19984     GeometryModifyTool::instance()->split_surface(face,
19985       pt_list, vec_lists );
19986 
19987     while( vec_lists.size() )
19988     {
19989       DLIList<CubitVector*> *vec_list = vec_lists.pop();
19990       while( vec_list->size() ) delete vec_list->pop();
19991       delete vec_list;
19992     }
19993     /*
19994     while( pt_list.size() )
19995       delete( pt_list.pop() );
19996       */
19997   }
19998 }
19999 
20000 void GeometryModifyTool::fixup_merged_entities( DLIList<int> &merged_surface_ids,
20001                                                 DLIList<int> &merged_curve_ids ) const
20002 {
20003   //use ids to find surviving merged entities
20004   DLIList<RefFace*> ref_face_list;
20005   DLIList<RefEdge*> ref_edge_list;
20006 
20007   int i;
20008   //see what merged survived operation
20009   for( i=merged_surface_ids.size(); i--; )
20010   {
20011     int face_id = merged_surface_ids.get_and_step();
20012     RefFace *surviving_merged_face = RefEntityFactory::instance()->get_ref_face( face_id );
20013     if( surviving_merged_face )
20014       ref_face_list.append( surviving_merged_face );
20015   }
20016 
20017   //see what merged survived operation
20018   for( i=merged_curve_ids.size(); i--; )
20019   {
20020     int edge_id = merged_curve_ids.get_and_step();
20021     RefEdge *surviving_merged_edge = RefEntityFactory::instance()->get_ref_edge( edge_id );
20022     if( surviving_merged_edge )
20023       ref_edge_list.append( surviving_merged_edge );
20024   }
20025 
20026   //fix up merged faces -- some might need to be reversed
20027   for(i=ref_face_list.size(); i--; )
20028   {
20029     RefFace *merged_face = ref_face_list.get_and_step();
20030     BasicTopologyEntity *bte = static_cast<BasicTopologyEntity*>(merged_face);
20031 
20032     //get the first bridge of the entity
20033     DLIList<TopologyBridge*> face_bridge_list;
20034     bte->bridge_manager()->get_bridge_list( face_bridge_list );
20035 
20036     //if there are 2 bridges in the list, it's still merged...do nothing
20037     if( face_bridge_list.size() > 1 )
20038       continue;
20039 
20040     //get the center of the RefFace
20041     CubitVector center = merged_face->center_point();
20042 
20043     //get the normal according to the RefFace
20044     CubitVector ref_face_normal = merged_face->normal_at( center );
20045 
20046     //get the normal at the center from the underlying Surface
20047     Surface *surface_ptr = CAST_TO( face_bridge_list.get(), Surface );
20048     CubitVector surface_normal;
20049     surface_ptr->closest_point( center, NULL, &surface_normal );
20050 
20051     //if normals are opposite, flip sense of surface_ptr
20052     if( fabs(ref_face_normal.interior_angle( surface_normal ) - 180 ) < 0.1  )
20053       merged_face->reverse_normal();
20054 
20055     //One more thing.....if surface is a composite, update the graphics
20056     //on the hidden curve...could have been deleted.
20057     if ( GeometryQueryTool::instance()->ige_is_composite( surface_ptr ) )
20058       AppUtil::instance()->send_event(GeometryEvent(GeometryEvent::TOPOLOGY_MODIFIED, merged_face));
20059   }
20060 
20061   //fix up merged edges -- some might need to be reversed
20062   for(i=ref_edge_list.size(); i--; )
20063   {
20064     RefEdge *merged_edge = ref_edge_list.get_and_step();
20065     BasicTopologyEntity *bte = static_cast<BasicTopologyEntity*>(merged_edge);
20066 
20067     //get the first bridge of the entity
20068     DLIList<TopologyBridge*> edge_bridge_list;
20069     bte->bridge_manager()->get_bridge_list( edge_bridge_list );
20070 
20071     //get start/end points of the edge
20072     CubitVector edge_start_point = merged_edge->start_vertex()->coordinates();
20073     CubitVector edge_end_point = merged_edge->end_vertex()->coordinates();
20074 
20075     //get start/end point of the curve
20076     edge_bridge_list.reset();
20077     Curve *curve_ptr = CAST_TO( edge_bridge_list.get(), Curve);
20078     DLIList<TBPoint*> tmp_points;
20079     curve_ptr->points( tmp_points );
20080     CubitVector curve_start_point = tmp_points.get_and_step()->coordinates();
20081     CubitVector curve_end_point = tmp_points.get_and_step()->coordinates();
20082 
20083     //check to see if curve sense needs to be reversed
20084     if( edge_start_point.distance_between( curve_start_point ) < GEOMETRY_RESABS &&
20085           edge_end_point.distance_between( curve_end_point ) < GEOMETRY_RESABS )
20086     {
20087       //do nothing...everything is fine
20088       continue;
20089     }
20090     else
20091     {
20092       if( edge_start_point.distance_between( curve_end_point ) < GEOMETRY_RESABS &&
20093             edge_end_point.distance_between( curve_start_point ) < GEOMETRY_RESABS )
20094       {
20095         //switch sense of ref entity
20096         merged_edge->reverse_tangent();
20097       }
20098     }
20099   }
20100 }
20101 
20102 void GeometryModifyTool::get_merged_curve_and_surface_ids(
20103                                           DLIList<Body*> &bodies,
20104                                           DLIList<int> &merged_surface_ids,
20105                                           DLIList<int> &merged_curve_ids ) const
20106 {
20107   int i;
20108   for( i=bodies.size(); i--; )
20109   {
20110     DLIList<RefEntity*> merged_children;
20111 
20112     MergeTool::instance()->contains_merged_children( bodies.get_and_step(),
20113                                                      merged_children );
20114 
20115     int j;
20116     for( j=merged_children.size(); j--; )
20117     {
20118       RefEntity *ref_ent = merged_children.get_and_step();
20119 
20120       RefFace *ref_face = CAST_TO( ref_ent, RefFace );
20121 
20122       if( ref_face )
20123         merged_surface_ids.append( ref_face->id() );
20124       else
20125       {
20126         RefEdge *ref_edge = CAST_TO( ref_ent, RefEdge );
20127 
20128         if( ref_edge )
20129           merged_curve_ids.append( ref_edge->id() );
20130       }
20131     }
20132   }
20133 }
20134 
20135 void GeometryModifyTool::plane_preview(DLIList<Body*>& body_list,
20136                                        const CubitVector &pt1,
20137                                        const CubitVector &pt2,
20138                                        const CubitVector &pt3)
20139 {
20140   CubitPlane plane;
20141   if( plane.mk_plane_with_points( pt1, pt2, pt3) == CUBIT_FAILURE)
20142   {
20143        PRINT_INFO( "Unable to create plane from given information.\n" );
20144        return ;
20145   }
20146 
20147   CubitBox bounding_box;
20148   Body* body_ptr = body_list.get_and_step();
20149   bounding_box = body_ptr->bounding_box();
20150 
20151   int i;
20152   for( i=1; i<body_list.size(); i++ )
20153   {
20154      body_ptr = body_list.get_and_step();
20155      bounding_box |= body_ptr->bounding_box();
20156   }
20157 
20158   int extension_type = 1;
20159   double extension = 10; //10%
20160   CubitVector p1, p2, p3, p4;
20161 
20162   if( AnalyticGeometryTool::instance()->
20163          min_pln_box_int_corners( plane, bounding_box, extension_type,
20164          extension, p1, p2, p3, p4 ) == CUBIT_FAILURE )
20165   {
20166      PRINT_INFO( "Unable to create plane from given information.\n" );
20167      return ;
20168   }
20169 
20170   GPoint gp[4];
20171   gp[0].x=p1.x(); gp[0].y=p1.y(); gp[0].z=p1.z();
20172   gp[1].x=p2.x(); gp[1].y=p2.y(); gp[1].z=p2.z();
20173   gp[2].x=p3.x(); gp[2].y=p3.y(); gp[2].z=p3.z();
20174   gp[3].x=p4.x(); gp[3].y=p4.y(); gp[3].z=p4.z();
20175 
20176   // clear previous previews
20177   GfxPreview::clear();
20178 
20179   // Get the color to draw in
20180   int color = CUBIT_BLUE_INDEX;
20181   GfxPreview::draw_quad(gp, color);
20182   GfxPreview::flush();
20183   return;
20184 }
20185 
20186 void GeometryModifyTool::march_using_planes(CubitVector &point_on_surf,
20187                                             RefFace *surf,
20188                                             CubitVector &march_dir,
20189                                             double step_size,
20190                                             DLIList<CubitVector> &horizontal_points,
20191                                             DLIList<CubitVector> &vertical_points)
20192 {
20193   CubitVector surf_norm = surf->normal_at(point_on_surf);
20194   CubitVector plane_norm = march_dir * surf_norm;
20195   GeometryModifyEngine *gme = get_engine((TopologyBridge*)surf->get_surface_ptr());
20196   if(gme)
20197   {
20198     CubitPlane plane(plane_norm, point_on_surf);
20199     CubitBox bbox = surf->ref_volume()->bounding_box();
20200     CubitVector p1, p2, p3, p4;
20201     AnalyticGeometryTool::instance()->min_pln_box_int_corners( plane, bbox, 1,
20202                                     10.0, p1, p2, p3, p4, CUBIT_TRUE );
20203     Body *plane_body = GeometryModifyTool::instance()->planar_sheet( p1, p2, p3, p4 );
20204     Body *model_body_copy = GeometryModifyTool::instance()->copy_body(surf->body());
20205     DLIList<Body*> from_body_list, new_body_list;
20206     from_body_list.append(plane_body);
20207     from_body_list.append(model_body_copy);
20208     GeometryModifyTool::imprint(from_body_list, new_body_list, CUBIT_FALSE);
20209     for(int i=0; i<new_body_list.size(); i++)
20210     {
20211       if(new_body_list[i] == plane_body)
20212       {
20213         trace_out_curves(plane_body, point_on_surf, march_dir,
20214                          step_size, horizontal_points, vertical_points);
20215         /*
20216         GfxDebug::clear();
20217         DLIList<RefEdge*> plane_curves;
20218         plane_body->ref_edges(plane_curves);
20219         for(int j=0; j<plane_curves.size(); j++)
20220         {
20221           GfxDebug::draw_ref_edge(plane_curves[j], CUBIT_RED_INDEX);
20222         }
20223         GfxDebug::flush();
20224         GfxDebug::mouse_xforms();
20225          */
20226       }
20227       else
20228         GeometryQueryTool::instance()->delete_single_Body(new_body_list[i]);
20229     }
20230   }
20231 }
20232 
20233 void GeometryModifyTool::trace_out_curves(Body *plane_body,
20234                                           CubitVector &start_point,
20235                                           CubitVector &march_dir,
20236                                           double step_size,
20237                                           DLIList<CubitVector> &horizontal_points,
20238                                           DLIList<CubitVector> &vertical_points)
20239 {
20240   // Find a curve that the start point is on.
20241   DLIList<RefEdge*> curves;
20242   plane_body->ref_edges(curves);
20243   DLIList<RefEdge*> interior_curves;
20244   for(int i=0; i<curves.size(); i++)
20245   {
20246     RefEdge *cur_curve = curves[i];
20247     DLIList<RefFace*> curve_surfs;
20248     cur_curve->ref_faces(curve_surfs);
20249     if(curve_surfs.size() == 2)
20250       interior_curves.append(cur_curve);
20251   }
20252   RefEdge *start_curve = NULL;
20253   for(int i=0; i<interior_curves.size(); i++)
20254   {
20255     CubitVector closest;
20256     RefEdge *cur_curve = interior_curves[i];
20257     cur_curve->closest_point_trimmed(start_point, closest);
20258     if(start_point.about_equal(closest))
20259     {
20260       start_curve = cur_curve;
20261       break;
20262     }
20263   }
20264   if(start_curve)
20265   {
20266     
20267   }
20268 }
20269 
20270 void GeometryModifyTool::march_path_to_discover_horizontal(CubitVector &start_pos,
20271                                     CubitVector &sweep_dir,
20272                                     RefFace *start_face,
20273                                     CubitVector &march_dir,  // should be normalized
20274                                     double &step_size,
20275                                     DLIList<CubitVector> &final_points,
20276                                     DLIList<RefFace*> &ending_faces)
20277 {
20278   double cos_45 = 0.70710678118654752440084436210485;
20279   double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance();
20280   CubitVector point_on_surf = start_pos;
20281   RefVolume *v = start_face->ref_volume();
20282   RefFace *cur_face = start_face;
20283 
20284   RefEdge *snap_edge = NULL;
20285   bool snapped_to_edge_last_time = false;
20286   bool turned = false;
20287   CubitVector old_pos = point_on_surf;
20288   while(!turned)
20289   {
20290     CubitVector new_pos;
20291     if(snapped_to_edge_last_time)
20292     {
20293       // Just set the new position to the position on the
20294       // edge.  This will force us to jump out without doing
20295       // anything and then on the next loop we will start
20296       // onto the new face.
20297       new_pos = old_pos;
20298       snapped_to_edge_last_time = false;
20299       continue;
20300     }
20301     else
20302     {
20303       // Calculate a new step along the vector.
20304       new_pos = old_pos + step_size * march_dir;
20305     }
20306 
20307     cur_face->get_surface_ptr()->closest_point_trimmed(new_pos, point_on_surf);
20308 
20309     CubitVector norm = cur_face->normal_at(point_on_surf, v);
20310     if(sweep_dir % norm < cos_45)
20311     {
20312       turned = true;
20313     }
20314     else
20315     {
20316       bool snapping_to_edge = true;
20317       CubitVector proj_dir = point_on_surf - new_pos;
20318       double proj_dist = proj_dir.length();
20319       if(proj_dist < geo_tol)
20320         snapping_to_edge = false;
20321       else
20322       {
20323         proj_dir /= proj_dist;
20324         double dot = proj_dir % norm;
20325         if(dot > .99 || dot < -.99)
20326           snapping_to_edge = false;
20327       }
20328       if(!snapping_to_edge)
20329       {
20330         snap_edge = NULL;
20331         // didn't snap to boundary
20332         old_pos = point_on_surf;
20333         final_points.append(point_on_surf);
20334       }
20335       else
20336       {
20337         // probably snapped to the boundary of this face
20338         DLIList<RefEdge*> face_edges;
20339         RefEdge *best_edge = NULL;
20340         cur_face->ref_edges(face_edges);
20341         int i;
20342         DLIList<RefEdge*> possible_edges;
20343         CubitVector closest;
20344         for(i=face_edges.size(); i>0; i--)
20345         {
20346           RefEdge *e = face_edges.get_and_step();
20347           e->closest_point_trimmed(point_on_surf, closest);
20348           double cur_dist = (closest - point_on_surf).length();
20349           if(cur_dist < geo_tol)
20350           {
20351             possible_edges.append(e);
20352           }
20353         }
20354         if(possible_edges.size() == 1)
20355           best_edge = possible_edges.get();
20356         else if(possible_edges.size() > 1)
20357         {
20358           int h;
20359           double smallest_dist = CUBIT_DBL_MAX;
20360           for(h=possible_edges.size(); h>0; h--)
20361           {
20362             RefEdge *ce = possible_edges.get_and_step();
20363             ce->closest_point_trimmed(old_pos, closest);
20364             double cur_dist = (old_pos-closest).length();
20365             if(cur_dist < smallest_dist)
20366             {
20367               smallest_dist = cur_dist;
20368               best_edge = ce;
20369             }
20370           }
20371         }
20372         if(best_edge)
20373         {
20374           if(snap_edge && snap_edge == best_edge)
20375           {
20376             final_points.append(point_on_surf);
20377             old_pos = point_on_surf;
20378             snapped_to_edge_last_time = true;
20379           }
20380           else
20381           {
20382             snap_edge = best_edge;
20383             cur_face = best_edge->other_face(cur_face, v);
20384             CubitVector old_pos_save = old_pos;
20385             old_pos = closest;
20386             i = 0;
20387             snapped_to_edge_last_time = true;
20388 
20389             GeometryModifyEngine *gme = get_engine((TopologyBridge*)best_edge->get_curve_ptr());
20390             if(gme)
20391             {
20392               TBPoint *pt1 = gme->make_Point(old_pos_save);
20393               TBPoint *pt2 = gme->make_Point(new_pos);
20394               CubitVector const* pt3 = NULL;
20395               Curve *crv = gme->make_Curve(STRAIGHT_CURVE_TYPE, pt1, pt2, pt3 );
20396               if(crv)
20397               {
20398                 CubitVector pos1, pos2;
20399                 double dist;
20400                 GeometryQueryTool::instance()->entity_entity_distance(crv, best_edge->get_curve_ptr(), pos1,
20401                   pos2, dist);
20402                 old_pos = pos2;
20403                 delete crv;
20404                 delete pt1;
20405                 delete pt2;
20406                 final_points.append(old_pos);
20407               }
20408             }
20409           }
20410         }
20411       }
20412     }
20413   }
20414   ending_faces.append(cur_face);
20415 }
20416 
20417 void GeometryModifyTool::march_path_to_discover_vertical(CubitVector &start_pos,
20418                                                          CubitVector &sweep_dir,
20419                                                            RefFace *start_face,
20420                                                            CubitVector &march_dir,  // should be normalized
20421                                                            double &step_size,
20422                                                            DLIList<CubitVector> &final_points,
20423                                                            DLIList<RefFace*> &ending_faces)
20424 {
20425   double cos_45 = 0.70710678118654752440084436210485;
20426   double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance();
20427   CubitVector point_on_surf = start_pos;
20428   RefVolume *v = start_face->ref_volume();
20429   RefFace *cur_face = start_face;
20430   
20431   RefEdge *snap_edge = NULL;
20432   bool snapped_to_edge_last_time = false;
20433   bool turned = false;
20434   CubitVector old_pos = point_on_surf;
20435   while(!turned)
20436   {
20437     CubitVector new_pos;
20438     if(snapped_to_edge_last_time)
20439     {
20440       // Just set the new position to the position on the
20441       // edge.  This will force us to jump out without doing
20442       // anything and then on the next loop we will start
20443       // onto the new face.
20444       new_pos = old_pos;
20445       snapped_to_edge_last_time = false;
20446       //snap_edge = NULL;
20447       continue;
20448     }
20449     else
20450     {
20451       // Calculate a new step along the vector.
20452       new_pos = old_pos + step_size * march_dir;
20453     }
20454     
20455     cur_face->get_surface_ptr()->closest_point_trimmed(new_pos, point_on_surf);
20456 
20457     int d = 0;
20458     if(d)
20459     {
20460       GfxDebug::draw_point(new_pos, CUBIT_BLUE_INDEX);
20461       GfxDebug::draw_point(point_on_surf, CUBIT_RED_INDEX);
20462       GfxDebug::flush();
20463       GfxDebug::mouse_xforms();
20464     }
20465     
20466     CubitVector norm = cur_face->normal_at(point_on_surf, v);
20467     double tmp_dot = sweep_dir % norm;
20468     if(tmp_dot > cos_45 || tmp_dot < -cos_45)
20469     {
20470       turned = true;
20471     }
20472     else
20473     {
20474       bool snapping_to_edge = true;
20475       CubitVector proj_dir = point_on_surf - new_pos;
20476       double proj_dist = proj_dir.length();
20477       if(proj_dist < geo_tol)
20478         snapping_to_edge = false;
20479       else
20480       {
20481         proj_dir /= proj_dist;
20482         double dot = proj_dir % norm;
20483         if(dot > .99 || dot < -.99)
20484           snapping_to_edge = false;
20485       }
20486       if(!snapping_to_edge)
20487       {
20488         snap_edge = NULL;
20489         // didn't snap to boundary
20490         old_pos = point_on_surf;
20491         final_points.append(point_on_surf);
20492       }
20493       else
20494       {
20495         // probably snapped to the boundary of this face
20496         DLIList<RefEdge*> face_edges;
20497         RefEdge *best_edge = NULL;
20498         CubitVector best_pos;
20499         cur_face->ref_edges(face_edges);
20500         DLIList<RefEdge*> possible_edges;
20501         CubitVector closest;
20502         for(int i=face_edges.size(); i>0; i--)
20503         {
20504           RefEdge *e = face_edges.get_and_step();
20505           e->closest_point_trimmed(point_on_surf, closest);
20506           double cur_dist = (closest - point_on_surf).length();
20507           if(cur_dist < geo_tol)
20508           {
20509             // If there are more than one edge that are coincident with the point
20510             // choose the one whose tangent is most normal to the direction we are
20511             // marching.  Switching onto the corresponding face should be best.
20512             if(best_edge)
20513             {
20514               CubitVector best_edge_tan, cur_edge_tan;
20515               best_edge->tangent(point_on_surf, best_edge_tan);
20516               e->tangent(point_on_surf, cur_edge_tan);
20517               if(fabs(best_edge_tan % march_dir) > fabs(cur_edge_tan % march_dir))
20518                 best_edge = e;
20519             }
20520             else
20521               best_edge = e;
20522           }
20523         }
20524         if(best_edge)
20525         {
20526           if(snap_edge && snap_edge == best_edge)
20527           {
20528             final_points.append(point_on_surf);
20529             old_pos = point_on_surf;
20530             snapped_to_edge_last_time = true;
20531           }
20532           else
20533           {
20534             snap_edge = best_edge;
20535             cur_face = best_edge->other_face(cur_face, v);
20536             CubitVector old_pos_save = old_pos;
20537             old_pos = best_pos;
20538             snapped_to_edge_last_time = true;
20539             
20540             GeometryModifyEngine *gme = get_engine((TopologyBridge*)best_edge->get_curve_ptr());
20541             if(gme)
20542             {
20543               TBPoint *pt1 = gme->make_Point(old_pos_save);
20544               TBPoint *pt2 = gme->make_Point(new_pos);
20545               CubitVector const* pt3 = NULL;
20546               Curve *crv = gme->make_Curve(STRAIGHT_CURVE_TYPE, pt1, pt2, pt3 );
20547               if(crv)
20548               {
20549                 CubitVector pos1, pos2;
20550                 double dist;
20551                 GeometryQueryTool::instance()->entity_entity_distance(crv, best_edge->get_curve_ptr(), pos1,
20552                                                                       pos2, dist);
20553                 old_pos = pos2;
20554                 delete crv;
20555                 delete pt1;
20556                 delete pt2;
20557                 final_points.append(old_pos);
20558               }
20559             }
20560           }
20561         }
20562       }
20563     }
20564   }
20565   ending_faces.append(cur_face);
20566 }
20567 
20568 CubitStatus GeometryModifyTool::stitch( DLIList<Body*> &bodies_to_stitch,
20569                                         DLIList<Body*> &result_list,
20570                                         bool tighten_gaps,
20571                                         double tolerance )
20572 {
20573   if (!okay_to_modify( bodies_to_stitch, "STITCH" ))
20574     return CUBIT_FAILURE;
20575 
20576   //get all the BodySMs from 'bodies_to_stitch'
20577   int i;
20578   for( i=bodies_to_stitch.size(); i--; )
20579   {
20580     Body *tmp_body = bodies_to_stitch.get_and_step();
20581     if( !tmp_body->is_sheet_body() )
20582     {
20583       PRINT_ERROR("Can't stitch body %d.  It's a solid body\n", tmp_body->id() );
20584       return CUBIT_FAILURE;
20585     }
20586   }
20587 
20588   DLIList<TopologyEntity*> entity_list(bodies_to_stitch.size());
20589   DLIList<TopologyBridge*> bridge_list(bodies_to_stitch.size());
20590   DLIList<BodySM*>         bodysm_list(bodies_to_stitch.size());
20591   CAST_LIST_TO_PARENT(bodies_to_stitch, entity_list);
20592   GeometryModifyEngine *gme = common_modify_engine(entity_list, bridge_list);
20593 
20594   if( entity_list.size() != bridge_list.size() )
20595   {
20596     PRINT_ERROR("Cannot stitch entities of different geometry engines.\n");
20597     return CUBIT_FAILURE;
20598   }
20599 
20600   if( CubitUndo::get_undo_enabled() )
20601     CubitUndo::save_state_with_cubit_file( bodies_to_stitch );
20602 
20603   CAST_LIST(bridge_list, bodysm_list, BodySM);
20604   DLIList<BodySM*> new_bodies;
20605   CubitStatus result = gme->stitch( bodysm_list, new_bodies, tighten_gaps, tolerance );
20606 
20607   if( result == CUBIT_FAILURE && CubitUndo::get_undo_enabled() )
20608     CubitUndo::remove_last_undo();
20609 
20610   if (!finish_sm_op(bodies_to_stitch, new_bodies, result_list))
20611   {
20612     result = CUBIT_FAILURE;
20613     CubitUndo::remove_last_undo();
20614   }
20615 
20616   if( CubitUndo::get_undo_enabled() )
20617   {
20618     if( result == CUBIT_SUCCESS )
20619       CubitUndo::note_result_bodies( result_list );
20620     else
20621       CubitUndo::remove_last_undo();
20622   }
20623 
20624   return result;
20625 }
20626 
20627 
20628 
20629 CubitStatus GeometryModifyTool::discover_topology(RefFace *surf, CubitVector &pos,
20630                                                   double &step_size,
20631                                                   int num_subdivisions)
20632 {
20633   CubitStatus ret = CUBIT_SUCCESS;
20634 
20635   CubitVector point_on_surf;
20636   surf->get_surface_ptr()->closest_point_trimmed(pos, point_on_surf);
20637   RefVolume *v = surf->ref_volume();
20638   CubitVector norm = surf->normal_at(point_on_surf, v);
20639   CubitVector march_dir = norm * CubitVector(1,0,0);
20640   if(march_dir.length() < .001)
20641   {
20642     march_dir = norm * CubitVector(0,1,0);
20643     if(march_dir.length() < .001)
20644     {
20645       march_dir = norm * CubitVector(0,0,1);
20646       if(march_dir.length() < .001)
20647       {
20648         PRINT_ERROR("Couldn't find a good march direction.\n");
20649         ret = CUBIT_FAILURE;
20650       }
20651     }
20652   }
20653 
20654   if(ret == CUBIT_SUCCESS)
20655   {
20656     int new_approach = 0;
20657     if(new_approach)
20658     {
20659       // Get initial 4 directions.
20660       march_dir.normalize();
20661       DLIList<CubitVector> march_directions;
20662       CubitVector v1 = march_dir;
20663       CubitVector v3 = -march_dir;
20664       CubitVector v2 = norm*march_dir;
20665       march_directions.append(v1);
20666       march_directions.append(v2);
20667       march_directions.append(v3);
20668 
20669       // Now subdivide directions further if requested.
20670       for(int i=0; i<num_subdivisions; ++i)
20671       {
20672         DLIList<CubitVector> tmp_list;
20673         int list_size = march_directions.size();
20674         for(int j=0; j<list_size-1; j++)
20675         {
20676           CubitVector dir1 = march_directions[j];
20677           CubitVector dir2 = march_directions[(j+1)%list_size];
20678           CubitVector mid = dir1 + dir2;
20679           mid.normalize();
20680           tmp_list.append(dir1);
20681           tmp_list.append(mid);
20682         }
20683         tmp_list.append(march_directions[list_size-1]);
20684         march_directions = tmp_list;
20685       }
20686       DLIList<DLIList<CubitVector> > horizontal_points, vertical_points;
20687       DLIList<RefFace*> horiz_ending_faces, vert_ending_faces;
20688       for(int i=0; i<march_directions.size()-1; i++)
20689       {
20690         DLIList<CubitVector> new_list;
20691         horizontal_points.append(new_list);
20692         vertical_points.append(new_list);
20693         march_using_planes(point_on_surf, surf, march_directions[i], step_size, horizontal_points[i], vertical_points[i]);
20694       }
20695     }
20696     else
20697     {
20698       // Get initial 4 directions.
20699       march_dir.normalize();
20700       DLIList<CubitVector> march_directions;
20701       CubitVector v1 = march_dir;
20702       CubitVector v3 = -march_dir;
20703       CubitVector v2 = norm*march_dir;
20704       CubitVector v4 = -v2;
20705       march_directions.append(v1);
20706       march_directions.append(v2);
20707       march_directions.append(v3);
20708       march_directions.append(v4);
20709       
20710       // Now subdivide directions further if requested.
20711       for(int i=0; i<num_subdivisions; ++i)
20712       {
20713         DLIList<CubitVector> tmp_list;
20714         int list_size = march_directions.size();
20715         for(int j=0; j<list_size; j++)
20716         {
20717           CubitVector dir1 = march_directions[j];
20718           CubitVector dir2 = march_directions[(j+1)%list_size];
20719           CubitVector mid = dir1 + dir2;
20720           mid.normalize();
20721           tmp_list.append(dir1);
20722           tmp_list.append(mid);
20723         }
20724         march_directions = tmp_list;
20725       }
20726       DLIList<DLIList<CubitVector> > horizontal_points, vertical_points;
20727       DLIList<RefFace*> horiz_ending_faces, vert_ending_faces;
20728       for(int i=0; i<march_directions.size(); i++)
20729       {
20730         DLIList<CubitVector> new_list;
20731         new_list.append(point_on_surf);
20732         horizontal_points.append(new_list);
20733         march_path_to_discover_horizontal(point_on_surf, norm, surf, march_directions[i], step_size, horizontal_points[i], horiz_ending_faces);
20734       }
20735       CubitVector new_dir = -norm;
20736       for(int i=0; i<march_directions.size(); i++)
20737       {
20738         CubitVector start_pos = horizontal_points[i].last_item();
20739         DLIList<CubitVector> new_list;
20740         new_list.append(start_pos);
20741         vertical_points.append(new_list);
20742         march_path_to_discover_vertical(start_pos, norm, horiz_ending_faces[i], new_dir, step_size, vertical_points[i], vert_ending_faces);
20743 //        GfxDebug::draw_point(vertical_points[i].last_item(), CUBIT_GREEN_INDEX);
20744 //        GfxDebug::flush();
20745       }
20746       
20747       // Draw lines traced out by marching directions
20748       for(int i=0; i<horizontal_points.size(); i++)
20749       {
20750         int size1 = horizontal_points[i].size();
20751         for(int j=0; j<size1-1; j++)
20752         {
20753           GfxDebug::draw_line(horizontal_points[i][j],
20754                               horizontal_points[i][j+1],
20755                               CUBIT_WHITE_INDEX);
20756         }
20757       }
20758       for(int i=0; i<vertical_points.size(); i++)
20759       {
20760         int size1 = vertical_points[i].size();
20761         for(int j=0; j<size1-1; j++)
20762         {
20763           GfxDebug::draw_line(vertical_points[i][j],
20764                               vertical_points[i][j+1],
20765                               CUBIT_YELLOW_INDEX);
20766         }
20767       }
20768       // Draw new topology
20769       int size1 = horizontal_points.size();
20770       for(int i=0; i<size1; i++)
20771       {
20772         GfxDebug::draw_line(horizontal_points[i].last_item(),
20773                             horizontal_points[(i+1)%size1].last_item(),
20774                             CUBIT_RED_INDEX);
20775       }
20776       size1 = vertical_points.size();
20777       for(int i=0; i<size1; i++)
20778       {
20779         GfxDebug::draw_line(vertical_points[i].last_item(),
20780                             vertical_points[(i+1)%size1].last_item(),
20781                             CUBIT_RED_INDEX);
20782       }
20783       GfxDebug::flush();
20784     }
20785   }
20786 
20787   return ret;
20788 }
20789 
20790 void GeometryModifyTool::subdivide_pie(CubitVector &dir1, CubitVector &dir2, int num_subdivisions,
20791                                        DLIList<CubitVector> &all_directions)
20792 {
20793   if(num_subdivisions > 0)
20794   {
20795     CubitVector mid = dir1 + dir2;
20796     mid.normalize();
20797     all_directions.append(mid);
20798     if(num_subdivisions > 1)
20799     {
20800       subdivide_pie(dir1, mid, num_subdivisions-1, all_directions);
20801       subdivide_pie(mid, dir2, num_subdivisions-1, all_directions);
20802     }
20803   }
20804 }
20805 
20806 Body* GeometryModifyTool::create_rectangle_surface( double width, double height, CubitVector plane )
20807 {
20808   if(0 == gmeList.size())
20809   {
20810     PRINT_WARNING("No active geometry engine.\n");
20811     return NULL;
20812   }
20813 
20814   if( width <= GEOMETRY_RESABS || height <= GEOMETRY_RESABS )
20815   {
20816     PRINT_ERROR("Values must be positive\n");
20817     return NULL;
20818   }
20819 
20820   if( CubitUndo::get_undo_enabled() )
20821     CubitUndo::save_state();
20822 
20823   BodySM *sheet_body_sm = NULL;
20824   CubitStatus status = gmeList.get()->create_rectangle_surface(width, height, plane, sheet_body_sm );
20825 
20826   if( status == CUBIT_FAILURE )
20827   {
20828     if(CubitUndo::get_undo_enabled())
20829       CubitUndo::remove_last_undo();
20830     return NULL;
20831   }
20832 
20833   Body *new_body = NULL;
20834   if( sheet_body_sm )
20835     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
20836 
20837   if (new_body)
20838   {
20839     if(CubitUndo::get_undo_enabled())
20840       CubitUndo::note_result_body(new_body);
20841     status = CUBIT_SUCCESS;
20842   }
20843   else
20844   {
20845     if(CubitUndo::get_undo_enabled())
20846       CubitUndo::remove_last_undo();
20847     status = CUBIT_FAILURE;
20848   }
20849 
20850   return new_body;
20851 }
20852 
20853 Body* GeometryModifyTool::create_parallelogram_surface( RefVertex *v1,
20854                                                               RefVertex *v2,
20855                                                               RefVertex *v3 )
20856 {
20857   if(0 == gmeList.size())
20858   {
20859     PRINT_WARNING("No active geometry engine.\n");
20860     return NULL;
20861   }
20862 
20863   GeometryModifyEngine *GMEPtr = get_engine( v1->get_point_ptr() );
20864 
20865   if( GMEPtr != get_engine( v2->get_point_ptr() ) )
20866   {
20867     PRINT_INFO("Vertices are not from same modeling engine.\n");
20868     return NULL;
20869   }
20870   if( GMEPtr != get_engine( v3->get_point_ptr() ) )
20871   {
20872     PRINT_INFO("Vertices are not from same modeling engine.\n");
20873     return NULL;
20874   }
20875 
20876   TBPoint *pt1, *pt2, *pt3;
20877 
20878   DLIList<RefVertex*> free_ref_vertices;
20879   if( v1->num_parent_ref_entities() == 0 )
20880   {
20881     free_ref_vertices.append( v1 );
20882     pt1 = v1->get_point_ptr();
20883   }
20884   else
20885     pt1 = GMEPtr->make_Point( v1->coordinates() );
20886 
20887   if( v2->num_parent_ref_entities() == 0 )
20888   {
20889     free_ref_vertices.append( v2 );
20890     pt2 = v2->get_point_ptr();
20891   }
20892   else
20893     pt2 = GMEPtr->make_Point( v2->coordinates() );
20894 
20895   if( v3->num_parent_ref_entities() == 0 )
20896   {
20897     free_ref_vertices.append( v3 );
20898     pt3 = v3->get_point_ptr();
20899   }
20900   else
20901     pt3 = GMEPtr->make_Point( v3->coordinates() );
20902 
20903   if( CubitUndo::get_undo_enabled() )
20904   {
20905     if( free_ref_vertices.size() )
20906       CubitUndo::save_state_with_cubit_file( free_ref_vertices, true );
20907     else
20908       CubitUndo::save_state();
20909   }
20910 
20911   BodySM *sheet_body_sm = NULL;
20912   CubitStatus status = GMEPtr->create_parallelogram_surface(pt1, pt2, pt3, sheet_body_sm );
20913 
20914   if( status == CUBIT_FAILURE )
20915   {
20916     if(CubitUndo::get_undo_enabled())
20917       CubitUndo::remove_last_undo();
20918     return NULL;
20919   }
20920 
20921   Body *new_body = NULL;
20922   if( sheet_body_sm )
20923     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
20924 
20925   if (new_body)
20926   {
20927     if(CubitUndo::get_undo_enabled())
20928       CubitUndo::note_result_body(new_body);    
20929   }
20930   else
20931   {
20932     if(CubitUndo::get_undo_enabled())
20933       CubitUndo::remove_last_undo();    
20934   }
20935 
20936   return new_body;
20937 }
20938 
20939 Body* GeometryModifyTool::create_circle_surface( double radius, CubitVector plane )
20940 {
20941   if(0 == gmeList.size())
20942   {
20943     PRINT_WARNING("No active geometry engine.\n");
20944     return NULL;
20945   }
20946 
20947   if( radius <= GEOMETRY_RESABS )
20948   {
20949     PRINT_ERROR("Values must be positive\n");
20950     return NULL;
20951   }
20952 
20953   if( CubitUndo::get_undo_enabled() )
20954     CubitUndo::save_state();
20955 
20956   BodySM *sheet_body_sm = NULL;
20957   CubitStatus status = gmeList.get()->create_circle_surface(radius, plane, sheet_body_sm );
20958 
20959   if( status == CUBIT_FAILURE )
20960   {
20961     if(CubitUndo::get_undo_enabled())
20962       CubitUndo::remove_last_undo();
20963     return NULL;
20964   }
20965 
20966   Body *new_body = NULL;
20967   if( sheet_body_sm )
20968     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
20969 
20970   if (new_body)
20971   {
20972     if(CubitUndo::get_undo_enabled())
20973       CubitUndo::note_result_body(new_body);    
20974   }
20975   else
20976   {
20977     if(CubitUndo::get_undo_enabled())
20978       CubitUndo::remove_last_undo();    
20979   }
20980 
20981   return new_body;
20982 }
20983 
20984 Body* GeometryModifyTool::create_circle_surface( RefVertex *v1,
20985                                                        RefVertex *v2,
20986                                                        RefVertex *v3 )
20987 {
20988   if(0 == gmeList.size())
20989   {
20990     PRINT_WARNING("No active geometry engine.\n");
20991     return NULL;
20992   }
20993 
20994   GeometryModifyEngine *GMEPtr = get_engine( v1->get_point_ptr() );
20995 
20996   if( GMEPtr != get_engine( v3->get_point_ptr() ) )
20997   {
20998     PRINT_INFO("Vertices are not from same modeling engine.\n");
20999     return NULL;
21000   }
21001 
21002   TBPoint *pt1, *pt3;
21003 
21004   DLIList<RefVertex*> free_ref_vertices;
21005   if( v1->num_parent_ref_entities() == 0 )
21006   {
21007     free_ref_vertices.append( v1 );
21008     pt1 = v1->get_point_ptr();
21009   }
21010   else
21011     pt1 = GMEPtr->make_Point( v1->coordinates() );
21012 
21013   if( v3->num_parent_ref_entities() == 0 )
21014   {
21015     free_ref_vertices.append( v3 );
21016     pt3 = v3->get_point_ptr();
21017   }
21018   else
21019     pt3 = GMEPtr->make_Point( v3->coordinates() );
21020 
21021 
21022   if( CubitUndo::get_undo_enabled() )
21023   {
21024     if( free_ref_vertices.size() )
21025       CubitUndo::save_state_with_cubit_file( free_ref_vertices, true );
21026     else
21027       CubitUndo::save_state();
21028   }
21029 
21030   BodySM *sheet_body_sm = NULL;
21031   CubitStatus status = GMEPtr->create_circle_surface(pt1, v2->coordinates(), pt3, sheet_body_sm );
21032 
21033   if( status == CUBIT_FAILURE )
21034   {
21035     if(CubitUndo::get_undo_enabled())
21036       CubitUndo::remove_last_undo();
21037     return NULL;
21038   }
21039 
21040   Body *new_body = NULL;
21041   if( sheet_body_sm )
21042     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
21043 
21044   if (new_body)
21045   {
21046     if(CubitUndo::get_undo_enabled())
21047       CubitUndo::note_result_body(new_body);    
21048   }
21049   else
21050   {
21051     if(CubitUndo::get_undo_enabled())
21052       CubitUndo::remove_last_undo();    
21053   }
21054 
21055   return new_body;
21056 }
21057 
21058 Body* GeometryModifyTool::create_circle_surface( RefVertex *v1,
21059                                                        RefVertex *v2,
21060                                                        CubitVector center_point )
21061 {
21062   if(0 == gmeList.size())
21063   {
21064     PRINT_WARNING("No active geometry engine.\n");
21065     return NULL;
21066   }
21067 
21068   GeometryModifyEngine *GMEPtr = get_engine( v1->get_point_ptr() );
21069 
21070   if( GMEPtr != get_engine( v2->get_point_ptr() ) )
21071   {
21072     PRINT_INFO("Vertices are not from same modeling engine.\n");
21073     return NULL;
21074   }
21075 
21076   TBPoint *pt1, *pt2;
21077 
21078   DLIList<RefVertex*> free_ref_vertices;
21079   if( v1->num_parent_ref_entities() == 0 )
21080   {
21081     free_ref_vertices.append( v1 );
21082     pt1 = v1->get_point_ptr();
21083   }
21084   else
21085     pt1 = GMEPtr->make_Point( v1->coordinates() );
21086 
21087   if( v2->num_parent_ref_entities() == 0 )
21088   {
21089     free_ref_vertices.append( v2 );
21090     pt2 = v2->get_point_ptr();
21091   }
21092   else
21093     pt2 = GMEPtr->make_Point( v2->coordinates() );
21094 
21095 
21096   if( CubitUndo::get_undo_enabled() )
21097   {
21098     if( free_ref_vertices.size() )
21099       CubitUndo::save_state_with_cubit_file( free_ref_vertices, true );
21100     else
21101       CubitUndo::save_state();
21102   }
21103 
21104   BodySM *sheet_body_sm = NULL;
21105   CubitStatus status = GMEPtr->create_circle_surface(pt1, pt2, center_point, sheet_body_sm );
21106 
21107   if( status == CUBIT_FAILURE )
21108   {
21109     if(CubitUndo::get_undo_enabled())
21110       CubitUndo::remove_last_undo();
21111     return NULL;
21112   }
21113 
21114   Body *new_body = NULL;
21115   if( sheet_body_sm )
21116     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
21117 
21118   if (new_body)
21119   {
21120     if(CubitUndo::get_undo_enabled())
21121       CubitUndo::note_result_body(new_body);    
21122   }
21123   else
21124   {
21125     if(CubitUndo::get_undo_enabled())
21126       CubitUndo::remove_last_undo();    
21127   }
21128 
21129   return new_body;
21130 }
21131 
21132 Body* GeometryModifyTool::create_ellipse_surface( RefVertex *v1,
21133                                                   RefVertex *v2,
21134                                                   CubitVector center_point )
21135 {
21136   if(0 == gmeList.size())
21137   {
21138     PRINT_WARNING("No active geometry engine.\n");
21139     return NULL;
21140   }
21141 
21142   GeometryModifyEngine *GMEPtr = get_engine( v1->get_point_ptr() );
21143 
21144   if( GMEPtr != get_engine( v2->get_point_ptr() ) )
21145   {
21146     PRINT_INFO("Vertices are not from same modeling engine.\n");
21147     return NULL;
21148   }
21149 
21150   TBPoint *pt1, *pt2;
21151 
21152   DLIList<RefVertex*> free_ref_vertices;
21153   if( v1->num_parent_ref_entities() == 0 )
21154   {
21155     free_ref_vertices.append( v1 );
21156     pt1 = v1->get_point_ptr();
21157   }
21158   else
21159     pt1 = GMEPtr->make_Point( v1->coordinates() );
21160 
21161   if( v2->num_parent_ref_entities() == 0 )
21162   {
21163     free_ref_vertices.append( v2 );
21164     pt2 = v2->get_point_ptr();
21165   }
21166   else
21167     pt2 = GMEPtr->make_Point( v2->coordinates() );
21168 
21169   if( CubitUndo::get_undo_enabled() )
21170   {
21171     if( free_ref_vertices.size() )
21172       CubitUndo::save_state_with_cubit_file( free_ref_vertices, true );
21173     else
21174       CubitUndo::save_state();
21175   }
21176 
21177   BodySM *sheet_body_sm = NULL;
21178   CubitStatus status = GMEPtr->create_ellipse_surface(pt1, pt2, center_point, sheet_body_sm );
21179 
21180   if( status == CUBIT_FAILURE )
21181   {
21182     if(CubitUndo::get_undo_enabled())
21183       CubitUndo::remove_last_undo();
21184     return NULL;
21185   }
21186 
21187   Body *new_body = NULL;
21188   if( sheet_body_sm )
21189     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
21190 
21191   if (new_body)
21192   {
21193     if(CubitUndo::get_undo_enabled())
21194       CubitUndo::note_result_body(new_body);    
21195   }
21196   else
21197   {
21198     if(CubitUndo::get_undo_enabled())
21199       CubitUndo::remove_last_undo();    
21200   }
21201 
21202   return new_body;
21203 }
21204 
21205 Body* GeometryModifyTool::create_ellipse_surface( double major_radius,
21206                                                   double minor_radius,
21207                                                   CubitVector plane )
21208 {
21209   if(0 == gmeList.size())
21210   {
21211     PRINT_WARNING("No active geometry engine.\n");
21212     return NULL;
21213   }
21214 
21215   if( major_radius <= GEOMETRY_RESABS || minor_radius <= GEOMETRY_RESABS )
21216   {
21217     PRINT_ERROR("Values must be positive\n");
21218     return NULL;
21219   }
21220 
21221   if( CubitUndo::get_undo_enabled() )
21222     CubitUndo::save_state();
21223 
21224   BodySM *sheet_body_sm = NULL;
21225   CubitStatus status = gmeList.get()->create_ellipse_surface(major_radius, minor_radius, plane, sheet_body_sm );
21226 
21227   if( status == CUBIT_FAILURE )
21228   {
21229     if(CubitUndo::get_undo_enabled())
21230       CubitUndo::remove_last_undo();
21231     return NULL;
21232   }
21233 
21234   Body *new_body = NULL;
21235   if( sheet_body_sm )
21236     new_body = GeometryQueryTool::instance()->make_Body(sheet_body_sm);
21237 
21238   if (new_body)
21239   {
21240     if(CubitUndo::get_undo_enabled())
21241       CubitUndo::note_result_body(new_body);    
21242   }
21243   else
21244   {
21245     if(CubitUndo::get_undo_enabled())
21246       CubitUndo::remove_last_undo();    
21247   }
21248 
21249   return new_body;
21250 }
21251 
21252 CubitStatus GeometryModifyTool::create_curve_helix( CubitVector &location,
21253                                                     CubitVector &direction,
21254                                                     CubitVector &start_point,
21255                                                     double &thread_distance,
21256                                                     double &angle,
21257                                                     bool right_handed,
21258                                                     RefEdge *&new_ref_edge_ptr)
21259 {
21260   if (0 == gmeList.size())
21261   {
21262     PRINT_WARNING("No active geometry engine.\n");
21263     return CUBIT_FAILURE;
21264   }
21265 
21266   Curve *new_curve = gmeList.get()->create_curve_helix(location, direction,
21267                                                 start_point, thread_distance,
21268                                                 angle, right_handed );
21269 
21270   if (new_curve == NULL)
21271     return CUBIT_FAILURE;
21272 
21273   if( CubitUndo::get_undo_enabled() )
21274     CubitUndo::save_state();
21275 
21276   new_ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
21277 
21278   if( CubitUndo::get_undo_enabled() )
21279     CubitUndo::note_result_entity( new_ref_edge_ptr );
21280 
21281   return CUBIT_SUCCESS;
21282 }
21283 
21284 void GeometryModifyTool::remove_bodies_outside_bounding_box(
21285   DLIList<Body*> &body_list,
21286     CubitBox &tool_bounding_box )
21287 {
21288   //remove bodies that don't overlap
21289   for( int k=body_list.size(); k--; )
21290   {
21291     Body *tmp_body = body_list.get();
21292     if( !tool_bounding_box.overlap( 0.001, tmp_body->bounding_box() ) )
21293       body_list.change_to( NULL );
21294     body_list.step();
21295   }
21296 
21297   body_list.remove_all_with_value(NULL);
21298 }
21299 
21300 
21301 
21302 void GeometryModifyTool::remove_bodies_outside_bounding_box(
21303   DLIList<Body*> &body_list,
21304     CubitVector v1, CubitVector v2, CubitVector v3 )
21305 {
21306     //create a bounding box from the body list and the passed in points
21307     CubitBox bbox1;
21308     for( int k=body_list.size(); k--; )
21309         bbox1 |= body_list.get_and_step()->bounding_box();
21310 
21311   //add in the pts
21312   bbox1 |= v1;
21313   bbox1 |= v2;
21314   bbox1 |= v3;
21315 
21316     //get the diagonal of the bounding box
21317   double diagonal_length = bbox1.diagonal().length();
21318 
21319     //offset each point by the diagonal
21320   CubitVector new_pt;
21321   CubitVector direction;
21322   direction = v2-v1;
21323   direction.normalize();
21324   new_pt = v1 + direction*diagonal_length;
21325 
21326   CubitBox bbox2( new_pt );
21327 
21328   direction = v3-v1;
21329   direction.normalize();
21330   new_pt = v1 + direction*diagonal_length;
21331   bbox2 |= new_pt;
21332 
21333   direction = v1-v2;
21334   direction.normalize();
21335   new_pt = v2 + direction*diagonal_length;
21336   bbox2 |= new_pt;
21337   direction = v3-v2;
21338   direction.normalize();
21339   new_pt = v2 + direction*diagonal_length;
21340   bbox2 |= new_pt;
21341 
21342   direction = v1-v3;
21343   direction.normalize();
21344   new_pt = v3 + direction*diagonal_length;
21345   bbox2 |= new_pt;
21346   direction = v2-v3;
21347   direction.normalize();
21348   new_pt = v3 + direction*diagonal_length;
21349   bbox2 |= new_pt;
21350 
21351   //remove bodies that don't overlap
21352   for( int k=body_list.size(); k--; )
21353   {
21354     Body *tmp_body = body_list.get();
21355     if( !bbox2.overlap( 0.001, tmp_body->bounding_box() ) )
21356       body_list.change_to( NULL );
21357     body_list.step();
21358   }
21359 
21360   body_list.remove_all_with_value(NULL);
21361 }
21362 
21363 CubitStatus prepare_surface_sweep(
21364                               DLIList<BodySM*> &blank_bodies,
21365                               DLIList<Surface*> &surfaces,
21366                               const CubitVector& sweep_vector,
21367                               bool sweep_perp,
21368                               bool through_all,
21369                               bool outward,
21370                               bool up_to_next,
21371                               Surface *stop_surf,
21372                               Curve *curve_to_sweep_along,
21373                               BodySM* &cutting_tool_ptr ,
21374                               const CubitVector* point ,
21375                               double *angle )
21376 {
21377   GeometryModifyEngine* gme = GeometryModifyTool::instance()->
21378                                   get_engine(blank_bodies.get());
21379 
21380   if(surfaces.size() == 0 )
21381     return CUBIT_FAILURE;
21382 
21383   DLIList<GeometryEntity*> ref_ent_list;
21384   Surface * temp_face = NULL;
21385   for(int i = 0; i < surfaces.size(); i++)
21386     {
21387       //copy the faces before sweep
21388       temp_face = gme->make_Surface(surfaces.get_and_step());
21389       if (temp_face)
21390         ref_ent_list.append((GeometryEntity*)temp_face);
21391     }
21392 
21393   BodySM* to_body = NULL;
21394   CubitStatus stat = CUBIT_SUCCESS;
21395   if(up_to_next && blank_bodies.size() > 1) //unite all bland_bodies
21396     {
21397        DLIList<BodySM*> newBodies;
21398        DLIList<BodySM*> copied_bodies;
21399        for(int i = 0; i < blank_bodies.size(); i++)
21400          copied_bodies.append(gme->copy_body(blank_bodies.get_and_step()));
21401 
21402        stat = gme->unite(copied_bodies, newBodies);
21403        if(stat == CUBIT_FAILURE)
21404          {
21405            PRINT_ERROR("Cannot use 'up_to_next' option with specified geometry\n");
21406            PRINT_INFO("Try the 'stop surface <id>' option instead\n");
21407            return stat;
21408          }
21409        to_body = newBodies.get();
21410     }
21411 
21412   else if(up_to_next && blank_bodies.size() == 1)
21413     to_body = gme->copy_body(blank_bodies.get());
21414 
21415   DLIList<BodySM*> swept_bodies;
21416   if (point && angle) //sweep_surface_rotated
21417     stat = gme->sweep_rotational(ref_ent_list,swept_bodies,*point,
21418                            sweep_vector, *angle,0, 0.0,0,false,false,
21419                            false,stop_surf, to_body);
21420 
21421   else
21422   {
21423     CubitVector tmp_sweep_vector = sweep_vector;
21424 
21425     //get model bbox info...will scale sweep vector by its diagonal
21426     //so that we go far enough
21427     if( through_all || stop_surf || up_to_next)
21428     {
21429       CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box();
21430       tmp_sweep_vector.normalize();
21431       tmp_sweep_vector*=(2*bounding_box.diagonal().length());
21432     }
21433 
21434     //see if we're sweeping along a specified curve
21435     if( curve_to_sweep_along )
21436       {
21437         DLIList<Curve*> curves_to_sweep_along;
21438         curves_to_sweep_along.append(curve_to_sweep_along);
21439         stat = gme->sweep_along_curve(ref_ent_list, swept_bodies,
21440                                  curves_to_sweep_along, 0.0,0,false,stop_surf,
21441                                  to_body);
21442       }
21443 
21444     else if (sweep_perp )
21445       stat = gme->sweep_perpendicular(ref_ent_list, swept_bodies,
21446                                  tmp_sweep_vector.length(),0.0,0,!outward,false,
21447                                  stop_surf, to_body);
21448     else
21449       stat = gme->sweep_translational(ref_ent_list, swept_bodies,
21450                                  tmp_sweep_vector,0.0,0, false, false, stop_surf,
21451                                  to_body);
21452   }
21453 
21454   if(stat == CUBIT_FAILURE || swept_bodies.size() == 0)
21455     {
21456        //delete copied faces
21457        GeometryEntity * temp_entity = NULL;
21458        for(int i = ref_ent_list.size();i--;)
21459          {
21460             temp_entity = ref_ent_list.get_and_step();
21461             if (temp_entity)
21462               gme->get_gqe()->delete_solid_model_entities( (Surface*)temp_entity);
21463          }
21464 
21465        return stat;
21466     }
21467 
21468   //if there are more than 1, unite them all
21469   DLIList<BodySM*>  newBodies;
21470   if (swept_bodies.size() > 1)
21471      stat = gme->unite(swept_bodies, newBodies);
21472   else
21473      newBodies = swept_bodies;
21474 
21475   if(stat == CUBIT_FAILURE || newBodies.size()!= 1)
21476     {
21477        PRINT_ERROR("webcut tool body is not created from occ.\n");
21478        //delete the swept_bodies
21479        BodySM* tmp_body = NULL;
21480        for (int i = swept_bodies.size(); i--;)
21481          {
21482            tmp_body= swept_bodies.get_and_step();
21483            if (tmp_body)
21484              gme->get_gqe()->delete_solid_model_entities(tmp_body);
21485          }
21486 
21487        //delete copied faces
21488        GeometryEntity * temp_entity = NULL;
21489        for(int i = ref_ent_list.size();i--;)
21490          {
21491             temp_entity = ref_ent_list.get_and_step();
21492             if (temp_entity)
21493               gme->get_gqe()->delete_solid_model_entities( (Surface*)temp_entity);
21494          }
21495        return CUBIT_FAILURE;
21496     }
21497 
21498     cutting_tool_ptr = newBodies.get();
21499     return stat;
21500 }
21501 
21502 
21503 
21504 //******************************************************************************************************************************
21505 CubitVector GeometryModifyTool::FindExtendedEndPt( double outer_rad , double inner_rad , CubitVector inner_AxisPt ,
21506                                                     CubitVector Axis , double Height )
21507 {
21508     CubitVector Extended_End_Pt;
21509 
21510     double Diff     = (outer_rad - inner_rad);
21511            Diff    /= Height;
21512     double dAngle   = atan ( Diff ) ;
21513     Axis.normalize();
21514 
21515     double dTan        = tan( dAngle );
21516     double dExtendvalue = inner_rad / dTan;
21517 
21518     CubitVector ExtendedPt;
21519     ExtendedPt.x( ( Axis.x() * dExtendvalue )  + inner_AxisPt.x() );
21520     ExtendedPt.y( ( Axis.y() * dExtendvalue )  + inner_AxisPt.y() );
21521     ExtendedPt.z( ( Axis.z() * dExtendvalue )  + inner_AxisPt.z() );
21522 
21523     return ExtendedPt;
21524 }
21525 //**********************************************************************************************************************************
21526 CubitVector GeometryModifyTool::FindExtendedStartPt( CubitBox Box , double outer_rad , double inner_rad , CubitVector AxisPt ,
21527                                                     CubitVector Axis , double &dLength , double dTanAngle,  double &dExtendedadius )
21528 {
21529     CubitVector Extended_Start_Pt;
21530 
21531     // Find the Difference between the Max and thre min values in all 3 directions.
21532     // Incase the point is within the box limits, then add the difference values
21533     // in all 3 directions , witht he " Axis " as the direction vector and extend the point.
21534 
21535     // After that find the Radius of this bigger end.
21536 
21537     CubitVector DiffVec;
21538 
21539     Axis.normalize();
21540 
21541     DiffVec.x( fabs( Box.max_x() - Box.min_x() ));
21542     DiffVec.y( fabs( Box.max_y() - Box.min_y() ));
21543     DiffVec.z( fabs( Box.max_z() - Box.min_z() ));
21544 
21545     // Extend the start Pt
21546 
21547     Extended_Start_Pt.x( AxisPt.x() + ( Axis.x() * DiffVec.x() ) );
21548     Extended_Start_Pt.y( AxisPt.y() + ( Axis.y() * DiffVec.y() ) );
21549     Extended_Start_Pt.z( AxisPt.z() + ( Axis.z() * DiffVec.z() ) );
21550 
21551 
21552     // Find the length
21553 
21554     dLength = sqrt( (( AxisPt.x() - Extended_Start_Pt.x()) *  (AxisPt.x() - Extended_Start_Pt.x()) ) +
21555                            (( AxisPt.y() - Extended_Start_Pt.y()) *  (AxisPt.y() - Extended_Start_Pt.y()) ) +
21556                            (( AxisPt.z() - Extended_Start_Pt.z()) *  (AxisPt.z() - Extended_Start_Pt.z()) ) );
21557 
21558 
21559 
21560     // Find the Extended Radius
21561 
21562     dExtendedadius = outer_rad + ( tan( dTanAngle ) * dLength ) ;
21563 
21564     return Extended_Start_Pt;
21565 }
21566 //*****************************************************************************************************************************************
21567 void GeometryModifyTool::FindExtendedPoints( CubitVector AxisPt1 , CubitVector AxisPt2 , double outer_radius , double inner_radius ,
21568             CubitVector axis,double Height , CubitBox bounding_box , double dTanAngle ,
21569             CubitVector& start , CubitVector& end , double& dExtended_OuterRadius, double& dExtended_InnerRadius  )
21570 {
21571 
21572     CubitVector endpt ;
21573     if( outer_radius > inner_radius )
21574     {
21575         endpt  = FindExtendedEndPt( outer_radius , inner_radius , AxisPt2 , axis,  Height );
21576         Height = sqrt( (endpt.x() - AxisPt1.x()) * (endpt.x() - AxisPt1.x())+
21577             (endpt.y() - AxisPt1.y()) * (endpt.y() - AxisPt1.y())+
21578             (endpt.z() - AxisPt1.z()) * (endpt.z() - AxisPt1.z()) );
21579 
21580         AxisPt2.x( endpt.x() );
21581         AxisPt2.y( endpt.y() );
21582         AxisPt2.z( endpt.z() );
21583 
21584         end.x( endpt.x() );
21585         end.y( endpt.y() );
21586         end.z( endpt.z() );
21587 
21588         dExtended_InnerRadius = 0;
21589     }
21590     else
21591     {
21592         // reverse the axis.
21593 
21594         axis.x( -axis.x());
21595         axis.y( -axis.y());
21596         axis.z( -axis.z());
21597 
21598         endpt  = FindExtendedEndPt( inner_radius , outer_radius , AxisPt1 , axis,  Height );
21599         Height = sqrt( (endpt.x() - AxisPt2.x()) * (endpt.x() - AxisPt2.x())+
21600             (endpt.y() - AxisPt2.y()) * (endpt.y() - AxisPt2.y())+
21601             (endpt.z() - AxisPt2.z()) * (endpt.z() - AxisPt2.z()) );
21602 
21603         AxisPt1.x( endpt.x() );
21604         AxisPt1.y( endpt.y() );
21605         AxisPt1.z( endpt.z() );
21606 
21607         start.x( endpt.x() );
21608         start.y( endpt.y() );
21609         start.z( endpt.z() );
21610 
21611         // reset the axis.
21612         axis.x( -axis.x());
21613         axis.y( -axis.y());
21614         axis.z( -axis.z());
21615 
21616 
21617         dExtended_OuterRadius = 0;
21618 
21619      }
21620 
21621 
21622 
21623     //*****************************************//
21624     // Now find the extension of the bigger end.
21625     //*****************************************//
21626 
21627     if( outer_radius > inner_radius )
21628     {
21629         // reverse the axis.
21630         axis.x( -axis.x());
21631         axis.y( -axis.y());
21632         axis.z( -axis.z());
21633 
21634 
21635         endpt  = FindExtendedStartPt( bounding_box , outer_radius , inner_radius , AxisPt1 , axis,  Height , dTanAngle , dExtended_OuterRadius );
21636         Height = sqrt( (endpt.x() - AxisPt2.x()) * (endpt.x() - AxisPt2.x())+
21637             (endpt.y() - AxisPt2.y()) * (endpt.y() - AxisPt2.y())+
21638             (endpt.z() - AxisPt2.z()) * (endpt.z() - AxisPt2.z()) );
21639 
21640         AxisPt1.x( endpt.x() );
21641         AxisPt1.y( endpt.y() );
21642         AxisPt1.z( endpt.z() );
21643 
21644         start.x( endpt.x() );
21645         start.y( endpt.y() );
21646         start.z( endpt.z() );
21647 
21648         // reverse the axis.
21649         axis.x( -axis.x());
21650         axis.y( -axis.y());
21651         axis.z( -axis.z());
21652 
21653     }
21654     else
21655     {
21656         endpt  = FindExtendedStartPt( bounding_box ,  inner_radius , outer_radius , AxisPt2 , axis,  Height , dTanAngle , dExtended_InnerRadius );
21657         Height = sqrt( (endpt.x() - AxisPt1.x()) * (endpt.x() - AxisPt1.x())+
21658             (endpt.y() - AxisPt1.y()) * (endpt.y() - AxisPt1.y())+
21659             (endpt.z() - AxisPt1.z()) * (endpt.z() - AxisPt1.z()) );
21660 
21661         AxisPt2.x( endpt.x() );
21662         AxisPt2.y( endpt.y() );
21663         AxisPt2.z( endpt.z() );
21664 
21665         end.x( endpt.x() );
21666         end.y( endpt.y() );
21667         end.z( endpt.z() );
21668     }
21669 }
21670 
21671 //This function gets called after RefEntities have been created
21672 //on TopologyBridges.  It builds up a map from original RefEntity 
21673 //to the copy RefEntity.  Used when copying Bodies, RefFaces, and
21674 //RefEdges.
21675 CubitStatus GeometryModifyTool::create_old_to_new_ref_ent_map( 
21676    TopologyBridge *old_top_level_bridge,
21677    TopologyBridge *new_top_level_bridge,
21678    std::map< RefEntity*, RefEntity* > &old_to_new_map,
21679    std::map< TopologyBridge*, TopologyBridge*> &old_tb_to_new_tb )
21680 {
21681   std::vector< std::pair<TopologyBridge*, TopologyBridge*> > unmatched_pairs;
21682   bool debug = false;
21683   std::map< TopologyBridge*, TopologyBridge*>::iterator iter;  
21684 
21685   //This first loop tries to find a RefEntity on each TopologyBridge pair in the
21686   //map 'old_tb_to_new_tb'.  If there is no virtual geometry here, everything
21687   //should be found.  If it didn't find a RefEntity, put it in the 
21688   //unmatched_pairs vector.
21689   for( iter = old_tb_to_new_tb.begin(); iter!=old_tb_to_new_tb.end(); iter++ )
21690   {
21691     std::pair<TopologyBridge*, TopologyBridge*> tmp_pair = *iter;
21692     TopologyBridge *old_tb = tmp_pair.first;
21693     TopologyBridge *new_tb = tmp_pair.second;
21694 
21695     TopologyEntity *te_old = old_tb->topology_entity();
21696     TopologyEntity *te_new = new_tb->topology_entity();
21697 
21698     if( te_old && te_new )
21699     {
21700       RefEntity *old_ref_ent = dynamic_cast<RefEntity*>(te_old);
21701       RefEntity *new_ref_ent = dynamic_cast<RefEntity*>(te_new);
21702 
21703       if( old_ref_ent && new_ref_ent )
21704       {
21705         if( debug )
21706           PRINT_INFO("%s %d ---> %s %d\n", 
21707           old_ref_ent->class_name(), old_ref_ent->id(),
21708           new_ref_ent->class_name(), new_ref_ent->id() );
21709 
21710         old_to_new_map.insert( std::make_pair( old_ref_ent, new_ref_ent ) );
21711       }
21712       else
21713         unmatched_pairs.push_back( tmp_pair );
21714     }
21715     else
21716       unmatched_pairs.push_back( tmp_pair );
21717   }  
21718 
21719   //Virtual geometry will be in unmatched pairs.  Composite will have an n-to-1 
21720   //TB-to-RefEntity mapping.  So it might try to stuff duplicate pairs into the 
21721   //map, but that's alright.
21722   for( size_t k=0; k<unmatched_pairs.size(); k++ )
21723   {
21724     std::pair<TopologyBridge*, TopologyBridge*> tmp_pair = unmatched_pairs[k];
21725 
21726     TopologyBridge *old_tb = tmp_pair.first;
21727     TopologyBridge *new_tb = tmp_pair.second;
21728 
21729     //get the owner tbs associate with old_tb
21730     DLIList<TopologyBridge*> old_owner_tbs;
21731     GeometryQueryTool::instance()->get_tbs_with_bridge_manager_as_owner( old_tb, old_owner_tbs );
21732 
21733     DLIList<TopologyBridge*> new_owner_tbs;
21734     GeometryQueryTool::instance()->get_tbs_with_bridge_manager_as_owner( new_tb, new_owner_tbs );
21735     
21736     if( old_owner_tbs.size() && old_owner_tbs.size() == new_owner_tbs.size() )
21737     {
21738       if( old_owner_tbs.size() == 1 && new_owner_tbs.size() == 1 ) //composite case
21739       {
21740         TopologyEntity *te_old = old_owner_tbs.get()->topology_entity();
21741         TopologyEntity *te_new = new_owner_tbs.get()->topology_entity();
21742 
21743         if( te_old && te_new )
21744         {
21745           RefEntity *old_ref_ent = dynamic_cast<RefEntity*>(te_old);
21746           RefEntity *new_ref_ent = dynamic_cast<RefEntity*>(te_new);
21747 
21748           if( old_ref_ent && new_ref_ent )
21749           {
21750             if( debug )
21751               PRINT_INFO("Virtual: %s %d ---> %s %d\n", 
21752               old_ref_ent->class_name(), old_ref_ent->id(),
21753               new_ref_ent->class_name(), new_ref_ent->id() );
21754 
21755             old_to_new_map.insert( std::make_pair( old_ref_ent, new_ref_ent ) );
21756 
21757             old_tb_to_new_tb.insert( std::make_pair( old_owner_tbs.get(), new_owner_tbs.get() ) );
21758           }
21759         }        
21760       }      
21761     }
21762   }
21763 
21764   //Partitions can hide entities because of the the n-to-m mapping.
21765   //The solution is to get all the child TB lumps, surface, curves, and
21766   //points.  
21767   double tol_sq = old_top_level_bridge->get_geometry_query_engine()->get_sme_resabs_tolerance();
21768   tol_sq *= tol_sq;
21769 
21770   DLIList<Lump*> old_lumps, new_lumps;
21771   DLIList<Surface*> old_surfaces, new_surfaces;
21772   DLIList<Curve*> old_curves, new_curves;
21773   DLIList<TBPoint*> old_points, new_points;
21774   
21775   if( dynamic_cast<BodySM*>(old_top_level_bridge) )
21776   {
21777     old_top_level_bridge->lumps( old_lumps );
21778     old_top_level_bridge->surfaces( old_surfaces );
21779     new_top_level_bridge->lumps( new_lumps );
21780     new_top_level_bridge->surfaces( new_surfaces );
21781   }
21782 
21783   old_top_level_bridge->curves( old_curves );
21784   old_top_level_bridge->points( old_points ); 
21785   new_top_level_bridge->curves( new_curves );
21786   new_top_level_bridge->points( new_points );
21787 
21788   //If it is already in the map, it has been paired to something.
21789   //Remove it from the list and forget about it.
21790   for( int k=0; k<old_lumps.size(); k++ )
21791   {
21792     //if it is found, make it NULL in the list
21793     iter = old_tb_to_new_tb.find( old_lumps[k] );
21794     if( iter != old_tb_to_new_tb.end() )
21795     {
21796       old_lumps[k] = NULL;
21797       if( new_lumps.move_to( (Lump*)iter->second ) )
21798         new_lumps.change_to( NULL );
21799     }
21800   }
21801   for( int k=0; k<old_surfaces.size(); k++ )
21802   {
21803     //if it is found, make it NULL in the list
21804     iter = old_tb_to_new_tb.find( old_surfaces[k] );
21805     if( iter != old_tb_to_new_tb.end() )
21806     {
21807       old_surfaces[k] = NULL;
21808       if( new_surfaces.move_to( (Surface*)iter->second ) )
21809         new_surfaces.change_to( NULL );
21810     }
21811   }
21812   for( int k=0; k<old_curves.size(); k++ )
21813   {
21814     //if it is found, make it NULL in the list
21815     iter = old_tb_to_new_tb.find( old_curves[k] );
21816     if( iter != old_tb_to_new_tb.end() )
21817     {
21818       old_curves[k] = NULL;
21819       if( new_curves.move_to( (Curve*)iter->second ) )
21820         new_curves.change_to( NULL );
21821     }
21822   }
21823   for( int k=0; k<old_points.size(); k++ )
21824   {
21825     //if it is found, make it NULL in the list
21826     iter = old_tb_to_new_tb.find( old_points[k] );
21827     if( iter != old_tb_to_new_tb.end() )
21828     {
21829       old_points[k] = NULL;
21830       if( new_points.move_to( (TBPoint*)iter->second ) )
21831         new_points.change_to( NULL );
21832     }
21833   }
21834 
21835   //Remove all the NULL-ed out stuff
21836   old_lumps.remove_all_with_value(NULL);
21837   old_surfaces.remove_all_with_value(NULL);
21838   old_curves.remove_all_with_value(NULL);
21839   old_points.remove_all_with_value(NULL);
21840 
21841   new_lumps.remove_all_with_value(NULL);
21842   new_surfaces.remove_all_with_value(NULL);
21843   new_curves.remove_all_with_value(NULL);
21844   new_points.remove_all_with_value(NULL);
21845 
21846   //should have exact correspondence
21847   if( old_lumps.size() != new_lumps.size() )
21848     return CUBIT_FAILURE;
21849   if( old_surfaces.size() != new_surfaces.size() )
21850     return CUBIT_FAILURE;
21851   if( old_curves.size() != new_curves.size() )
21852     return CUBIT_FAILURE;
21853   if( old_points.size() != new_points.size() )
21854     return CUBIT_FAILURE;
21855 
21856   //If we are here, there are partitions we have to resolve.  The only way to do it 
21857   //is a brute force approach.  It's save to use a tolerance since we know the 
21858   //entities will be exactly on top of each other.  
21859   for( int k=0; k<old_surfaces.size(); k++ )
21860   {
21861     Surface *old_surf = old_surfaces[k];
21862     CubitBox old_bbox = old_surf->bounding_box();
21863 
21864     for( int j=0; j<new_surfaces.size(); j++ )
21865     {
21866       Surface *new_surf = new_surfaces[j];
21867       if( new_surf )
21868       {
21869         CubitBox new_bbox = new_surf->bounding_box();          
21870         if( old_bbox.center().distance_between_squared( new_bbox.center() ) < tol_sq )
21871         {
21872           if( fabs(old_bbox.diagonal().length_squared() - 
21873             new_bbox.diagonal().length_squared() ) < tol_sq )
21874           {
21875             TopologyEntity *te_old = old_surf->topology_entity();
21876             TopologyEntity *te_new = new_surf->topology_entity();
21877 
21878             if( te_old && te_new )
21879             {
21880               RefEntity *old_ref_ent = dynamic_cast<RefEntity*>(te_old);
21881               RefEntity *new_ref_ent = dynamic_cast<RefEntity*>(te_new);
21882 
21883               if( old_ref_ent && new_ref_ent )
21884               {
21885                 if( debug )
21886                   PRINT_INFO("Partition: %s %d ---> %s %d\n", 
21887                   old_ref_ent->class_name(), old_ref_ent->id(),
21888                   new_ref_ent->class_name(), new_ref_ent->id() );
21889 
21890                 old_to_new_map.insert( std::make_pair( old_ref_ent, new_ref_ent ) );
21891                 new_surfaces[j] = NULL;
21892                 break;
21893               }
21894             }
21895           }
21896         }
21897       }
21898     }
21899   }
21900 
21901   //Curves
21902   for( int k=0; k<old_curves.size(); k++ )
21903   {
21904     Curve *old_curve = old_curves[k];
21905     CubitBox old_bbox = old_curve->bounding_box();
21906 
21907     for( int j=0; j<new_curves.size(); j++ )
21908     {
21909       Curve *new_curve = new_curves[j];
21910       if( new_curve )
21911       {
21912         CubitBox new_bbox = new_curve->bounding_box();          
21913         if( old_bbox.center().distance_between_squared( new_bbox.center() ) < tol_sq )
21914         {
21915           if( fabs(old_bbox.diagonal().length_squared() - 
21916             new_bbox.diagonal().length_squared() ) < tol_sq )
21917           {
21918             TopologyEntity *te_old = old_curve->topology_entity();
21919             TopologyEntity *te_new = new_curve->topology_entity();
21920 
21921             if( te_old && te_new )
21922             {
21923               RefEntity *old_ref_ent = dynamic_cast<RefEntity*>(te_old);
21924               RefEntity *new_ref_ent = dynamic_cast<RefEntity*>(te_new);
21925 
21926               if( old_ref_ent && new_ref_ent )
21927               {
21928                 if( debug )
21929                   PRINT_INFO("Partition: %s %d ---> %s %d\n", 
21930                   old_ref_ent->class_name(), old_ref_ent->id(),
21931                   new_ref_ent->class_name(), new_ref_ent->id() );
21932 
21933                 old_to_new_map.insert( std::make_pair( old_ref_ent, new_ref_ent ) );
21934                 new_curves[j] = NULL;
21935                 break;
21936               }
21937             }
21938           }
21939         }
21940       }
21941     }
21942   }
21943 
21944   //Points
21945   for( int k=0; k<old_points.size(); k++ )
21946   {
21947     TBPoint *old_point = old_points[k];
21948     CubitBox old_bbox = old_point->bounding_box();
21949 
21950     for( int j=0; j<new_points.size(); j++ )
21951     {
21952       TBPoint *new_point = new_points[j];
21953       if( new_point )
21954       {
21955         CubitBox new_bbox = new_point->bounding_box();          
21956         if( old_bbox.center().distance_between_squared( new_bbox.center() ) < tol_sq )
21957         {
21958           if( fabs(old_bbox.diagonal().length_squared() - 
21959             new_bbox.diagonal().length_squared() ) < tol_sq )
21960           {
21961             TopologyEntity *te_old = old_point->topology_entity();
21962             TopologyEntity *te_new = new_point->topology_entity();
21963 
21964             if( te_old && te_new )
21965             {
21966               RefEntity *old_ref_ent = dynamic_cast<RefEntity*>(te_old);
21967               RefEntity *new_ref_ent = dynamic_cast<RefEntity*>(te_new);
21968 
21969               if( old_ref_ent && new_ref_ent )
21970               {
21971                 if( debug )
21972                   PRINT_INFO("Partition: %s %d ---> %s %d\n", 
21973                   old_ref_ent->class_name(), old_ref_ent->id(),
21974                   new_ref_ent->class_name(), new_ref_ent->id() );
21975 
21976                 old_to_new_map.insert( std::make_pair( old_ref_ent, new_ref_ent ) );
21977                 new_points[j] = NULL;
21978                 break;
21979               }
21980             }
21981           }
21982         }
21983       }
21984     }
21985   }
21986 
21987   return CUBIT_SUCCESS;
21988 
21989 }
21990 
21991 //author: Jane Hu
21992 //Date Created: Jan. 9, 2013
21993 CubitStatus webcut_w_cylinder( DLIList<BodySM*> &webcut_body_list,
21994                                double radius,
21995                                const CubitVector &axis,
21996                                const CubitVector &center,
21997                                DLIList<BodySM*>& neighbor_imprint_list,
21998                                DLIList<BodySM*>& results_list,
21999                                ImprintType imprint_type )
22000 {
22001   GeometryModifyEngine* gme = 0;
22002   gme = GeometryModifyTool::instance()->
22003                     get_engine(webcut_body_list.get());
22004   assert(gme);
22005 
22006   double max_size =  0.;
22007   //lets find the distance to the center for each body and take
22008   //the max.
22009   double curr;
22010   CubitVector cent_bod;
22011   CubitBox bounding_box;
22012   BodySM *body_ptr;
22013   bounding_box = webcut_body_list[0]->bounding_box();
22014   cent_bod =  bounding_box.center();
22015   cent_bod = cent_bod - center;
22016   curr = cent_bod.length();
22017   if ( curr > max_size )
22018      max_size = curr;
22019 
22020 
22021   for ( int ii = webcut_body_list.size()-1; ii > 0; ii-- )
22022     {
22023       body_ptr = webcut_body_list[ii];
22024       bounding_box |= body_ptr->bounding_box();
22025       cent_bod = body_ptr->bounding_box().center();
22026       cent_bod = cent_bod - center;
22027       curr = cent_bod.length();
22028       if ( curr > max_size )
22029         max_size = curr;
22030     }
22031 
22032   curr = bounding_box.diagonal().length();
22033 
22034   if ( curr > max_size )
22035      max_size = curr;
22036 
22037   double height = 0.0;
22038   if ( center.x() > max_size )
22039     {
22040       height = 500.0 * center.x();
22041     }
22042   else if ( center.y() > max_size )
22043     {
22044       height = 500.0 * center.y();
22045     }
22046   else if ( center.z() > max_size )
22047     {
22048       height = 500.0 * center.z();
22049     }
22050   else
22051     {
22052       height = 500.0 * max_size;
22053     }
22054 
22055   //lets make certain we have a valid height..
22056   if ( height < GEOMETRY_RESABS )
22057     {
22058       height = 500.0;
22059     }
22060 
22061   BodySM *cutting_tool_ptr = gme->cylinder( height, radius, radius, radius );
22062 
22063   if( cutting_tool_ptr == NULL )
22064     return CUBIT_FAILURE;
22065 
22066   //transform the cyclinder to cernter and axis
22067   // The current frustum is centered on the z axis.
22068   CubitVector axis2(0., 0., 1.0 );
22069   //now find the normal to the current axis and axis we want to be
22070   //at. This normal is where we will rotate about.
22071   CubitVector normal_axis = axis2 * axis;
22072   if ( normal_axis.length() > CUBIT_RESABS )
22073     {
22074        //angle in degrees.
22075        double angle = normal_axis.vector_angle( axis2, axis );
22076        gme->get_gqe()->rotate(cutting_tool_ptr, normal_axis, angle);
22077     }
22078   gme->get_gqe()->translate(cutting_tool_ptr, center);
22079 
22080   CubitStatus stat = gme->webcut( webcut_body_list, cutting_tool_ptr,
22081               neighbor_imprint_list, results_list, imprint_type) ;
22082 
22083   // Delete the BodySM that was created to be used as a tool
22084   gme->get_gqe()->delete_solid_model_entities(cutting_tool_ptr) ;
22085 
22086   return stat;
22087 }
22088 
22089 //*********************************************************************************************************************************************************************
22090 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines