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   }