[cgma-dev] r3496 - in cgm/branches/merge-cubit12/geom/ACIS_SRC: . gtcAttrib gtcAttrib/incl gtcAttrib/src

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Tue Jan 26 20:15:24 CST 2010


Author: kraftche
Date: 2010-01-26 20:15:23 -0600 (Tue, 26 Jan 2010)
New Revision: 3496

Added:
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.hpp
Modified:
   cgm/branches/merge-cubit12/geom/ACIS_SRC/
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisBridge.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisDrawTool.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisEdgeTool.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/CMakeLists.txt
   cgm/branches/merge-cubit12/geom/ACIS_SRC/CoEdgeACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/Makefile.am
   cgm/branches/merge-cubit12/geom/ACIS_SRC/PointACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/ShellACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/UseACIS.cmake
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.cpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.hpp
   cgm/branches/merge-cubit12/geom/ACIS_SRC/decl_none.h
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/CMakeLists.txt
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/Makefile
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/incl/
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/incl/attrib_gtc_export.h
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/src/
   cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/src/attrib_gtc.C
Log:
Initial merge of Cubit-12 ACIS port w/ current CGM.

This probably doesn't even compile yet.



Property changes on: cgm/branches/merge-cubit12/geom/ACIS_SRC
___________________________________________________________________
Modified: svn:mergeinfo
   - /cgm/trunk/geom/ACIS_SRC:3427-3493
   + /cgm/branches/cubit/geom/ACIS_SRC:3487-3491
/cgm/trunk/geom/ACIS_SRC:3427-3493

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisBridge.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisBridge.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisBridge.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -12,11 +12,7 @@
 //-------------------------------------------------------------------------
 
 // ************* BEGIN ACIS INCLUDES *************
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/api.hxx"
-#else
 #include "api.hxx"
-#endif
 // ************* END ACIS INCLUDES ***************
 
 // ************* BEGIN CUBIT INCLUDES *************
@@ -99,6 +95,7 @@
     {
       API_BEGIN;
       attribute->unhook();
+      attribute->lose();
       API_END;
     }
   }
@@ -129,6 +126,7 @@
                    (attrib_ptr->string_data_list()->step_and_get())->c_str()) == 0))
         {
           attribute_gtc->unhook();
+          attribute_gtc->lose();
           loop_continue = CUBIT_FALSE;
         }
       }
@@ -149,6 +147,7 @@
         attrib_ptr->string_data_list()->reset();
 
         attribute_len->unhook();
+        attribute_len->lose();
         loop_continue = CUBIT_FALSE;
 
       }
@@ -170,6 +169,7 @@
   {
     API_BEGIN;
     attribute->unhook();
+    attribute->lose();
     API_END;
   }
   ATTRIB_GTC_NAME *attribute_gtc =
@@ -184,6 +184,7 @@
   {
     API_BEGIN;
     attribute_gtc->unhook();
+    attribute_gtc->lose();
     API_END;
   }
 
@@ -199,6 +200,7 @@
   {
     API_BEGIN;
     attribute_len->unhook();
+    attribute_len->lose();
     API_END;
   }
 }

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisDrawTool.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisDrawTool.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisDrawTool.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -9,6 +9,7 @@
 // ********** BEGIN ACIS INCLUDES             **********
 #include "entity.hxx"
 #include "body.hxx"
+#include "wire.hxx"
 #include "lump.hxx"
 #include "shell.hxx"
 #include "loop.hxx"
@@ -81,7 +82,8 @@
     return draw_FACE( (FACE*)ENTITY_ptr, color, tessellate, flush );
   }
   else if( IS_ENTITY_TYPE( ENTITY_ptr, LOOP ) ||
-           IS_ENTITY_TYPE( ENTITY_ptr, COEDGE ) )
+           IS_ENTITY_TYPE( ENTITY_ptr, COEDGE ) ||
+           IS_ENTITY_TYPE( ENTITY_ptr, WIRE ) ) 
   {
     DLIList<EDGE*> EDGE_list;
     AQE->get_EDGEs( ENTITY_ptr, EDGE_list );
@@ -127,13 +129,12 @@
   Curve *curve_ptr = AQE->populate_topology_bridges( (EDGE *)copied_ENTITY_ptr );
 
   GMem g_mem;
-  int num_points;
 
   // get the graphics
   CubitStatus stat;
-  stat = AQE->get_graphics( curve_ptr, num_points, &g_mem );
+  stat = AQE->get_graphics( curve_ptr, &g_mem );
 
-  if (stat==CUBIT_FAILURE || num_points == 0)
+  if (stat==CUBIT_FAILURE || g_mem.pointListCount == 0)
   {
     PRINT_ERROR("Unable to tessellate a curve for display\n" );
     AQE->delete_solid_model_entities( curve_ptr );
@@ -179,41 +180,30 @@
 
   if( tessellate )
   {
-    int num_tris, num_pnts, num_facets;
     GMem g_mem;
     unsigned short norm_tol = 10;
     double dist_tol = -1.0;
-    AQE->get_graphics( FACE_ptr, num_tris, num_pnts, num_facets,
-      &g_mem, norm_tol, dist_tol );
+    AQE->get_graphics( FACE_ptr, &g_mem, norm_tol, dist_tol );
 
-    if(num_tris < 1)
+    if(g_mem.fListCount < 1)
     {
       // decrease tolerance and try again (we can get this for small features)
       norm_tol /= 2;
-      AQE->get_graphics( FACE_ptr, num_tris, num_pnts, num_facets, &g_mem, 
-        norm_tol, dist_tol);
+      AQE->get_graphics( FACE_ptr, &g_mem, norm_tol, dist_tol);
     }
 
-    if(num_tris < 1)
+    if(g_mem.fListCount < 1)
     {
       // lets give up 
       PRINT_ERROR( "Unable to tessellate surface for display\n" );
       return CUBIT_FAILURE;
     }
 
-    // Draw the triangles
-    GPoint p[3];
-    GPoint* plist = g_mem.point_list();
-    int* facet_list = g_mem.facet_list();
-    int i, c = 0;
-    for( i=0; i<num_tris; i++ )
-    {
-      p[0] = plist[facet_list[++c]];
-      p[2] = plist[facet_list[++c]];
-      p[1] = plist[facet_list[++c]]; 
-      c++;
-      GfxPreview::draw_tri( p, color );
-    }
+    // draw this more efficiently as a list of polygons
+    const float* xyzs = reinterpret_cast<const float*>(g_mem.point_list());
+    GfxPreview::draw_polygons(g_mem.pointListCount, xyzs, 
+                              g_mem.fListCount, g_mem.facet_list(),
+                              color);
   }
   else
   {
@@ -236,5 +226,7 @@
 {
   const SPAposition &coords = VERTEX_ptr->geometry()->coords();
   GfxPreview::draw_point( coords.x(), coords.y(), coords.z(), color );
+  if( flush )
+    GfxPreview::flush();
   return CUBIT_SUCCESS;
 }

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisEdgeTool.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisEdgeTool.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisEdgeTool.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -7,19 +7,11 @@
 
 // ********** BEGIN ACIS INCLUDES             **********
 
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#include "kernel/kerndata/top/vertex.hxx"
-#include "kernel/kerndata/geom/point.hxx"
-#include "intersct/sg_husk/split/esplit.hxx"
-#else
 #include "kernapi.hxx" 
 #include "vertex.hxx" 
 #include "point.hxx"
 #include "coverapi.hxx"
 #include "esplit.hxx"
-#endif
 
 // ********** END ACIS INCLUDES               **********
 
@@ -64,9 +56,6 @@
 AcisEdgeTool::create_curve_combine( DLIList<Curve*>& curve_list, 
                                     Curve *&new_curve_ptr )
 {
-   AcisQueryEngine *const AQE = AcisQueryEngine::instance();
-   GeometryQueryTool *const GQT = GeometryQueryTool::instance();
-   
    new_curve_ptr = create_curve_combine( curve_list );
    if (!new_curve_ptr)
      return CUBIT_FAILURE;

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -13,11 +13,7 @@
 
 //#define ACIS_FACET_MAN_DEBUG
 
-#if CUBIT_ACIS_VERSION < 1100
-#include "baseutil/vector/position.hxx"
-#else
 #include "position.hxx"
-#endif
 
 // #define ACIS_FACET_MAN_DEBUG
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFacetManager.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -9,11 +9,7 @@
 #ifndef ACISFACETMANAGER_HPP
 #define ACISFACETMANAGER_HPP
 
-#if CUBIT_ACIS_VERSION < 1100
-#include "faceter/meshmgr/meshmg.hxx"
-#else
 #include "meshmg.hxx"
-#endif
 
 #include "AcisTypes.h"
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -34,6 +34,11 @@
     GeometryFeatureTool::instance()->add_gfe(this);
 }
 
+AcisFeatureEngine::~AcisFeatureEngine()
+{
+  instance_ = NULL;
+}
+
 CubitBoolean AcisFeatureEngine::is_feature_engine( const TopologyBridge* tb_ptr )
 {
     if(dynamic_cast<AcisBridge*>(const_cast<TopologyBridge*>(tb_ptr))) 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisFeatureEngine.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -19,7 +19,7 @@
     static AcisFeatureEngine* instance();
 
     //! virtual destructor
-    virtual ~AcisFeatureEngine() {}
+    virtual ~AcisFeatureEngine(); 
 
     //! returns CUBIT_TRUE if the entity belongs to this feature engine
     virtual CubitBoolean is_feature_engine( const TopologyBridge* );

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -12,54 +12,6 @@
 #include "undefwin_.h"
 #endif
 
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/acis.hxx"
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#include "kernel/kerndata/top/face.hxx"
-
-#include "boolean/kernapi/api/boolapi.hxx"
-#include "euler/kernapi/api/eulerapi.hxx"
-#include "healhusk/heal_api/heal_api.hxx"
-
-#include "kernel/kerndata/data/entity.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-
-#include "kernel/kerndata/top/alltop.hxx" // Required for is_TEDGE
-
-#include "healhusk/util/bhl_opt.hxx"
-#include "healhusk/util/tols.hxx"
-#include "healhusk/tgtspl/net_heal.hxx"
-#include "healhusk/attrib/at_aggr.hxx"
-#include "healhusk/attrib/aggrsimg.hxx"
-#include "healhusk/attrib/aggrstch.hxx"
-#include "healhusk/attrib/hmaster.hxx"
-#include "healhusk/attrib/entsimg.hxx"
-#include "healhusk/attrib/hanalsol.hxx"
-#include "healhusk/attrib/huvsolv.hxx"
-#include "healhusk/simgeom/simgeom.hxx"
-# include "healhusk/stitch/stitch.hxx"
-# include "healhusk/stitch/stch_utl.hxx"
-
-// Needed for advanced feedback
-#include "healhusk/attrib/aggrgbld.hxx"
-#include "healhusk/attrib/edgmbld.hxx"
-#include "healhusk/attrib/vegmbld.hxx"
-#include "healhusk/attrib/cegmbld.hxx"
-#include "healhusk/attrib/fagmbld.hxx"
-#include "healhusk/attrib/entstch.hxx"
-#include "healhusk/attrib/curgmbld.hxx"
-#include "healhusk/attrib/surgmbld.hxx"
-#include "healhusk/attrib/pcgmbld.hxx"
-#include "healhusk/attrib/shlgmbld.hxx"
-#include "healhusk/attrib/lpgmbld.hxx"
-#include "healhusk/attrib/lmpgmbld.hxx"
-#include "healhusk/util/traverse.hxx"
-#include "healhusk/attrib/hsharped.hxx"
-#include "healhusk/attrib/hadvspl.hxx"
-#include "healhusk/attrib/hreblend.hxx"
-#else
 #include "acis.hxx"
 #include "api.hxx"
 #include "kernapi.hxx" 
@@ -106,7 +58,6 @@
 # include "traverse_heal.hxx"
 # include "hsharped.hxx"
 # include "hadvspl.hxx"
-#endif
 
 #ifdef UNIX_PORT
 # include "defwin_.h"
@@ -139,7 +90,6 @@
 #include "Shell.hpp"
 #include "RefVolume.hpp"
 #include "RefVertex.hpp"
-
 #include "DLIList.hpp"
 
 // ********** END CUBIT INCLUDES              **********
@@ -162,7 +112,8 @@
 static double defaultStitchMinTol = CUBIT_DBL_MAX;
 static logical stitchMinTolSw = FALSE;
 static double stitchMaxTol = 0;
-static double defaultStitchMaxTol = CUBIT_DBL_MAX;
+//static double defaultStitchMaxTol = CUBIT_DBL_MAX;
+static double defaultStitchMaxTol = 0.1;
 static logical stitchMaxTolSw = FALSE;
 static logical doStitch = TRUE;
 static logical userControlStitch = FALSE;
@@ -373,13 +324,9 @@
    
    if( !userControlSimplify || (userControlSimplify && doSimplify) )
    {
-#if CUBIT_ACIS_VERSION < 1100
-      result = api_hh_simplify_auto( BODY_ptr);
-#else
       hh_simplify_options simp_opts;
       simp_opts.set_do_curve_simplification(0);
       result = api_hh_simplify_auto( BODY_ptr, &simp_opts );
-#endif 
       if( !result.ok() )
       {
          PRINT_ERROR( "error in simplify\n" );
@@ -1127,12 +1074,12 @@
    
    if ( isosplineTolSw == TRUE )
    {
-      ATTRIB_HH_AGGR_ISOSPLINE * att = (ATTRIB_HH_AGGR_ISOSPLINE *)
+      /*ATTRIB_HH_AGGR_ISOSPLINE * att = (ATTRIB_HH_AGGR_ISOSPLINE *)*/
          find_leaf_attrib(body,ATTRIB_HH_AGGR_ISOSPLINE_TYPE);
    }
    else if ( defaultIsosplineTol != CUBIT_DBL_MAX )
    {
-      ATTRIB_HH_AGGR_ISOSPLINE * att = (ATTRIB_HH_AGGR_ISOSPLINE *)
+      /*ATTRIB_HH_AGGR_ISOSPLINE * att = (ATTRIB_HH_AGGR_ISOSPLINE *)*/
          find_leaf_attrib(body,ATTRIB_HH_AGGR_ISOSPLINE_TYPE);
    }
    
@@ -1409,7 +1356,7 @@
    else if( ent != NULL )
    {
       if( ent->identity(BODY_LEVEL)==BODY_TYPE) {
-         ATTRIB_HH_AGGR_ISOSPLINE * att = (ATTRIB_HH_AGGR_ISOSPLINE *)
+         /*ATTRIB_HH_AGGR_ISOSPLINE * att = (ATTRIB_HH_AGGR_ISOSPLINE *)*/
             find_leaf_attrib(ent,ATTRIB_HH_AGGR_ISOSPLINE_TYPE);
       }
    }
@@ -2163,7 +2110,7 @@
       ATTRIB_HH_ENT_GEOMBUILD_EDGE *att = (ATTRIB_HH_ENT_GEOMBUILD_EDGE *)
          find_leaf_attrib(ent_list[i],ATTRIB_HH_ENT_GEOMBUILD_EDGE_TYPE);
       if (NULL != att){
-         if(att->get_vexity () == TANGENT){
+         if(att->get_vexity () == ACIS_TANGENT){
             TopologyEntity* te_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity(ent_list[i]);
             ref_edge_ptr = CAST_TO( te_ptr, RefEdge );
             if( ref_edge_ptr == NULL )
@@ -2188,7 +2135,7 @@
       ATTRIB_HH_ENT_GEOMBUILD_EDGE *att = (ATTRIB_HH_ENT_GEOMBUILD_EDGE *)
          find_leaf_attrib(ent_list[i],ATTRIB_HH_ENT_GEOMBUILD_EDGE_TYPE);
       if (NULL != att){
-         if(att->get_vexity () ==CONVEX){
+         if(att->get_vexity () ==ACIS_CONVEX){
             TopologyEntity* te_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity(ent_list[i]);
             ref_edge_ptr = CAST_TO( te_ptr, RefEdge );
             if( ref_edge_ptr == NULL )
@@ -2213,7 +2160,7 @@
       ATTRIB_HH_ENT_GEOMBUILD_EDGE *att = (ATTRIB_HH_ENT_GEOMBUILD_EDGE *)
          find_leaf_attrib(ent_list[i],ATTRIB_HH_ENT_GEOMBUILD_EDGE_TYPE);
       if (NULL != att){
-         if(att->get_vexity () ==CONCAVE){
+         if(att->get_vexity () ==ACIS_CONCAVE){
             TopologyEntity* te_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity(ent_list[i]);
             ref_edge_ptr = CAST_TO( te_ptr, RefEdge );
             if( ref_edge_ptr == NULL )

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHealerTool.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -28,6 +28,10 @@
 class BODY;
 class ENTITY;
 
+const int ACIS_TANGENT = 0;
+const int ACIS_CONVEX = 1;
+const int ACIS_CONCAVE = - 1;
+
 class AcisHealerTool : public GeometryHealerEngine
 {
 public:

Copied: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.cpp (from rev 3491, cgm/branches/cubit/geom/ACIS_SRC/AcisHistory.cpp)
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.cpp	                        (rev 0)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -0,0 +1,580 @@
+
+#include "AcisHistory.hpp"
+#include "AcisQueryEngine.hpp"
+#include "CubitMessage.hpp"
+#include "RefEntity.hpp"
+#include "acistype.hxx"
+#include "lists.hxx"
+#include "attrib_history.hpp"
+#include "CGMHistory.hpp"
+#include "GeometryQueryTool.hpp"
+
+/*Here's a brief description of how the history is created in the 
+ * Acis port:
+ * 1.  Create an AcisHistory object.
+ *
+ * 2. TopologyBridges are given to the port for modification.  From 
+ * the TopologyBridges, get all associated parent and child TopologyBridges.  
+ * From each TopologyBridge, get a) the corresponding RefEntity
+ * and b) the corresponding ENTITY(s).  
+ *
+ * 3.  On every ACIS ENTITY, attach an attrib_history attribute. 
+ * The attrib_history basically holds a unique 'tracking' integer.
+ *
+ * 4.  Populate the refentity_tracking_id_map in the AcisHistory object, with
+ * pairs, where each pair consists of a RefEntity pointer and it's associated
+ * tracking id, in #3.
+ *
+ * 5.  Acis performs the operation(s), making callbacks into the 
+ * attrib_history's overloaded functions.  It does the following:
+ * -For split_owner callbacks, where A is split into A and B, 
+ *  put a history attrib on B and add A's tracking integer to B.
+ * -For merge_owner callbacks, where A and B are merged into A, 
+ *  add B's tracking id to A.  Now A will have 2 tracking ids 
+ *  associated with it.
+ *  -In the copying callback macros, if B has been copied from A, give B
+ *  the tracking id that was in A.
+ *  -For the other callbacks, replace_owner, lop_change_owner, and 
+ *  replace_owner_geometry, add an AcisEvent to the AcisHistory object's
+ *  event list.
+ *
+ * 6.  Once the operation has ended and TopologyBridges have been added
+ * to the new ENTITYs (populate_topology_bridges has been called), for 
+ * each TopologyBridge, create a pair consisting of
+ * a set of tracking ids and a TopologyBridge pointer. 
+ *
+ * 7.  Find pairs in #6 that have any tracking id in common in their sets. 
+ * If you find multiple pairs who's sets in size, you have a subdivision-absorption
+ * event (n->m).  If you only find a single pair that has a set with 
+ * multiple tracking ids in it, you have an absorption event (n->1).  If you find 
+ * multiple pairs that all have a single tracking id in their set, you have
+ * a subdivision event(1->n).  And if you only find a single pair with a single
+ * tracking id in it's set, you have a geometry modified event.
+ *
+ * 8. Everytime you gather one of these pair group, in #7, you create a PortEvent 
+ * which ties the original RefEntity pointer(s) to the new TopologyBridge(s).
+ */
+
+AcisHistory::AcisHistory()
+{
+  trackingId = -1;
+  highLevelCopying = false;
+}
+
+AcisHistory::~AcisHistory()
+{
+ ATTRIB_HISTORY::remove_all_attribs(); 
+}
+
+void AcisHistory::add_event( const AcisEvent &event )
+{
+  eventList.push_back( event );
+}
+
+void AcisHistory::add_refentity_tracking_id_pair( RefEntity *ref_ent, int tracking_id ) 
+{
+  refentity_tracking_id_map.push_back( 
+    std::pair<RefEntity*, int>( ref_ent, tracking_id));
+}
+
+
+void AcisHistory::print()
+{
+  /*
+  std::vector<CGMEvent>::iterator iter = cgmEventList.begin();
+  for(; iter != cgmEventList.end(); iter++ )
+  {
+    CGMEvent cgm_event = *iter;
+    PRINT_INFO("Event type = %s RefEntities ", event_names[ cgm_event.eventType ]);
+
+    int i;
+    for( i=0; i<cgm_event.RefEnts.size(); i++ )
+    {
+      RefEntity *ref_ent = cgm_event.RefEnts[i];
+      PRINT_INFO(" %s %d ", ref_ent->class_name(), ref_ent->id() );
+    }
+    PRINT_INFO(" ---> ");
+    for( i=0; i<cgm_event.TopologyBridges.size(); i++ )
+    {
+      TopologyBridge *tb = cgm_event.TopologyBridges[i];
+      PRINT_INFO(" %p", tb );
+    }
+    PRINT_INFO("\n"); 
+  } */
+}
+
+int AcisHistory::generate_next_tracking_id()
+{
+  trackingId++;
+  return trackingId;
+}
+
+void AcisHistory::add_to_tracking_ids_tb_map( std::set<int> &tracking_ids, TopologyBridge *tb ) 
+{
+  tracking_ids_to_tb_map.push_back( std::pair< std::set<int>, TopologyBridge*>( tracking_ids, tb ) );
+}
+
+void AcisHistory::create_cgm_history_objects()
+{
+  //look for subdivision-absorption events.
+  //Look in tracking_ids_to_tb_map for a pair whose vector 
+  //has multiple integers in it.  If you find another pair with the 
+  //same integers in it, you've found a subdivision-absorption event.
+
+  std::vector< std::pair< std::set<int>, TopologyBridge*> > unrelated_pairs;
+  std::list< std::pair< std::set<int>, TopologyBridge*> >::iterator iter;
+ 
+  if( highLevelCopying )
+  {
+    while( tracking_ids_to_tb_map.size() )
+    {
+      iter = tracking_ids_to_tb_map.begin();
+
+      std::pair< std::set<int>, TopologyBridge*> pair1 = *iter; 
+
+      std::vector< std::pair< std::set<int>, TopologyBridge*> > found_pairs; 
+      found_pairs.push_back( pair1 );
+      
+      create_port_event( CGMHistory::COPY, found_pairs );
+      tracking_ids_to_tb_map.erase( iter++ );
+    }
+  }
+  else
+  {
+
+    while( tracking_ids_to_tb_map.size() )
+    {
+      iter = tracking_ids_to_tb_map.begin();
+
+      std::pair< std::set<int>, TopologyBridge*> pair1 = *iter; 
+      std::set<int> set1 = pair1.first;
+
+      //find all pairs that have a vector that contains any integer in set1,
+      //and at the same time recursively do the same for the found pairs 
+      //get back a 'found_pairs' list
+      
+      std::vector< std::pair< std::set<int>, TopologyBridge*> > found_pairs; 
+      found_pairs.push_back( pair1 );
+      tracking_ids_to_tb_map.erase( iter++ );
+      collect_relevant_pairs( set1, found_pairs ); 
+
+      //if the found_pairs just contains the original pair
+      //it's a simple absorption
+      std::vector< std::pair< std::set<int>, TopologyBridge*> >::iterator vec_iter;
+      std::pair< std::set<int>, TopologyBridge*> tmp_pair; 
+      if( found_pairs.size() == 1 )
+      {
+        //if the single set contains multiple integers, 
+        //it's a simple absorption
+
+        vec_iter = found_pairs.begin();
+        tmp_pair = *vec_iter;
+        std::set<int> tmp_set = tmp_pair.first;
+        if( tmp_set.size() > 1 )
+          create_port_event( CGMHistory::ABSORPTION, found_pairs ); 
+        else
+          unrelated_pairs.push_back( pair1 );
+      }
+      else
+      {
+        //if the found_pairs all have exactly one integer in their sets, 
+        //it's a simple subdivision
+        vec_iter = found_pairs.begin();
+        tmp_pair = *vec_iter;
+        std::set<int> tmp_set = tmp_pair.first;
+        int size_of_set = tmp_set.size(); 
+        vec_iter++; 
+        bool varying_sizes = false;
+        for(; vec_iter != found_pairs.end(); vec_iter++ )
+        {
+          tmp_pair = *vec_iter;
+          tmp_set = tmp_pair.first;
+          if( size_of_set != tmp_set.size() )
+          {
+            varying_sizes = true;
+            break;
+          }
+        }
+
+        if( varying_sizes )
+          create_port_event( CGMHistory::SUBDIVISION_ABSORPTION, found_pairs ); 
+        else
+          create_port_event( CGMHistory::SUBDIVISION, found_pairs ); 
+      }
+    }
+  }
+
+  std::vector< std::pair< std::set<int>, TopologyBridge*> >::iterator vec_iter1;
+  vec_iter1 = unrelated_pairs.begin();
+  for(; vec_iter1 != unrelated_pairs.end(); vec_iter1++ ) 
+  {
+    std::set<int> set1 = (*vec_iter1).first;
+    if( set1.size() == 0 )
+      continue;
+    int tracking_id = *set1.begin();
+
+    std::vector<AcisEvent>::iterator vec_iter2 = eventList.begin();
+    for(; vec_iter2 != eventList.end(); vec_iter2++ )
+    {
+      AcisEvent event = (*vec_iter2);
+      if( event.eventType == CGMHistory::GEOMETRY_CHANGED ||
+          event.eventType == CGMHistory::CUT ) 
+      {
+        int other_tracking_id = event.entities[0];
+
+        if( tracking_id == other_tracking_id )
+        {
+          TopologyBridge *tb = (*vec_iter1).second;
+          std::pair<RefEntity*, int> tmp_pair = refentity_tracking_id_map[tracking_id];
+          RefEntity* ref_ent = tmp_pair.first; 
+          CGMHistory::PortEvent port_event( event.eventType );
+          port_event.RefEnts.push_back( ref_ent );
+          port_event.TopologyBridges.push_back( tb );
+          GeometryQueryTool::instance()->history().add_port_event( port_event ); 
+          break;
+        }
+      }
+    }
+  }
+}
+
+
+void AcisHistory::collect_relevant_pairs( std::set<int> &seed_set,
+           std::vector< std::pair< std::set<int>, TopologyBridge*> > &found_pairs ) 
+{
+   
+  std::list< std::pair< std::set<int>, TopologyBridge*> >::iterator iter;
+  iter = tracking_ids_to_tb_map.begin();
+
+  for(; iter != tracking_ids_to_tb_map.end(); iter++ ) 
+  {
+    std::pair< std::set<int>, TopologyBridge*> my_pair1 = *iter; 
+    std::set<int> set1 = my_pair1.first;
+
+    if( set1.empty() )
+      continue;
+    
+    std::set<int>::iterator iter1, iter2;
+    //does set1 contain any integers that are in the seed set?
+    //if so, remove the pair from the list and add it to 'found_pairs'
+    iter1 = set1.begin();
+    bool pair_found = false;
+    for(; iter1 != set1.end(); iter1++ )
+    {
+      int int1 = *iter1;
+      
+      for( iter2 = seed_set.begin(); iter2 != seed_set.end(); iter2++ )
+      {
+        int int2 = *iter2; 
+
+        if( int2 == int1 )
+        {
+          //clear out the set
+          std::set<int> &tmp_set = (*iter).first; 
+          tmp_set.clear();
+
+          found_pairs.push_back( my_pair1 );
+          //tracking_ids_to_tb_map.erase( iter++ );
+          collect_relevant_pairs( set1, found_pairs );
+          pair_found = true;
+          break;
+        }
+      }
+      if( pair_found )
+        break;
+    }
+//    if( pair_found == false )
+//      iter++;
+  }
+}
+
+
+void AcisHistory::create_port_event( CGMHistory::EventType event_type, 
+           std::vector< std::pair< std::set<int>, TopologyBridge*> > &found_pairs ) 
+{
+  CGMHistory::PortEvent port_event( event_type );
+  
+  //add all TBs to the event's TB list
+  std::vector< std::pair< std::set<int>, TopologyBridge*> >::iterator vec_iter;
+  vec_iter = found_pairs.begin();
+  std::pair< std::set<int>, TopologyBridge*> tmp_pair; 
+  DLIList<RefEntity*> ref_ent_list;
+  DLIList<TopologyBridge*> tb_list;
+  for(; vec_iter != found_pairs.end(); vec_iter++ )
+  {
+    tmp_pair = *vec_iter;
+    TopologyBridge *tb = tmp_pair.second; 
+    tb_list.append( tb );
+
+    std::set<int> tmp_set = tmp_pair.first;
+    std::set<int>::iterator iter=tmp_set.begin();
+    for(; iter != tmp_set.end(); iter++ )
+    {
+      int index = *iter;
+      std::pair<RefEntity*, int> pair2 = refentity_tracking_id_map[index];
+      RefEntity* ref_ent = pair2.first; 
+      ref_ent_list.append( ref_ent );
+    }
+  }
+    
+  //uniquify the lists...then append them to the CGMEvent's vector
+  ref_ent_list.uniquify_unordered(); 
+  tb_list.uniquify_unordered(); 
+  
+  int i;
+  for(i=ref_ent_list.size(); i--; )
+    port_event.RefEnts.push_back( ref_ent_list.get_and_step() );
+  for(i=tb_list.size(); i--; )
+    port_event.TopologyBridges.push_back( tb_list.get_and_step() );
+
+  GeometryQueryTool::instance()->history().add_port_event( port_event ); 
+}
+
+
+void AcisHistory::add_ENTITY( ENTITY *entity )
+{
+  all_ents.push_back( entity );
+}
+
+void AcisHistory::remove_attributes()
+{
+  int i;
+  for( i=0; i<all_ents.size(); i++ )
+  {
+    ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( all_ents[i], false ); 
+    if( att )
+      att->lose();
+  }
+}
+
+/*
+void AcisHistory::collect_events_and_find_resultant_uniqueids( int source_id, 
+                                     DLIList<AcisEvent*> &events, 
+                                     DLIList<int> &result_unique_ids )
+{
+  //get an AcisEvent w/ 'entity' in  'other_entities' list
+  std::vector<AcisEvent>::iterator iter;
+  bool found_entity = false;
+  for(iter=eventList.begin(); iter != eventList.end(); iter++ )
+  {
+    AcisEvent *tmp_event = &(*iter);
+
+    //ignore events that are already in the list
+    if( events.is_in_list( tmp_event ) )
+      continue;
+ 
+    //search 'entities' list 
+    if( tmp_event->eventType == SUBDIVISION || 
+        tmp_event->eventType == ABSORPTION || 
+        tmp_event->eventType == COPY ) 
+    {
+      int k;
+      for(k=0; k<tmp_event->entities.size(); k++ )
+      {
+        if( source_id == tmp_event->entities[k] )
+        {
+          found_entity = true;
+          //we found the ENTITY...now get ents in 'entities' list
+          //and look for them 
+          events.append( tmp_event );
+          int i;
+          for( i=0; i<tmp_event->other_entities.size(); i++ )
+            collect_events_and_find_resultant_uniqueids( tmp_event->other_entities[i], 
+                events, result_unique_ids );
+        }
+      }
+    }
+    else if( tmp_event->eventType == GEOMETRY_CHANGED ) 
+    {
+      if( source_id == tmp_event->entities[0] )
+      {
+        events.append( tmp_event );
+        collect_events_and_find_resultant_uniqueids( tmp_event->entities[0], 
+            events, result_unique_ids);
+      }
+    }
+  }
+
+  //so you can't go any further, traversing the events...see if this one is in
+  //the results list...if so, append it
+  if( false == found_entity ) 
+  {
+    if( resultUniqueIds.find( source_id ) != resultUniqueIds.end() ) 
+      result_unique_ids.append( source_id );
+  }
+} */
+
+
+/*
+void AcisHistory::collect_events_and_find_original_uniqueids( int source_id, 
+                                     DLIList<AcisEvent*> &events, 
+                                     DLIList<int> &original_unique_ids)
+{
+ 
+  //get an AcisEvent w/ 'entity' in  'other_entities' list
+  std::vector<AcisEvent>::iterator iter;
+  bool found_entity = false;
+  for(iter=eventList.begin(); iter != eventList.end(); iter++ )
+  {
+    AcisEvent *tmp_event = &(*iter);
+
+    //ignore events that are already in the list
+    if( events.is_in_list( tmp_event ) )
+      continue;
+ 
+    //search 'other_entities' list 
+    if( tmp_event->eventType == SUBDIVISION || 
+        tmp_event->eventType == ABSORPTION || 
+        tmp_event->eventType == COPY ) 
+    {
+      int k;
+      for(k=0; k<tmp_event->other_entities.size(); k++ )
+      {
+        if( source_id == tmp_event->other_entities[k] )
+        {
+          found_entity = true;
+          //we found the ENTITY...now get ents in 'entities' list
+          //and look for them 
+          events.append( tmp_event );
+          int i;
+          for( i=0; i<tmp_event->entities.size(); i++ )
+            collect_events_and_find_original_uniqueids( tmp_event->entities[i], events, original_unique_ids );
+        }
+      }
+    }
+    else if( tmp_event->eventType == GEOMETRY_CHANGED ) 
+    {
+      if( source_id == tmp_event->entities[0] )
+      {
+        events.append( tmp_event );
+        collect_events_and_find_original_uniqueids( tmp_event->entities[0], events, original_unique_ids );
+      }
+    }
+  }
+
+  if( false == found_entity )
+    original_unique_ids.append( source_id );
+} */
+
+
+/*
+void AcisHistory::map_back_to_ref_entity( TopologyBridge *topology_bridge, 
+                                          RefEntity *ref_entity, 
+                                          AcisHistory::EventType event_type )
+{
+
+  ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( topology_bridge ); 
+
+  ATTRIB_HISTORY *tmp_attrib = ATTRIB_HISTORY::get_history_attrib( entity );
+  if( !tmp_attrib )
+    return;
+
+  int source_id = tmp_attrib->get_unique_id();
+  
+  DLIList<AcisEvent*> events;
+  DLIList<int> original_unique_ids;
+
+  //starting from the result ENTITY, work your waying up the events, 
+  // to the original ENTITY
+  collect_events_and_find_original_uniqueids( source_id, events, original_unique_ids );
+  
+  //PRINT_INFO("source entity = %p  ", entity );
+
+  //PRINT_INFO("target_ents = ");
+  int i;
+  //for( i=original_ents.size(); i--; )
+  //  PRINT_INFO("%p ", original_ents.get_and_step() );
+  //PRINT_INFO("\n");
+
+
+  EventType my_event_type = NO_EVENT;
+  DLIList<RefEntity*> original_ref_ents; 
+
+  //from the supposed original ENTITY, 
+  //find the corresponding RefEntity in refentity_ENTITY_multimap 
+  for( i=original_unique_ids.size(); i--; )
+  {
+    int original_id = original_unique_ids.get_and_step();
+
+    std::multimap<RefEntity*, int>::iterator iter = refentity_uniqueid_multimap.begin();
+    for( ; iter != refentity_uniqueid_multimap.end(); iter++ )
+    {
+      int tmp_id = (*iter).second;
+      if( original_id == tmp_id ) 
+      {
+        //determine what type of event you have
+        int j;
+        for( j=events.size(); j--; )
+        {
+          AcisEvent *event = events.get_and_step();
+
+          //ignore copy events for now
+          if( event->eventType != COPY && 
+              event->eventType != NO_EVENT )
+          {
+
+            //split events take priority over 
+            if( event->eventType > my_event_type  )
+              my_event_type = event->eventType;
+          }
+        }
+        RefEntity *original_ref_ent = (*iter).first;
+        original_ref_ents.append( original_ref_ent );
+      }
+    }
+  }
+
+  if( my_event_type != NO_EVENT )
+  {
+    PRINT_INFO("Event type = %s RefEntity = %s %d Result ENTITY = %p\n", 
+      event_names[my_event_type], original_ref_ents.get()->class_name(),  
+      original_ref_ents.get()->id(), entity ); 
+
+    CGMEvent tmp_event;
+    tmp_event.eventType = my_event_type;
+    for( i=original_ref_ents.size(); i--; )
+      tmp_event.RefEnts.push_back( original_ref_ents.get_and_step() );
+
+    tmp_event.TopologyBridges.push_back( topology_bridge ); 
+    
+    cgmEventList.push_back( tmp_event );
+  }
+
+}*/
+
+/*Here's a brief description of how the history is created in the 
+ * Acis port:
+ * 1.  Create an AcisHistory object.
+ *
+ * 2.  Create a RefEnity to ENTITY multimap in the AcisHistory object:
+ * TopologyBridges are given to the port for modification.  From 
+ * the TopologyBridges, get all associated parent and child TopologyBridges.  
+ * From each TopologyBridge, get a) the corresponding RefEntity
+ * and b) the corresponding ENTITY(s).  Put them in 'refentity_ENTITY_multimap', 
+ * where the RefEntity is the key and the ENTITY(s) is the data.
+ *
+ * 3.  Attach an attrib_history attribute to every Acis ENTITY.
+ *
+ * 4.  Acis preforms the operation(s), making callbacks into the 
+ * attrib_history's overloaded functions.  Within these functions, AcisEvents are 
+ * created and added to the AcisHistory object's event list.
+ *
+ * 5.  Once the operation has ended and TopologyBridges have been added
+ * to the new ENTITYs, get all ENTITYs off the resulting BODYs and add them 
+ * to the AcisHistory's 'resultENTITY's' list.  
+ *
+ * 6.  Remove (ignore) any SUBDIVISION events that don't result in multiple 
+ * ENTITIYs in the result BODY.
+ *
+ * 7.  For each TopologyBridge, trace your way back through the AcisEvents until 
+ * you can't go any further.  With this 'leaf' entity, try to find a corresponding
+ * RefEntity in the 'refentity_ENTITY_multimap'.  
+ *
+ * 8.  If you found a corresponding RefEntity, create a CGMEvent.
+ *
+ * 9.  Consolidate CGMEvents of type SUBIDIVISION and ABSORPTION.
+ *
+ */
+
+
+

Copied: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.hpp (from rev 3491, cgm/branches/cubit/geom/ACIS_SRC/AcisHistory.hpp)
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.hpp	                        (rev 0)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisHistory.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -0,0 +1,125 @@
+
+
+#ifndef AcisHistory_hpp
+#define AcisHistory_hpp
+
+#include <map>
+#include <vector>
+#include <set>
+#include <list>
+#include "DLIList.hpp"
+#include "TopologyBridge.hpp"
+#include "CGMHistory.hpp"
+
+class RefEntity;
+class ENTITY;
+class ENTITY_LIST;
+
+class AcisHistory
+{
+  public:
+    AcisHistory();
+    ~AcisHistory();
+
+    /*        
+    enum EventType
+    {
+      NO_EVENT,
+
+      // An entity is copied from another
+      // you may also get this when an unmerge happens in cgm
+      // this is a supplemental event such that other events completely
+      // describe the topology changes, but this event specifies where the
+      // copy occurred
+      COPY,
+
+      // The geometry of an entity is changed such that it might have been
+      // stretched, warped or other such changes where the topology may be the
+      // same.  If child entities changed, they'll have their own event.
+      GEOMETRY_CHANGED,
+
+      // An entity is subdivided into multiple entities
+      // this is a supplemental event such that other events completely
+      // describe the topology changes, but this event specifies where the
+      // subdivision occurred
+      SUBDIVISION,
+
+      CUT,
+
+      // Multiple entities are absorbed into one entity
+      // this is a supplemental event such that other events completely
+      // describe the topology changes, but this event specifies where the
+      // absorption occurred
+      ABSORPTION,
+
+      // Multiple entities modified by a combination of subdivision and
+      // absorption, and intermediate entities don't exist by the time
+      // this history object is given to someone
+      // this is a supplemental event such that other events completely
+      // describe the topology changes, but this event specifies where the
+      // subdivision/absorption occurred
+      SUBDIVISION_ABSORPTION
+
+    }; */
+
+    //Event is a record of a change that occurred during an operation
+    struct AcisEvent
+    {
+      // the type of event this is
+      CGMHistory::EventType eventType;
+
+      // the entities this event applies to
+      std::vector<int> entities;
+
+      // extra data associated with event
+      std::vector<int> other_entities;
+    };
+
+    struct CGMEvent
+    {
+      // the type of event this is
+      CGMHistory::EventType eventType;
+
+      // the entities this event applies to
+      std::vector<RefEntity*> RefEnts;
+
+      // extra data associated with event
+      std::vector<TopologyBridge*> TopologyBridges;
+    };
+
+    // add an event to this history
+    void add_event( const AcisEvent &event );
+
+    // add a RefEntity, ENTITY pair
+    void add_refentity_tracking_id_pair( RefEntity *ref_ent, int tracking_id ); 
+    void add_to_tracking_ids_tb_map( std::set<int> &tracking_ids, TopologyBridge *tb ); 
+
+    void collect_relevant_pairs( std::set<int> &seed_set,
+           std::vector< std::pair< std::set<int>, TopologyBridge*> > &found_pairs );
+
+    int generate_next_tracking_id();
+
+    void print();
+
+    void create_cgm_history_objects();
+
+    void create_port_event( CGMHistory::EventType event_type, 
+           std::vector< std::pair< std::set<int>, TopologyBridge*> > &found_pairs );
+
+    void add_ENTITY( ENTITY *ent );
+    void remove_attributes();
+
+    bool highLevelCopying; 
+
+  private:
+    // the list of events
+    std::vector<AcisEvent> eventList;
+    std::vector< std::pair<RefEntity*, int> > refentity_tracking_id_map;
+    std::list< std::pair< std::set<int>, TopologyBridge* > > tracking_ids_to_tb_map;
+    std::vector<CGMEvent> cgmEventList;
+    int trackingId;
+    std::vector<ENTITY*> all_ents;
+};
+
+#endif
+

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -19,22 +19,6 @@
 // ********** END STANDARD INCLUDES           **********
 
 // ********** BEGIN ACIS INCLUDES             **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/acis.hxx"
-#include "kernel/kernutil/version/version.hxx"
-#include "operator/kernapi/api/operapi.hxx"
-#include "boolean/kernapi/api/boolapi.hxx"
-#include "constrct/kernapi/api/cstrapi.hxx"
-#include "constrct/sg_husk/utils/utils.hxx"
-#include "cover/kernapi/api/coverapi.hxx"
-#include "euler/kernapi/api/eulerapi.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "sbool/kernapi/api/sboolapi.hxx"
-#include "kernel/kernutil/law/generic_graph.hxx"
-#include "ct_husk/api/ctapi.hxx"
-#include "ct_husk/classes/cell.hxx"
-#include "boolean/sg_husk/sanity/err_ent.hxx"
-#else
 #include "acis.hxx"
 #include "version.hxx"
 #include "operapi.hxx"
@@ -53,47 +37,11 @@
 #include "acistype.hxx"
 #include "entity_simplify.hxx"
 #include "esplit.hxx"
-#endif
-
-#if CUBIT_ACIS_VERSION >= 800
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/acis_options.hxx"
-#else
+#include "ent_err_info.hxx"
+#include "stchapi.hxx"
+#include "err_info.hxx"
 #include "acis_options.hxx"
-#endif
-#endif
 
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "sweep/kernapi/api/sweepapi.hxx"
-#include "intersct/sg_husk/query/ptentrel.hxx"
-#include "kernel/kerndata/geometry/getbox.hxx"
-#include "kernel/kerndata/data/debug.hxx"
-#include "kernel/kerndata/data/entity.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "kernel/kernapi/api/api.err"
-#include "kernel/kerndata/attrib/attrib.hxx"
-#include "kernel/kerndata/geom/pcurve.hxx"
-#include "kernel/kerndata/geom/point.hxx"
-#include "kernel/kerndata/geom/allcurve.hxx"
-#include "kernel/kerndata/geom/allsurf.hxx"
-#include "kernel/kerndata/geom/plane.hxx"
-#include "kernel/kerndata/geom/cone.hxx"
-#include "kernel/kerndata/geom/sphere.hxx"
-#include "kernel/kerndata/geom/torus.hxx"
-#include "kernel/kerndata/geom/spline.hxx"
-#include "kernel/kerndata/geom/transfrm.hxx"
-#include "kernel/kerndata/geom/surface.hxx"
-#include "kernel/kerndata/geometry/geometry.hxx"
-#include "intersct/kerndata/geometry/geomutil.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "kernel/kerngeom/surface/surdef.hxx"
-#include "kernel/kerngeom/surface/allsfdef.hxx"
-#include "kernel/kerngeom/curve/curdef.hxx"
-#include "constrct/kernwire/sweeping/sweeping.hxx"
-#include "shl_husk/api/shl_api.hxx"
-#else
 #include "api.hxx"
 #include "kernapi.hxx"
 #include "sweepapi.hxx"
@@ -125,45 +73,7 @@
 #include "sweeping.hxx"
 #include "shl_api.hxx"
 #include "warp_api.hxx"
-#endif
 
-#if CUBIT_ACIS_VERSION < 800
-#include "sweep/kernwire/sweeping/piershee.hxx"
-#endif
-
-
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernutil/tensor/tensor.hxx"
-#include "kernel/kerndata/top/alltop.hxx"
-#include "kernel/kerndata/top/wire.hxx"
-#include "kernel/kerndata/transent/transent.hxx"
-#include "faceter/api/af_api.hxx"
-#include "kernel/sg_husk/query/q_wire.hxx"
-#include "intersct/sg_husk/query/sgquery.hxx"
-#include "kernel/kernint/d3_chk/chk_stat.hxx"
-#include "intersct/kernint/d3_chk/chk.hxx"
-#include "kernel/sg_husk/api/sgapi.err"
-#include "faceter/meshmgr/ppm.hxx"
-#include "faceter/meshmgr/ppmface.hxx"
-#include "kernel/kerndata/savres/fileinfo.hxx"
-#include "kernel/spline/bs3_crv/sp3crtn.hxx"
-#include "kernel/spline/api/spl_api.hxx"
-#include "intersct/spline/bs3_crv/bs3cutil.hxx"
-#include "kernel/spline/bs2_crv/sp2crtn.hxx"
-#include "ga_husk/api/ga_api.hxx"
-#include "kernel/sg_husk/sweep/swp_spl.hxx"
-#include "kernel/geomhusk/copyent.hxx"
-#include "kernel/kerndata/geom/cnstruct.hxx"
-#include "skin/kernapi/api/skinapi.hxx"
-#include "offset/kernapi/api/ofstapi.hxx"
-#include "kernel/kernutil/law/law.hxx"
-#include "kernel/geomhusk/wire_qry.hxx"
-#include "kernel/kernint/intcucu/intcucu.hxx"
-#include "kernel/geomhusk/entwray.hxx"
-#include "constrct/geomhusk/wire_utl.hxx"
-#include "intersct/sg_husk/query/sgquertn.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#else
 #include "tensor.hxx"
 #include "alltop.hxx"
 #include "wire.hxx"
@@ -173,7 +83,6 @@
 #include "sgquery.hxx"
 #include "chk_stat.hxx"
 #include "chk.hxx"
-//#include "sgapi.err"
 #include "ppm.hxx"
 #include "ppmface.hxx"
 #include "fileinfo.hxx"
@@ -194,30 +103,13 @@
 #include "wire_utl.hxx"
 #include "sgquertn.hxx"
 #include "body.hxx"
-#endif
+#include "mprop.hxx"
+#include "surextnd.hxx"
 
 #ifdef ACIS_HEALER
-#if CUBIT_ACIS_VERSION < 1100
-#include "healhusk/heal_api/heal_api.hxx"
-#else
 #include "heal_api.hxx"
 #endif
-#endif
 
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/geomhusk/getowner.hxx"
-#include "baseutil/vector/vector.hxx"
-#include "baseutil/vector/unitvec.hxx"
-#include "baseutil/vector/position.hxx"
-#include "baseutil/vector/transf.hxx"
-#include "baseutil/vector/box.hxx"
-#include "baseutil/errorsys/errmsg.hxx"
-#include "baseutil/logical.h"
-#include "baseutil/debug/module.hxx"
-#include "baseutil/option/option.hxx"
-#include "sweep/sg_husk/sweep/swp_opts.hxx"
-#include "kernel/geomhusk/getowner.hxx"
-#else
 #include "getowner.hxx"
 #include "vector.hxx"
 #include "unitvec.hxx"
@@ -230,40 +122,28 @@
 #include "option.hxx"
 #include "swp_opts.hxx"
 #include "getowner.hxx"
-#endif
+#include "stitch_progress_info.hxx"
 
+#include "skin_opts.hxx"
+#include "lop_opts.hxx"
+#include "lop_api.hxx"
+
 #ifdef ACIS_IGES_TRANSLATOR
-#if CUBIT_ACIS_VERSION < 1100
-   #include "igeshusk/igs_api/routines.hxx"
-#else
-#include "acisiges_api.hxx"
+//#include "acisiges_api.hxx"
 #endif
+
+#ifdef ACIS_STEP_TRANSLATOR
+//#include "acisstep_api.hxx"
 #endif
+
 #ifdef ACIS_PROE_TRANSLATOR
    #include "proe/proehusk/api/proeapi.hxx"
 #endif
 
 #ifdef ACIS_LOCAL_OPS
-#if CUBIT_ACIS_VERSION < 1100
-#include "rem_husk/api/rem_api.hxx"
-#else
 #include "rem_api.hxx"
 #endif
-#endif
 
-#ifdef ACIS_STEP_TRANSLATOR
-#if CUBIT_ACIS_VERSION < 1100
-   #include "stephusk/include/acis_inc.hxx"
-   #include "stephusk/include/stpapi.hxx"
-   #include "stephusk/util/apiinit.hxx"
-   #include "stephusk/stepwrit/api/apiwrite.hxx"
-   #include "stephusk/stepread/api/apiread.hxx"
-   #include "stephusk/util/stphead.hxx"
-   #include "stephusk/util/stp_res.hxx"
-#else
-#include "acisstep_api.hxx"
-#endif
-#endif
 
 // ********** END ACIS INCLUDES               **********
 
@@ -291,6 +171,7 @@
 #include "GeometryQueryTool.hpp"
 #include "GeometryModifyTool.hpp"
 
+#include "AcisTopologyTool.hpp"
 #include "AcisQueryEngine.hpp"
 #include "AcisModifyEngine.hpp"
 #include "AcisHealerTool.hpp"
@@ -298,6 +179,7 @@
 #include "AcisSurfaceTool.hpp"
 #include "AcisFacetManager.hpp"
 #include "AcisEdgeTool.hpp"
+#include "AcisHistory.hpp"
 
 #include "DoubleListItem.hpp"
 
@@ -310,6 +192,7 @@
 #include "SurfaceOverlapTool.hpp"
 #include "GeometryUtil.hpp"
 #include "RefEntityFactory.hpp"
+#include "CGMHistory.hpp"
 
 #include "DLIList.hpp"
 
@@ -320,9 +203,11 @@
 
 #include "Body.hpp"
 #include "attrib_snl_simple.hpp"
+#include "attrib_history.hpp"
 
 // still need this for vertex-id-rearranging junk
 #include "RefVertex.hpp"
+#include "RefFace.hpp"
 
 // include the DagDrawingTool header FOR DEBUGGING PURPOSES
 #include "DagDrawingTool.hpp"
@@ -330,9 +215,12 @@
 // including the AcisDrawTool for debugging
 #include "AcisDrawTool.hpp"
 #include "GfxDebug.hpp"
+#include "GfxPreview.hpp"
 
 AcisModifyEngine* AcisModifyEngine::instance_ = 0;
 
+int stitch_process_callback( stitch_progress_info *progress_info );
+
 AcisModifyEngine::~AcisModifyEngine()
 {
    api_terminate_booleans();
@@ -591,6 +479,9 @@
 {
    BODY* new_BODY = make_planar_quad_BODY( p1, p2, p3, p4 );
 
+   if(!new_BODY)
+     return NULL;
+
    // Build a VGI Body (i.e, the entire VGI structure) from this
    // ACIS BODY.
    BodySM *this_bodysm = AcisQueryEngine::instance()->populate_topology_bridges(new_BODY);
@@ -609,12 +500,22 @@
 // Creation Date : 10/24/96
 //-------------------------------------------------------------------------
 
-BodySM* AcisModifyEngine::copy_body ( BodySM* OSMEPtr) const
+BodySM* AcisModifyEngine::copy_body ( BodySM* body_sm ) const
 {
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    history_object.highLevelCopying = true;
+    DLIList<TopologyBridge*> my_bridges(1);
+    TopologyBridge *tb = CAST_TO( body_sm, TopologyBridge );
+    my_bridges.append( tb );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
      // Make sure that we have a valid pointer
-   assert(OSMEPtr != NULL) ;
+   assert(body_sm != NULL) ;
 
-   BodyACIS* bodyACISPtr = CAST_TO(OSMEPtr, BodyACIS) ;
+   BodyACIS* bodyACISPtr = CAST_TO(body_sm, BodyACIS) ;
 
      // Make sure that we have a valid BodyACIS
    assert(bodyACISPtr != NULL) ;
@@ -627,7 +528,15 @@
 
      // Build a VGI Body and return it.
    BodySM *this_bodysm = AcisQueryEngine::instance()->populate_topology_bridges(new_BODY_ptr);
-   return this_bodysm;
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<BodySM*> new_bodies(1);
+    new_bodies.append( this_bodysm );
+    AcisModifyEngine::instance()->stop_tracking_history( new_bodies, history_object ); 
+  }
+
+  return this_bodysm;
 }
 
 CubitStatus AcisModifyEngine::imprint_BODYs (BODY* body1_ptr,
@@ -790,7 +699,8 @@
 */
    // Also make sure that any healing attributes are removed from it
 #ifdef ACIS_HEALER
-   AcisHealerTool::instance()->end_BODY_for_healing( new_body_ptr );
+   if (new_body_ptr)
+       AcisHealerTool::instance()->end_BODY_for_healing( new_body_ptr );
 #endif
    return new_body_ptr;
 }
@@ -1363,6 +1273,60 @@
 }
 
 //=============================================================================
+// Function   : tweak_bend
+// Member Type: PUBLIC
+// Description: Bend solid bodies based on a bend radius and angle
+// Author     : Sam Showman
+// Date       : 06/23/08
+//=============================================================================
+CubitStatus AcisModifyEngine::tweak_bend(DLIList<BodySM*> &bend_bodies,
+			                 DLIList<BodySM*> &new_bodysm_list,
+                                         CubitVector& neutral_root,
+                                         CubitVector& bend_axis,
+					 CubitVector& bend_direction,
+					 double radius,
+					 double angle,
+                                         DLIList<CubitVector*> bend_regions,
+                                         double width,
+                                         CubitBoolean center_bend,
+                                         int num_points,
+                                         CubitBoolean keep_old_body,
+                                         CubitBoolean preview ) const
+{
+  
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( bend_bodies, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_bend(
+		bend_bodies,
+		new_bodysm_list,
+		neutral_root,
+		bend_axis,
+		bend_direction,
+		radius,
+		angle,
+        bend_regions,
+        width,
+        center_bend,
+        num_points,
+		keep_old_body,
+		preview);
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status; 
+}
+
+//=============================================================================
 // Function   : tweak_chamfer
 // Member Type: PUBLIC
 // Description: Chamfer curves on solid bodies.  The left and right offsets are
@@ -1379,8 +1343,24 @@
                                              CubitBoolean keep_old_body,
                                              CubitBoolean preview ) 
 {
-    return AcisTweakTool::instance()->tweak_chamfer( curve_list, left_offset,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_chamfer( curve_list, left_offset,
       new_bodysm_list, right_offset, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1406,9 +1386,25 @@
                                  CubitBoolean keep_old_body,
                                  CubitBoolean preview ) 
 {
-  return AcisTweakTool::instance()->tweak_chamfer( ref_vertex_list, offset1,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( ref_vertex_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_chamfer( ref_vertex_list, offset1,
     new_bodysm_list, edge1, offset2, edge2, offset3, edge3, keep_old_body,
     preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1425,8 +1421,24 @@
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) 
 {
-    return AcisTweakTool::instance()->tweak_fillet( curve_list, radius,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_fillet( curve_list, radius,
       new_bodysm_list, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1445,8 +1457,29 @@
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) 
 {
-  return AcisTweakTool::instance()->tweak_fillet( curve_ptr, start_radius,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges(1);
+    TopologyBridge *tb = CAST_TO( curve_ptr, TopologyBridge );
+    my_bridges.append( tb );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_fillet( curve_ptr, start_radius,
     end_radius, new_bodysm_ptr, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+    {
+      DLIList<BodySM*> new_bodies(1);
+      new_bodies.append( new_bodysm_ptr );
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodies, history_object ); 
+    }
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1464,8 +1497,24 @@
                                 CubitBoolean keep_old_body,
                                 CubitBoolean preview ) 
 {
-  return AcisTweakTool::instance()->tweak_fillet( ref_vertex_list, radius,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( ref_vertex_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_fillet( ref_vertex_list, radius,
     new_bodysm_list, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1481,8 +1530,24 @@
                                           CubitBoolean keep_old_body,
                                           CubitBoolean preview ) const
 {
-   return AcisTweakTool::instance()->tweak_move( surface_list, delta,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( surface_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+   CubitStatus status = AcisTweakTool::instance()->tweak_move( surface_list, delta,
      new_bodysm_list, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1498,8 +1563,24 @@
                                           CubitBoolean keep_old_body,
                                           CubitBoolean preview ) const
 {
-  return AcisTweakTool::instance()->tweak_move( curve_list, delta,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_move( curve_list, delta,
      new_bodysm_list, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1512,12 +1593,31 @@
 //=============================================================================
 CubitStatus AcisModifyEngine::tweak_offset( DLIList<Surface*> &surface_list,
                                             double offset_distance,
+                                            DLIList<Surface*> *add_surface_list_ptr, 
+                                            DLIList<double> *add_offset_list_ptr,
                                             DLIList<BodySM*> &new_bodysm_list,
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) const
 {
-   return AcisTweakTool::instance()->tweak_offset( surface_list,
-     offset_distance, new_bodysm_list, keep_old_body, preview );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( surface_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_offset( surface_list,
+    offset_distance, add_surface_list_ptr, add_offset_list_ptr, new_bodysm_list, 
+    keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1530,12 +1630,31 @@
 //=============================================================================
 CubitStatus AcisModifyEngine::tweak_offset( DLIList<Curve*> &curve_list,
                                             double offset_distance,
+                                            DLIList<Curve*> *add_curve_list_ptr, 
+                                            DLIList<double> *add_offset_list_ptr,
                                             DLIList<BodySM*> &new_bodysm_list,
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) const
 {
-  return AcisTweakTool::instance()->tweak_offset( curve_list, offset_distance,
-    new_bodysm_list, keep_old_body, preview );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_offset( curve_list, offset_distance,
+    add_curve_list_ptr, add_offset_list_ptr, new_bodysm_list, keep_old_body,
+    preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1549,12 +1668,27 @@
 CubitStatus AcisModifyEngine::tweak_remove( DLIList<Surface*> &ref_face_list,
                                             DLIList<BodySM*> &new_bodysm_list,
                                             CubitBoolean extend_adjoining,
-                                            CubitBoolean keep_surface,
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) const
 {
-   return AcisTweakTool::instance()->tweak_remove( ref_face_list,
-     new_bodysm_list, extend_adjoining, keep_surface, keep_old_body, preview );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( ref_face_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+   CubitStatus status = AcisTweakTool::instance()->tweak_remove( ref_face_list,
+     new_bodysm_list, extend_adjoining, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //================================================================================
@@ -1568,8 +1702,24 @@
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) const
 {
-  return AcisTweakTool::instance()->tweak_remove( curve_list, new_bodysm_list,
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_remove( curve_list, new_bodysm_list,
     keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1583,12 +1733,30 @@
 CubitStatus AcisModifyEngine::tweak_target( DLIList<Surface*> &surface_list,
                                             DLIList<Surface*> &target_face_list,
                                             DLIList<BodySM*> &new_bodysm_list,
+                                            CubitBoolean extend_flg,
+                                            CubitPlane *limit_plane,
                                             CubitBoolean reverse_flg,
                                             CubitBoolean keep_old_body,
                                             CubitBoolean preview ) const
 {
-   return AcisTweakTool::instance()->tweak_target( surface_list, target_face_list,
-     new_bodysm_list, reverse_flg, keep_old_body, preview );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( surface_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+   CubitStatus status = AcisTweakTool::instance()->tweak_target( surface_list, target_face_list,
+     new_bodysm_list, extend_flg, limit_plane, reverse_flg, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_bodysm_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1603,12 +1771,32 @@
 AcisModifyEngine::tweak_target( DLIList<Curve*> &curve_list,
                                 DLIList<Surface*> &target_surf_list,
                                 DLIList<BodySM*> &new_body_list,
+                                CubitBoolean extend_flg,
+                                CubitPlane *limit_plane,
                                 CubitBoolean reverse_flg,
                                 CubitBoolean keep_old_bodies,
-                                CubitBoolean preview ) const
+                                CubitBoolean preview,
+                                double max_area_increase /*= 0%*/ ) const
 {
-  return AcisTweakTool::instance()->tweak_target( curve_list, target_surf_list,
-    new_body_list, reverse_flg, keep_old_bodies, preview );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_target( curve_list, target_surf_list,
+    new_body_list, extend_flg, limit_plane, reverse_flg, keep_old_bodies, preview,
+    max_area_increase );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+  }
+
+  return status;
 }
 
 //=============================================================================
@@ -1625,12 +1813,75 @@
 AcisModifyEngine::tweak_target( DLIList<Curve*> &curve_list,
                                 DLIList<Curve*> &target_curve_list,
                                 DLIList<BodySM*> &new_body_list,
+                                CubitBoolean extend_flg,
+                                CubitPlane *limit_plane,
                                 CubitBoolean reverse_flg,
                                 CubitBoolean keep_old_bodies,
+                                CubitBoolean preview,
+                                double max_area_increase /*= 0*/ ) const
+{
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( curve_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = AcisTweakTool::instance()->tweak_target( curve_list, target_curve_list,
+    new_body_list, extend_flg, limit_plane, reverse_flg, keep_old_bodies, preview, max_area_increase );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+  }
+
+  return status;
+}
+
+//=============================================================================
+// Function   : tweak_target
+// Member Type: PUBLIC
+// Description: Tweak specified point of a sheet body to a given location.  The
+//              given point must be part of a planar surface or surfaces 
+//              attached to linear curves only.  The user specified which of 
+//              those surfaces to actually modify.  The given location will be
+//              projected to be on the given planar surface(s) before being
+//              used - this projected location must be the same on all surfaces.
+// Author     : Steve Storm
+// Date       : 09/09/08
+//=============================================================================
+CubitStatus
+AcisModifyEngine::tweak_target( Point *point_ptr,
+                                DLIList<Surface*> &modify_surface_list,
+                                CubitVector &target_loc,
+                                BodySM *&new_bodysm_ptr,
+                                CubitBoolean keep_old_body,
                                 CubitBoolean preview ) const
 {
-  return AcisTweakTool::instance()->tweak_target( curve_list, target_curve_list,
-    new_body_list, reverse_flg, keep_old_bodies, preview );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( modify_surface_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+  
+  CubitStatus status = AcisTweakTool::instance()->tweak_target( point_ptr,
+    modify_surface_list, target_loc, new_bodysm_ptr, keep_old_body, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( status )
+    {
+      DLIList<BodySM*> new_body_list(1);
+      new_body_list.append( new_bodysm_ptr );
+      AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+    }
+  }
+  
+  return status;
 }
 
 //================================================================================
@@ -1663,12 +1914,33 @@
 // Author     : Tyronne Lim
 // Date       : 08/18/03
 //================================================================================
-CubitStatus AcisModifyEngine::create_offset_surface( Surface* ref_face_ptr, BodySM*& new_body, double offset_distance ) const
+CubitStatus AcisModifyEngine::create_offset_surface( Surface* surf_ptr,
+                                                     BodySM*& new_body,
+                                                     double offset_distance ) const
 {
-   return AcisSurfaceTool::instance()->create_offset_surface( ref_face_ptr, new_body, offset_distance );
+   return AcisSurfaceTool::instance()->create_offset_surface( surf_ptr, new_body, 
+     offset_distance );
 }
 
 //================================================================================
+// Description: Creates an offset sheet.
+// Author     : Steve Storm
+// Date       : 05/04/08
+//================================================================================
+CubitStatus
+AcisModifyEngine::create_offset_sheet( DLIList<Surface*> &surface_list,
+                                       double offset_distance,
+                                       DLIList<Surface*> *add_surface_list_ptr,
+                                       DLIList<double> *add_offset_list_ptr,
+                                       DLIList<BodySM*> &new_body_list,
+                                       CubitBoolean preview ) const
+{
+  return AcisTweakTool::instance()->make_offset_sheet( surface_list,
+    offset_distance, add_surface_list_ptr, add_offset_list_ptr, new_body_list,
+    preview );
+}
+
+//================================================================================
 // Description: Creates an offset body.
 // Author     : Tyronne Lim
 // Date       : 08/18/03
@@ -1683,9 +1955,10 @@
 // Author     : Tyronne Lim
 // Date       : 08/18/03
 //================================================================================
-CubitStatus AcisModifyEngine::create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body ) const
+CubitStatus AcisModifyEngine::create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body,
+                                                   DLIList<Curve*>& guides) const
 {
-   return AcisSurfaceTool::instance()->create_skin_surface( curves, new_body );
+   return AcisSurfaceTool::instance()->create_skin_surface( curves, new_body, guides );
 }
 
 //================================================================================
@@ -1733,6 +2006,13 @@
    return AcisSurfaceTool::instance()->create_surface( vec_list, new_body, ref_face_ptr, project_points );
 }
 
+
+CubitStatus AcisModifyEngine::create_surface( DLIList<Point*>& points, 
+                                              BodySM *&new_body ) const
+{
+   return AcisSurfaceTool::instance()->create_surface( points, new_body );
+}
+
 //================================================================================
 // Description: Creates a weld surface.
 // Author     : Tyronne Lim
@@ -1904,6 +2184,27 @@
     return CUBIT_SUCCESS;
 }
 
+CubitBoolean AcisModifyEngine::bodies_interfering( BodySM *body1_ptr,
+                                                   BodySM *body2_ptr) const
+{
+  BODY* BODY1 =  AcisQueryEngine::get_BODY(body1_ptr);
+  BODY* BODY2 =  AcisQueryEngine::get_BODY(body2_ptr);
+  
+  SPAbox spa_box1, spa_box2;
+  spa_box1 = AcisQueryEngine::instance()->bounding_box( BODY1 );
+  spa_box2 = AcisQueryEngine::instance()->bounding_box( BODY2 );
+
+  CubitBox box1 = AcisQueryEngine::bounding_box( spa_box1 );
+  CubitBox box2 = AcisQueryEngine::bounding_box( spa_box2 );
+
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+  
+  if( box1.overlap( tolerance, box2 ) )
+    return BODYs_interfering( BODY1, BODY2 );
+
+  return CUBIT_FALSE;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Determines whether the 2 input ACIS BODYs overlap
 //                 in any way at all.
@@ -2008,24 +2309,8 @@
   }
 
   //stitch together to form a sheet body.
-#if CUBIT_ACIS_VERSION < 1100
-
-  for( i=0; i<copied_FACES.count(); i++ )
-  {
-    result = api_unite((BODY*)copied_FACES[i], master );
-    if( !result.ok() )
-    {
-      PRINT_ERROR("Problems stitching surfaces\n");
-      //delete all other surface
-      for(; i<copied_FACES.count(); i++)
-        api_delent( copied_FACES[i]);
-      return CUBIT_FAILURE;
-    }
-  }
-#else
   exact_stitch_options stitch_opts;
   result = api_stitch( master, copied_FACES, &stitch_opts );
-#endif
 
   if( !result.ok() )
   {
@@ -2581,6 +2866,7 @@
    ACIS_sweep_options.set_draft_angle(draft_angle);
    ACIS_sweep_options.set_gap_type(draft_type);
    ACIS_sweep_options.set_rigid(rigid);
+   ACIS_sweep_options.set_solid(false);
    EDGE *copied_EDGE_ptr = NULL;
    result = api_edge( EDGE_ptr, copied_EDGE_ptr);
 
@@ -2852,6 +3138,7 @@
    ACIS_sweep_options.set_draft_angle(draft_angle);
    ACIS_sweep_options.set_gap_type(draft_type);
    ACIS_sweep_options.set_rigid(rigid);
+   ACIS_sweep_options.set_solid(false);
    EDGE *copied_EDGE_ptr = NULL;
    result = api_edge( EDGE_ptr, copied_EDGE_ptr );
    if( !result.ok() )
@@ -3308,6 +3595,7 @@
    if(make_solid)
    {
      ACIS_sweep_options.set_close_to_axis(TRUE);
+     ACIS_sweep_options.set_solid(TRUE);
      EDGE* EDGES[1];
      EDGES[0] = copied_EDGE_ptr;
      BODY* EDGE_BODY_ptr = NULL;
@@ -3322,6 +3610,8 @@
 
    }
    else {
+     ACIS_sweep_options.set_solid(FALSE);
+     ACIS_sweep_options.set_two_sided(TRUE);
      result = api_sweep_with_options(copied_EDGE_ptr,
                                      ACIS_point, ACIS_axis_unit_vector,
                                      &ACIS_sweep_options, BODYptr);
@@ -4021,10 +4311,15 @@
 // body that will result from this.  The height of the cone
 // is determined by a factor of the model limits currently
 // in cubit.
-FACE* AcisModifyEngine::make_type_FACE( CONE *CONE_ptr ) const
+FACE* AcisModifyEngine::make_type_FACE( CONE *CONE_ptr, FACE *FACE_ptr,
+                                        CubitBox *limit_box ) const
 {
      //Given this lets create another face that is extended from it.
-   CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box();
+   CubitBox bounding_box;
+   if( !limit_box )
+     bounding_box = GeometryQueryTool::instance()->model_bounding_box();
+   else
+     bounding_box = *limit_box;
 
    BODY *sheet_body;
    CubitBoolean cylinder = CUBIT_FALSE;
@@ -4033,7 +4328,7 @@
    double const end_ang = 2*CUBIT_PI;
    double cost = CONE_ptr->cosine_angle();
    double sint = CONE_ptr->sine_angle();
-   if ( sint == 0.0 && fabs(cost) == 1.0 )
+   if( sint == 0.0 && fabs(cost) == 1.0 )
    {
        //This is a cylinder.
      cylinder = CUBIT_TRUE;
@@ -4047,6 +4342,7 @@
    CubitVector temp_norm( normal_a.x(), normal_a.y(), normal_a.z());
    if ( !cylinder )
    {
+     //forces cone direction vector to point towards the apex
      if ( sint > 0.0 && cost > 0.0 )
      {
        sint = -sint;
@@ -4062,23 +4358,42 @@
      double theta_rad = acos(cost);
      elipse_radius.set(major_a.x(), major_a.y(), major_a.z() );
      double old_radius = elipse_radius.length();
-     double old_height = old_radius/tan(theta_rad);
-
-     //make center of surface along axis, 1/2 height of
-     //bounding box of entire model.
+     double old_height = fabs(old_radius/tan(theta_rad));
      CubitVector root_vec( root.x(), root.y(), root.z() );
-     center_vec = root_vec + (-0.5*height)*temp_norm;
 
-     //calculate new radius
-     double new_radius = (old_height+ 0.5*height) * tan (theta_rad );
+     //get the tip of the cone
+     CubitVector cone_point = root_vec + (temp_norm * old_height);
+
+     //----------CENTER--------
+     //get center of bbox of FACE
+     SPAbox bbox = AcisQueryEngine::instance()->bounding_box( FACE_ptr );
+     SPAposition tmp_center = bbox.mid();
+     CubitVector bbox_center( tmp_center.x(), tmp_center.y(), tmp_center.z() );
+     bbox_center -= root_vec; 
+     double dot_prod = temp_norm % bbox_center;
+     center_vec = root_vec + temp_norm*dot_prod;
+     center_vec = center_vec - (temp_norm*(height*0.5)); 
+
+     CubitVector tmp_vec = center_vec - cone_point;
+     if( height > tmp_vec.length() )
+     {
+       //recalculate the center
+       center_vec = cone_point - (temp_norm*(height));
+     }
+
+     //----------RADIUS--------
+     tmp_vec = cone_point - center_vec;
+     double new_radius = tan(theta_rad)*tmp_vec.length();
      elipse_radius.normalize();
      elipse_radius *= new_radius;
    }
    else
    {
      CubitVector root_vec( root.x(), root.y(), root.z() );
-     center_vec = .5*height*temp_norm;
-     center_vec = root_vec - center_vec;
+     CubitVector cyl_root_to_box_center = bounding_box.center() - root_vec;
+     double dist_to_center_along_cyl_norm = cyl_root_to_box_center % temp_norm;
+     CubitVector new_center = root_vec + dist_to_center_along_cyl_norm * temp_norm;
+     center_vec = new_center - .5*height*temp_norm;
      elipse_radius.set(major_a.x(), major_a.y(), major_a.z() );
    }
    SPAvector const major_axis(elipse_radius.x(), elipse_radius.y(), elipse_radius.z() );
@@ -4270,48 +4585,446 @@
 
    return sheet_body->lump()->shell()->first_face();
 }
+
+
+
+#if CUBIT_ACIS_VERSION < 1900
 // This function will create a spline face using the info
 // from the existing spline.  It is actually a face or sheet
-// body that will result from this. The new spher face or sheet
-// will be the grand spline itself, not a section of it.
-FACE* AcisModifyEngine::make_type_FACE( SPLINE *SPLINE_ptr ) const
+// body that will result from this.
+FACE* AcisModifyEngine::make_type_FACE( SPLINE *SPLINE_ptr, CubitBox *limit_box_ptr ) const
 {
-   BODY *sheet_body;
-   PRINT_WARNING("Extents of spline will be only as far as\n"
-                 "the spline definition, this really isn't an infinite surface.\n");
+  // Need to figure out how far to extend the surface out, in parameter space.
+  // This is a difficult problem... for now, we just try extending out a huge
+  // amount, and trim to the given input box.  This is not guaranteed to work;
+  // if we fail, we just return the whole of the given spline surface (i.e.,
+  // extended out to current limits of UV, with 4 EDGEs max).
 
-     //use the geometry to make the spline body.
-   surface const *this_spline = &(SPLINE_ptr->equation());
+  // Get UV max/min of surface
+  //SPAbox *bbox = spline_FACE->bound();
+  SPAinterval u_face_range;
+  u_face_range = SPLINE_ptr->equation().param_range_u();
 
-     //make a spline body then move it to the give place.
-   outcome result = api_make_spline( *((spline*)this_spline), sheet_body );
-   if (!result.ok() || sheet_body == NULL ||
-       sheet_body->lump() == NULL ||
-       sheet_body->lump()->shell() == NULL ||
-       sheet_body->lump()->shell()->first_face() == NULL ||
-       sheet_body->lump()->shell()->first_face()->geometry() == NULL )
-   {
-      PRINT_ERROR("In AcisModifyEngine::make_type_FACE(spline)\n"
-                  "       ACIS api_make_spline function failed.\n\n");
-      AcisQueryEngine::instance()->ACIS_API_error (result);
+  double u_min = u_face_range.start_pt();
+  double u_max = u_face_range.end_pt();
+
+  // Debug - check if it is bounded in U
+  if( DEBUG_FLAG(168) && u_face_range.bounded() )
+  {
+    PRINT_INFO( "U lower bound = %f\n", u_min );
+    PRINT_INFO( "U upper bound = %f\n", u_max );
+  }
+  else if( DEBUG_FLAG(168) )
+    PRINT_INFO( "Unbounded in U\n" );
+
+  SPAinterval v_face_range;
+  v_face_range = SPLINE_ptr->equation().param_range_v();
+
+  double v_min = v_face_range.start_pt();
+  double v_max = v_face_range.end_pt();
+
+  // Debug - check if it is bounded in V
+  if( DEBUG_FLAG(168) && v_face_range.bounded() )
+  {
+    PRINT_INFO( "V lower bound = %f\n", v_min );
+    PRINT_INFO( "V upper bound = %f\n", v_max );
+  }
+  else if( DEBUG_FLAG(168) )
+    PRINT_INFO( "Unbounded in V\n" );
+
+  // Try going out a huge amount (I feel really bad doing it this way - we need
+  // to find a better way).
+  double range_u = 1e5*fabs( u_max - u_min );
+  double range_v = 1e5*fabs( v_max - v_min );
+
+  // Setup the expansion each direction
+  SPAinterval u_interval( u_min-range_u, u_max+range_u );
+  SPAinterval v_interval( v_min-range_v, v_max+range_v );
+  SPApar_box pb( u_interval, v_interval );
+  
+  double low_u = pb.low().u;
+  double high_u = pb.high().u;
+  double low_v = pb.low().v;
+  double high_v = pb.high().v;
+
+  PRINT_DEBUG_168( "  Requested U range = %lf, %lf\n", low_u, high_u );
+  PRINT_DEBUG_168( "  Requested V range = %lf, %lf\n", low_v, high_v );
+
+  BODY *new_BODY_ptr = NULL;
+  outcome result;
+
+  // Method
+  // 1. Copy the surface of the FACE
+  // 2. Extend the surface in place using the function extend_face in the
+  //    header file surextnd.hxx.  This function is not documented.  It can
+  //    possibly return a smaller parameter range than requested, for example,
+  //    if the requested extension was found to be self-intersecting.  This is
+  //    goodness.
+  // 3. Make a new FACE from the extended surface.
+  // Different method from P_Face_Extend Scheme example from face_scm.cpp
+	//SPAtransf &strans=get_face_trans(spline_FACE);
+	//surface *tsurf = spline_FACE->geometry()->trans_surface(strans);
+	//SPApar_box testbox=extend_surface(*tsurf,pb);
+  //FACE *new_FACE_ptr = make_face_spline( *tsurf, *(curve const*)NULL_REF, 
+  //  *(curve const*)NULL_REF, *(curve const*)NULL_REF, *(curve const*)NULL_REF, 
+  //  testbox );
+  
+  surface *new_surf_ptr = SPLINE_ptr->equation().make_copy();
+  SPApar_box achieved_parbox = extend_surface( *new_surf_ptr, pb );
+ 
+  low_u = achieved_parbox.low().u;
+  high_u = achieved_parbox.high().u;
+  low_v = achieved_parbox.low().v;
+  high_v = achieved_parbox.high().v;
+
+  PRINT_DEBUG_168( "  Achieved U range = %lf to %lf\n", low_u, high_u );
+  PRINT_DEBUG_168( "  Achieved V range = %lf to %lf\n", low_v, high_v ); 
+  
+  CubitBoolean try_alt_method = CUBIT_FALSE;
+  FACE *new_FACE_ptr;
+  result = api_make_face_from_surface( new_surf_ptr, new_FACE_ptr );
+  ACIS_DELETE new_surf_ptr;
+  if( !result.ok() || new_FACE_ptr==NULL )
+    try_alt_method = CUBIT_TRUE;
+  else
+  {
+    // If no EDGEs need to try the alternate method
+    ENTITY_LIST EDGES;
+    api_get_edges( new_FACE_ptr, EDGES );
+    if( EDGES.count() == 0 )
+    {
+      try_alt_method = CUBIT_TRUE;
+      PRINT_DEBUG_168( "Got extended spline with zero edges - trying alternate method\n" );
+      api_delent( new_FACE_ptr );
+    }
+  }
+
+  // If we failed, try making a spline that just fits around the input FACE
+  if( try_alt_method == CUBIT_TRUE )
+  {
+    PRINT_DEBUG_168( "Using api_make_spline to extend spline surface\n" );
+    PRINT_WARNING("Extents of spline will be only as far as\n"
+      "the spline definition, this really isn't an infinite surface.\n");
+
+    // Use the geometry to make the spline body.
+    surface const *this_spline = &(SPLINE_ptr->equation());
+
+    // Make a spline body
+    outcome result = api_make_spline( *((spline*)this_spline), new_BODY_ptr );
+    if (!result.ok() || new_BODY_ptr == NULL ||
+      new_BODY_ptr->lump() == NULL ||
+      new_BODY_ptr->lump()->shell() == NULL ||
+      new_BODY_ptr->lump()->shell()->first_face() == NULL ||
+      new_BODY_ptr->lump()->shell()->first_face()->geometry() == NULL )
+    {
+      AcisQueryEngine::instance()->ACIS_API_error( result );
+      PRINT_ERROR("Unable to extend spline surface\n");
       return (FACE *)NULL;
-   }
-   result =  api_body_to_2d( sheet_body );
-   if (!result.ok())
-   {
-      PRINT_ERROR("In AcisModifyEngine::make_type_FACE(spline)\n"
-                  "       ACIS api_body_to_2d function failed.\n\n");
+    }
+    // We fail if we don't have any EDGEs
+    ENTITY_LIST EDGEs;
+    api_get_edges( new_FACE_ptr, EDGEs );
+    if( EDGEs.count() == 0 )
+    {
+      api_delent( new_BODY_ptr );
+      PRINT_ERROR("Couldn't create trimmed surface from extended spline\n");
+      return (FACE *)NULL;
+    }
+  }
+  else
+  {
+    // Convert to sheet BODY
+    FACE *FACE_list[1];
+    FACE_list[0] = new_FACE_ptr;
+    result = api_sheet_from_ff( 1, FACE_list, new_BODY_ptr );
+    if (!result.ok() || new_BODY_ptr == NULL || new_BODY_ptr->lump() == NULL
+      || new_BODY_ptr->lump()->shell() == NULL ||
+      new_BODY_ptr->lump()->shell()->first_face() == NULL )
+    {
+      api_delent( new_FACE_ptr );
       AcisQueryEngine::instance()->ACIS_API_error (result);
       return (FACE *)NULL;
-   }
+    }
+  }
 
-   return sheet_body->lump()->shell()->first_face();
+  // Make double sided
+  result =  api_body_to_2d( new_BODY_ptr );
+  if (!result.ok())
+  {
+    api_delent( new_BODY_ptr );
+    AcisQueryEngine::instance()->ACIS_API_error(result);
+    return (FACE *)NULL;
+  }
+
+  // Trim to input bounding box
+  CubitBox cubit_super_box;
+  if( !limit_box_ptr )
+  {
+    cubit_super_box = GeometryQueryTool::instance()->model_bounding_box();
+    cubit_super_box *= 1.1; // Expand out 10%
+    limit_box_ptr = &cubit_super_box;
+  }
+  trim_BODY_to_box( new_BODY_ptr, *limit_box_ptr );
+
+  // Check result
+  if( new_BODY_ptr == NULL )
+  {
+    PRINT_ERROR( "Unable to extend spline surface\n" );
+    return (FACE *)NULL;
+  }
+
+  // Return the FACE
+  return new_BODY_ptr->lump()->shell()->first_face();
 }
+#endif
+
+
+FACE* AcisModifyEngine::make_type_FACE( FACE *FACE_ptr, CubitBox *limit_box_ptr ) const
+{
+  
+  CubitBox bounding_box; 
+  if( !limit_box_ptr )
+  {
+    bounding_box = GeometryQueryTool::instance()->model_bounding_box();
+    bounding_box *= 1.1;
+    limit_box_ptr = &bounding_box;
+  }
+
+  FACE *face_list[1];
+  BODY *sheet_body = NULL;
+  face_list[0] = FACE_ptr;
+
+  // Make a FACE from copy_FACE.
+  outcome rc = api_sheet_from_ff(1, face_list, sheet_body);
+
+  if( rc.ok() )
+  {
+    ENTITY_LIST EDGES;
+    api_get_edges( sheet_body, EDGES );
+    double offset = limit_box_ptr->diagonal().length() * 0.5;
+    
+    SPAposition bb_low( limit_box_ptr->min_x(),
+                        limit_box_ptr->min_y(),
+                        limit_box_ptr->min_z() );
+    SPAposition bb_high( limit_box_ptr->max_x(),
+                         limit_box_ptr->max_y(),
+                         limit_box_ptr->max_z() );
+    
+    lop_options local_options;
+    rc = api_extend_sheetbody( EDGES, offset, bb_low, bb_high, &local_options );
+
+    if (!rc.ok())
+      sheet_body = NULL;
+  }
+  
+  if( sheet_body )
+  {
+    rc = api_body_to_2d( sheet_body );
+    trim_BODY_to_box( sheet_body, *limit_box_ptr );
+  }
+
+  if( sheet_body )
+      return sheet_body->lump()->shell()->first_face();
+  else  //do it the old, dangerous way.
+  {
+    //can only handle spline geometry
+    SURFACE *SURFACE_ptr = FACE_ptr->geometry();
+    int type = SURFACE_ptr->identity();
+
+    if( type != SPLINE_TYPE )
+      return NULL;
+
+    SPLINE *SPLINE_ptr = (SPLINE*)SURFACE_ptr;
+
+    // This is a difficult problem... for now, we just try extending out a huge
+    // amount, and trim to the given input box.  This is not guaranteed to work;
+    // if we fail, we just return the whole of the given spline surface (i.e.,
+    // extended out to current limits of UV, with 4 EDGEs max).
+
+    // Get UV max/min of surface
+    //SPAbox *bbox = spline_FACE->bound();
+    SPAinterval u_face_range;
+    u_face_range = SPLINE_ptr->equation().param_range_u();
+
+    double u_min = u_face_range.start_pt();
+    double u_max = u_face_range.end_pt();
+
+    // Debug - check if it is bounded in U
+    if( DEBUG_FLAG(168) && u_face_range.bounded() )
+    {
+      PRINT_INFO( "U lower bound = %f\n", u_min );
+      PRINT_INFO( "U upper bound = %f\n", u_max );
+    }
+    else if( DEBUG_FLAG(168) )
+      PRINT_INFO( "Unbounded in U\n" );
+
+    SPAinterval v_face_range;
+    v_face_range = SPLINE_ptr->equation().param_range_v();
+
+    double v_min = v_face_range.start_pt();
+    double v_max = v_face_range.end_pt();
+
+    // Debug - check if it is bounded in V
+    if( DEBUG_FLAG(168) && v_face_range.bounded() )
+    {
+      PRINT_INFO( "V lower bound = %f\n", v_min );
+      PRINT_INFO( "V upper bound = %f\n", v_max );
+    }
+    else if( DEBUG_FLAG(168) )
+      PRINT_INFO( "Unbounded in V\n" );
+
+    // Try going out a huge amount (I feel really bad doing it this way - we need
+    // to find a better way).
+    double range_u = 1e5*fabs( u_max - u_min );
+    double range_v = 1e5*fabs( v_max - v_min );
+
+    // Setup the expansion each direction
+    SPAinterval u_interval( u_min-range_u, u_max+range_u );
+    SPAinterval v_interval( v_min-range_v, v_max+range_v );
+    SPApar_box pb( u_interval, v_interval );
+    
+    double low_u = pb.low().u;
+    double high_u = pb.high().u;
+    double low_v = pb.low().v;
+    double high_v = pb.high().v;
+
+    PRINT_DEBUG_168( "  Requested U range = %lf, %lf\n", low_u, high_u );
+    PRINT_DEBUG_168( "  Requested V range = %lf, %lf\n", low_v, high_v );
+
+    BODY *new_BODY_ptr = NULL;
+    outcome result;
+
+    // Method
+    // 1. Copy the surface of the FACE
+    // 2. Extend the surface in place using the function extend_face in the
+    //    header file surextnd.hxx.  This function is not documented.  It can
+    //    possibly return a smaller parameter range than requested, for example,
+    //    if the requested extension was found to be self-intersecting.  This is
+    //    goodness.
+    // 3. Make a new FACE from the extended surface.
+    // Different method from P_Face_Extend Scheme example from face_scm.cpp
+          //SPAtransf &strans=get_face_trans(spline_FACE);
+          //surface *tsurf = spline_FACE->geometry()->trans_surface(strans);
+          //SPApar_box testbox=extend_surface(*tsurf,pb);
+    //FACE *new_FACE_ptr = make_face_spline( *tsurf, *(curve const*)NULL_REF, 
+    //  *(curve const*)NULL_REF, *(curve const*)NULL_REF, *(curve const*)NULL_REF, 
+    //  testbox );
+    
+    surface *new_surf_ptr = SPLINE_ptr->equation().make_copy();
+    SPApar_box achieved_parbox = extend_surface( *new_surf_ptr, pb );
+   
+    low_u = achieved_parbox.low().u;
+    high_u = achieved_parbox.high().u;
+    low_v = achieved_parbox.low().v;
+    high_v = achieved_parbox.high().v;
+
+    PRINT_DEBUG_168( "  Achieved U range = %lf to %lf\n", low_u, high_u );
+    PRINT_DEBUG_168( "  Achieved V range = %lf to %lf\n", low_v, high_v ); 
+    
+    CubitBoolean try_alt_method = CUBIT_FALSE;
+    FACE *new_FACE_ptr;
+    result = api_make_face_from_surface( new_surf_ptr, new_FACE_ptr );
+    ACIS_DELETE new_surf_ptr;
+    if( !result.ok() || new_FACE_ptr==NULL )
+      try_alt_method = CUBIT_TRUE;
+    else
+    {
+      // If no EDGEs need to try the alternate method
+      ENTITY_LIST EDGES;
+      api_get_edges( new_FACE_ptr, EDGES );
+      if( EDGES.count() == 0 )
+      {
+        try_alt_method = CUBIT_TRUE;
+        PRINT_DEBUG_168( "Got extended spline with zero edges - trying alternate method\n" );
+        api_delent( new_FACE_ptr );
+      }
+    }
+
+    // If we failed, try making a spline that just fits around the input FACE
+    if( try_alt_method == CUBIT_TRUE )
+    {
+      PRINT_DEBUG_168( "Using api_make_spline to extend spline surface\n" );
+      PRINT_WARNING("Extents of spline will be only as far as\n"
+        "the spline definition, this really isn't an infinite surface.\n");
+
+      // Use the geometry to make the spline body.
+      surface const *this_spline = &(SPLINE_ptr->equation());
+
+      // Make a spline body
+      outcome result = api_make_spline( *((spline*)this_spline), new_BODY_ptr );
+      if (!result.ok() || new_BODY_ptr == NULL ||
+        new_BODY_ptr->lump() == NULL ||
+        new_BODY_ptr->lump()->shell() == NULL ||
+        new_BODY_ptr->lump()->shell()->first_face() == NULL ||
+        new_BODY_ptr->lump()->shell()->first_face()->geometry() == NULL )
+      {
+        AcisQueryEngine::instance()->ACIS_API_error( result );
+        PRINT_ERROR("Unable to extend spline surface\n");
+        return (FACE *)NULL;
+      }
+      // We fail if we don't have any EDGEs
+      ENTITY_LIST EDGEs;
+      api_get_edges( new_FACE_ptr, EDGEs );
+      if( EDGEs.count() == 0 )
+      {
+        api_delent( new_BODY_ptr );
+        PRINT_ERROR("Couldn't create trimmed surface from extended spline\n");
+        return (FACE *)NULL;
+      }
+    }
+    else
+    {
+      // Convert to sheet BODY
+      FACE *FACE_list[1];
+      FACE_list[0] = new_FACE_ptr;
+      result = api_sheet_from_ff( 1, FACE_list, new_BODY_ptr );
+      if (!result.ok() || new_BODY_ptr == NULL || new_BODY_ptr->lump() == NULL
+        || new_BODY_ptr->lump()->shell() == NULL ||
+        new_BODY_ptr->lump()->shell()->first_face() == NULL )
+      {
+        api_delent( new_FACE_ptr );
+        AcisQueryEngine::instance()->ACIS_API_error (result);
+        return (FACE *)NULL;
+      }
+    }
+
+    // Make double sided
+    result =  api_body_to_2d( new_BODY_ptr );
+    if (!result.ok())
+    {
+      api_delent( new_BODY_ptr );
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      return (FACE *)NULL;
+    }
+
+    // Trim to input bounding box
+    CubitBox cubit_super_box;
+    if( !limit_box_ptr )
+    {
+      cubit_super_box = GeometryQueryTool::instance()->model_bounding_box();
+      cubit_super_box *= 1.1; // Expand out 10%
+      limit_box_ptr = &cubit_super_box;
+    }
+    trim_BODY_to_box( new_BODY_ptr, *limit_box_ptr );
+
+    // Check result
+    if( new_BODY_ptr == NULL )
+    {
+      PRINT_ERROR( "Unable to extend spline surface\n" );
+      return (FACE *)NULL;
+    }
+
+    // Return the FACE
+    return new_BODY_ptr->lump()->shell()->first_face();
+  }
+} 
+
 // This function will create a plane face using the info
 // from the existing plane.  It is actually a face or sheet
-// body that will result from this. The new spher face or sheet
+// body that will result from this. The new face or sheet
 // will be the grand plane itself, not a section of it.
-FACE* AcisModifyEngine::make_type_FACE( PLANE *PLANE_ptr ) const
+FACE* AcisModifyEngine::make_type_FACE( PLANE *PLANE_ptr, 
+                                        CubitBox *limit_box ) const
 {
      //first lets find 3 points.
    SPAposition point_1, point_2, point_3;
@@ -4322,8 +5035,14 @@
    PLANE_ptr->equation().eval( pos_2, point_2 );
    PLANE_ptr->equation().eval( pos_3, point_3 );
 
-   CubitBox cubit_super_box = GeometryQueryTool::instance()->model_bounding_box();
-   SPAbox super_box = AcisQueryEngine::bounding_box(cubit_super_box);
+   SPAbox super_box;
+   if( !limit_box )
+   {
+     CubitBox cubit_super_box = GeometryQueryTool::instance()->model_bounding_box();
+     super_box = AcisQueryEngine::bounding_box(cubit_super_box);
+   }
+   else
+     super_box = AcisQueryEngine::bounding_box( *limit_box );
 
    CubitVector vec_1( point_1.x(), point_1.y(), point_1.z() );
    CubitVector vec_2( point_2.x(), point_2.y(), point_2.z() );
@@ -4355,7 +5074,8 @@
 // Creation Date : 10/6/97
 //-------------------------------------------------------------------------
 FACE* AcisModifyEngine::make_FACE(FACE* FACE_ptr,
-                                    CubitBoolean extended_from) const
+                                  CubitBoolean extended_from,
+                                  CubitBox *limit_box_ptr ) const
 {
   if (FACE_ptr == NULL)
     return NULL;
@@ -4367,15 +5087,21 @@
     SURFACE *SURFACE_ptr = FACE_ptr->geometry();
     int type = SURFACE_ptr->identity();
     if (type == CONE_TYPE)
-      return make_type_FACE((CONE*)SURFACE_ptr);
+      return make_type_FACE((CONE*)SURFACE_ptr, FACE_ptr, limit_box_ptr);
     else if (type == SPHERE_TYPE)
       return make_type_FACE((SPHERE*)SURFACE_ptr);
     else if (type == TORUS_TYPE)
       return make_type_FACE((TORUS*)SURFACE_ptr);
     else if (type == SPLINE_TYPE)
-      return make_type_FACE((SPLINE*)SURFACE_ptr);
+    {
+#if CUBIT_ACIS_VERSION < 1900
+      return make_type_FACE((SPLINE*)SURFACE_ptr, limit_box_ptr);
+#else
+      return make_type_FACE( FACE_ptr, limit_box_ptr );
+#endif
+    }
     else if (type == PLANE_TYPE)
-      return make_type_FACE((PLANE*)SURFACE_ptr);
+      return make_type_FACE((PLANE*)SURFACE_ptr, limit_box_ptr);
     else
       return NULL;
   }
@@ -4420,6 +5146,41 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : This function creates a sheet body by extending out a
+//                 set of surfaces.  The sheet body is a double sided face
+//                 with no volume.
+//
+// Special Notes :
+//
+// Creator       : Steve Storm
+//
+// Creation Date : 2/27/08
+//-------------------------------------------------------------------------
+BODY* 
+AcisModifyEngine::make_extended_sheet( DLIList<FACE*> &FACE_list, 
+                                       CubitBox *clip_box_ptr,
+                                       bool suppress_errors /* = false */) const
+{
+  CubitBox clip_box;
+  if( !clip_box_ptr )
+  {
+    // Setup a default clipping box - 10% larger than Cubit model
+    clip_box = GeometryQueryTool::instance()->model_bounding_box();
+    clip_box *= 1.1;
+    clip_box_ptr = &clip_box;
+  }
+
+  BODY *ext_BODY_ptr;
+  if( AcisTweakTool::instance()->make_extended_sheet( FACE_list, ext_BODY_ptr,
+    clip_box_ptr, suppress_errors ) == CUBIT_FAILURE )
+  {
+    return NULL;
+  }
+
+  return ext_BODY_ptr;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : Creates an ACIS FACE, given the type of surface geometry
 //                 and an ordered list of bounding EDGEs.
 //
@@ -4780,66 +5541,66 @@
     // This will reactivate all the RefEntities that need to be kept.
   mark_owners_deactivated_flag(FACE_ptr, CUBIT_FALSE, CUBIT_TRUE);
 
-    // Where coincident vertices were merged by ACIS,
-    // make sure the lower ID is used.
-  input_EDGE_list.reset();
-
+  DLIList<VERTEX*> old_vertices;
   for (i = 0; i < input_EDGE_list.size(); i++)
   {
-      // get the copy and original EDGE
-    EDGE* cur_EDGE_new = EDGEs[i];
-    EDGE* cur_EDGE_old = input_EDGE_list.get_and_step();
+    ENTITY_LIST tmp_list;
+    api_get_vertices( input_EDGE_list.get_and_step(), tmp_list );
+       
+    old_vertices.append_unique( (VERTEX*)tmp_list[0] );
 
-      // If the original start RefVertex is deactivated,
-      // see if we need to swap it with the replacement RefVertex
-    VERTEX* cur_VERT_new = cur_EDGE_new->start();
-    VERTEX* cur_VERT_old = cur_EDGE_old->start();
+    if( tmp_list.count() > 1 )
+      old_vertices.append_unique( (VERTEX*)tmp_list[1] );
+  }
+  
+  //the following while loop attempts to put the lowest ids 
+  //from the original vertices of the edges onto the new 
+  //vertices of the surface.  It's done spatially.
+  ENTITY_LIST new_vertices; 
+  api_get_vertices( wire_BODY, new_vertices );
+  ENTITY *tmp_ent = NULL;
+  while( (tmp_ent=new_vertices.next())!=NULL )
+  {
+    VERTEX *new_VERTEX = (VERTEX*)tmp_ent;
 
-    for (int j = 2; j--; )
+    //find another vertex in 'old_vertices' that has same xyz 
+    //position as new_vertex
+    SPAposition pos = new_VERTEX->geometry()->coords();
+    CubitVector new_pos( pos.x(), pos.y(), pos.z() );
+    
+    for( i=old_vertices.size(); i--; )
     {
-      RefVertex* ref_vert_old =
-        CAST_TO(ATTRIB_CUBIT_OWNER::get_topology_entity(cur_VERT_old),
-                RefVertex);
+      VERTEX *old_VERTEX = old_vertices.get_and_step(); 
+      pos = old_VERTEX->geometry()->coords();
+      CubitVector old_pos( pos.x(), pos.y(), pos.z() );
 
-      AcisBridge* bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_VERT_old);
-
-      if (ref_vert_old && bridge_deactivated(bridge))
+      if( new_pos.distance_between( old_pos ) < 0.0001 )
       {
-        RefVertex* ref_vert_new =
-          CAST_TO(ATTRIB_CUBIT_OWNER::get_topology_entity(cur_VERT_new),
-                  RefVertex);
-        if (ref_vert_new && ref_vert_old->id() < ref_vert_new->id())
-        {
-          int id_old = ref_vert_old->id();
-          int id_new = ref_vert_new->id();
-          ref_vert_old->set_id(0);
-          ref_vert_new->set_id(id_old);
-          ref_vert_old->set_id(id_new);
-        }
-      }
+        RefVertex* ref_vert_old = CAST_TO(ATTRIB_CUBIT_OWNER::
+          get_topology_entity(old_VERTEX),RefVertex);
+        AcisBridge* bridge = ATTRIB_CUBIT_OWNER::cubit_owner(old_VERTEX);
 
-/*
-      PointACIS* ref_vert_old =
-        CAST_TO(ATTRIB_CUBIT_OWNER::cubit_owner(cur_VERT_old),PointACIS);
-
-      if (ref_vert_old && bridge_deactivated(ref_vert_old) && ref_vert_old->owner())
-      {
-        //RefVertex* ref_vert_new =
-        //  CAST_TO(ATTRIB_CUBIT_OWNER::get_topology_entity(cur_VERT_new),
-        //          RefVertex);
-        PointACIS* ref_vert_new =
-          CAST_TO(ATTRIB_CUBIT_OWNER::cubit_owner(cur_VERT_new),PointACIS);
-        if (ref_vert_new)
+        if (ref_vert_old && bridge_deactivated(bridge))
         {
-          ref_vert_old->owner()->swap_bridge(ref_vert_old,ref_vert_new,true);
+          RefVertex* ref_vert_new =
+            CAST_TO(ATTRIB_CUBIT_OWNER::get_topology_entity(new_VERTEX),
+                    RefVertex);
+          if (ref_vert_new && ref_vert_old->id() < ref_vert_new->id())
+          {
+            int id_old = ref_vert_old->id();
+            int id_new = ref_vert_new->id();
+            ref_vert_old->set_id(0);
+            ref_vert_new->set_id(id_old);
+            ref_vert_old->set_id(id_new);
+          }
         }
       }
-*/
-      cur_VERT_new = cur_EDGE_new->end();
-      cur_VERT_old = cur_EDGE_old->end();
     }
   }
 
+
+
+
     // Get rid of the stuff we aren't using.  This will delete the RefVertices
     // that correspond to the VERTEXes deleted by ACIS in api_make_ewire.
     // We also delete the original ACIS EDGEs since they are no longer
@@ -5447,6 +6208,7 @@
     // Start by going through each LUMP, if LUMPs are being used.
   LUMP* start_LUMP = cur_LUMP;
   CURVE *geometry = NULL;
+  CURVE *weak_match = NULL;
   do
   {
     PRINT_DEBUG_18( "**New Lump check**\n");
@@ -5460,19 +6222,24 @@
       COEDGE* start_COEDGE = cur_WIRE->coedge();
       cur_COEDGE = start_COEDGE;
         // Check it and loop through the rest
+      COEDGE *last_COEDGE = NULL;
       do
       {
         PRINT_DEBUG_18( "  **New CoEdge check**\n");
         cur_EDGE =  cur_COEDGE->edge();
+        SPAinterval curve_range = cur_EDGE->param_range();
+        if(cur_EDGE->sense() == REVERSED)
+          curve_range.negate();
         geometry = cur_EDGE->geometry();
           // See if this is close enough to
           // the start and end points
         if (geometry != NULL)
         {
           SPAposition new_point;
+          SPAparameter param1, param2;
             // Make sure start vertex is on curve
           geometry->equation().point_perp(from_VERTEX->geometry()->coords(),
-                                          new_point);
+                                          new_point, *(SPAparameter*)NULL_REF, param1);
           PRINT_DEBUG_18( "\n\tNew Point 1: (%g, %g, %g)\n"
                      "\t  From Vert: (%g, %g, %g)\n",
                      new_point.x(),
@@ -5486,7 +6253,7 @@
           {
               // Make sure end vertex is on curve
             geometry->equation().point_perp(to_VERTEX->geometry()->coords(),
-                                            new_point);
+                                            new_point, *(SPAparameter*)NULL_REF, param2);
             PRINT_DEBUG_18( "\tNew Point 2: (%g, %g, %g)\n"
                        "\t    To Vert: (%g, %g, %g) \n",
                        new_point.x(),
@@ -5498,16 +6265,21 @@
             if (AcisQueryEngine::instance()->about_spatially_equal(to_VERTEX->geometry()->coords(),
                                             new_point, 1.0))
             {
-                // You found it!!!
-              cur_WIRE = NULL;
-              start_LUMP = NULL;
-              break;
+              weak_match = geometry;
+              if(curve_range >> param1 && curve_range >> param2)
+              {
+                  // You found it!!!
+                cur_WIRE = NULL;
+                start_LUMP = NULL;
+                break;
+              }
             }
           }
         }
+        last_COEDGE = cur_COEDGE;
         cur_COEDGE = cur_COEDGE->next();
         geometry = NULL; // Make sure you indicate we haven't found geom
-      }while (cur_COEDGE != NULL && cur_COEDGE != start_COEDGE);
+      }while (cur_COEDGE != NULL && cur_COEDGE != start_COEDGE && cur_COEDGE != last_COEDGE);
         // You break out of this do-while loop when
         //   a) You find the correct EDGE
         //   b) There are no more COEDGEs in this WIRE
@@ -5573,6 +6345,9 @@
       PRINT_INFO("Exit loop for Other Reason!!!\n");
   }
 
+  if(!geometry && weak_match)
+    geometry = weak_match;
+
     // Make sure you found something valid
   if ( geometry == NULL )
   {
@@ -5780,6 +6555,15 @@
   DLIList<BODY*> old_BODY_list;
   DLIList<BodySM*> old_BodySM_list;
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges(1);
+    TopologyBridge *tmp_bridge = CAST_TO( bodysms.get(), TopologyBridge );
+    my_bridges.append( tmp_bridge ); 
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
   BodySM* BodySMPtr = bodysms.get_and_step();
   BODY* BODYPtr =  AcisQueryEngine::get_BODY(BodySMPtr);
   old_BodySM_list.append(BodySMPtr);
@@ -5809,10 +6593,9 @@
   outcome result = api_boolean_chop_body(tool_BODY, blank_BODY, nonreg,outside_BODY, leftovers_BODY);
 
   if (!result.ok() || blank_BODY == NULL ||  
-       tool_BODY == NULL || blank_BODY->lump() == NULL )
+       tool_BODY == NULL || blank_BODY->lump() == NULL ||
+       outside_BODY->lump() == NULL )
   {
-
-
     if( !result.ok() )
     {
       PRINT_ERROR("In AcisModifyEngine::chop\n");
@@ -5834,6 +6617,17 @@
         AcisQueryEngine::instance()->delete_ACIS_BODY(outside_BODY, CUBIT_TRUE);
     }
 
+    if( outside_BODY->lump() == NULL )
+    {
+      PRINT_ERROR("tool body completely encloses blank.\n");
+      if (blank_BODY != NULL) 
+        AcisQueryEngine::instance()->delete_ACIS_BODY(blank_BODY, CUBIT_TRUE);
+      if (leftovers_BODY != NULL) 
+        AcisQueryEngine::instance()->delete_ACIS_BODY(leftovers_BODY, CUBIT_TRUE);
+      if (outside_BODY != NULL) 
+        AcisQueryEngine::instance()->delete_ACIS_BODY(outside_BODY, CUBIT_TRUE);
+    }
+
     return CUBIT_FAILURE;
   }
 
@@ -5842,6 +6636,14 @@
   BodySM* outsideBody =  get_new_Body(old_BodySM_list, old_BODY_list, outside_BODY, keep_old);
   outsideBodies.append( outsideBody );
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<BodySM*> new_bodies;
+    new_bodies.append( intersectBody );
+    new_bodies.append( outsideBody );
+    AcisModifyEngine::instance()->stop_tracking_history( new_bodies, history_object ); 
+  }
+
   return CUBIT_SUCCESS;
 }
 
@@ -5857,7 +6659,6 @@
 //-------------------------------------------------------------------------
 CubitStatus
 AcisModifyEngine::flip_normals( DLIList<Surface*>& ref_face_list ) const
-
 {
   bool delete_attribs =
     (GeometryModifyTool::instance()->get_new_ids() != 0);
@@ -5878,21 +6679,20 @@
   while( copied_ref_face_list.size() )
   {
     BODY *copied_BODY_ptr;
-#ifdef BOYD07
-    DLIList<SurfaceACIS*> reverse_face_list;
-#endif
     DLIList<FACE*> reverse_FACE_list;
     if( get_copied_FACES_of_body( copied_ref_face_list, reverse_FACE_list,
       copied_BODY_ptr ) == CUBIT_FAILURE )
       break;
 
     // Get original Body and BODY
-    BodySM *body_ptr = AcisQueryEngine::instance()->get_body_sm_of_ENTITY( copied_BODY_ptr );
+    BodySM *body_ptr = AcisQueryEngine::instance()->
+      get_body_sm_of_ENTITY( copied_BODY_ptr );
     BODY *BODY_ptr = AcisQueryEngine::get_BODY(body_ptr);
 
     // Now cleanout the owner attributes from the copied BODY, if required
     if( delete_attribs )
-      AcisQueryEngine::instance()->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
+      AcisQueryEngine::instance()->
+      remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
 
     reverse_FACE_list.reset();
     for( i=reverse_FACE_list.size(); i--; )
@@ -5909,18 +6709,7 @@
       }
     }
 
-    BodySM* new_body_ptr = get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr, CUBIT_FALSE );
-
-    if( new_body_ptr!=NULL && new_body_ptr!=body_ptr )
-    {
-      PRINT_INFO( "Created new volume\n" );
-    }
-    else if( new_body_ptr!=NULL && new_body_ptr==body_ptr )
-    {
-      PRINT_INFO( "Modified volume\n" );
-    }
-    else
-      PRINT_WARNING( "Volume was not modified\n" );
+    get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr, CUBIT_FALSE );
   }
 
   return CUBIT_SUCCESS;
@@ -6130,7 +6919,75 @@
 #endif
 }
 
+void AcisModifyEngine::get_possible_invalid_tbs(DLIList<TopologyBridge*> &bridges_in,
+                             DLIList<TopologyBridge*> &bridges_out)
+{
+  int i, j;
+  DLIList<ENTITY*> old_ENTITIES;
 
+  for(j=bridges_in.size(); j--;)
+  {
+    AcisBridge *ab = dynamic_cast<AcisBridge*>(bridges_in.get_and_step());
+    if(ab)
+    {
+      ENTITY *top_ENTITY = ab->ENTITY_ptr();
+      if(top_ENTITY)
+      {
+        ENTITY_LIST ENTITIES;
+        // vertices
+        api_get_vertices( top_ENTITY, ENTITIES);
+        for (i = 0; i < ENTITIES.count(); i++)
+        {
+          ab = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITIES[i]);
+          TopologyBridge *tb = dynamic_cast<TopologyBridge*>(ab);
+          if(tb)
+          {
+            TopologyBridge *tb_owner = dynamic_cast<TopologyBridge*>(tb->owner());
+            if(tb_owner)
+              bridges_out.append(tb_owner);
+            else
+              bridges_out.append(tb);
+          }
+        }
+        ENTITIES.clear();
+
+        // edges
+        api_get_edges( top_ENTITY, ENTITIES);
+        for (i = 0; i < ENTITIES.count(); i++)
+        {
+          ab = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITIES[i]);
+          TopologyBridge *tb = dynamic_cast<TopologyBridge*>(ab);
+          if(tb)
+          {
+            TopologyBridge *tb_owner = dynamic_cast<TopologyBridge*>(tb->owner());
+            if(tb_owner)
+              bridges_out.append(tb_owner);
+            else
+              bridges_out.append(tb);
+          }
+        }
+        ENTITIES.clear();
+        // faces
+        api_get_faces( top_ENTITY, ENTITIES);
+        for (i = 0; i < ENTITIES.count(); i++)
+        {
+          ab = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITIES[i]);
+          TopologyBridge *tb = dynamic_cast<TopologyBridge*>(ab);
+          if(tb)
+          {
+            TopologyBridge *tb_owner = dynamic_cast<TopologyBridge*>(tb->owner());
+            if(tb_owner)
+              bridges_out.append(tb_owner);
+            else
+              bridges_out.append(tb);
+          }
+        }
+      }
+    }
+  }
+  bridges_out.uniquify_ordered();
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Boolean Operation of a list of Bodies: unite
 //
@@ -6142,7 +6999,7 @@
 //-------------------------------------------------------------------------
 CubitStatus AcisModifyEngine::unite(DLIList<BodySM*> &bodies,
                                     DLIList<BodySM*> &newBodies,
-                                      bool keep_old) const
+                                    bool keep_old) const
 {
     // Union all bodies in the bodies list into a single body.
   if (bodies.size() <= 1)
@@ -6151,26 +7008,31 @@
     return CUBIT_FAILURE;
   }
 
-    // Create new acis bodies that are copies of the original acis bodies.
-    // If something goes wrong in the unioning, we can then delete our copies
-    // and the originals are intact.  If everything goes fine, we will delete
-    // the originals at that time.
+  // Create new acis bodies that are copies of the original acis bodies.
+  // If something goes wrong in the unioning, we can then delete our copies
+  // and the originals are intact.  If everything goes fine, we will delete
+  // the originals at that time.
 
-    // pass in keep_old to the delete_owner_attrib flag; if we're not keeping
-    // old bodies, we want to keep the owner attrib, so we can pick up entities
-    // that didn't change
-   bool delete_attribs =
-      (GeometryModifyTool::instance()->get_new_ids() || keep_old);
+  // pass in keep_old to the delete_owner_attrib flag; if we're not keeping
+  // old bodies, we want to keep the owner attrib, so we can pick up entities
+  // that didn't change
+  bool delete_attribs = (GeometryModifyTool::instance()->get_new_ids() || keep_old);
 
-   // check if the boolean operation is regularized or nonregularized
-     BOOL_TYPE bool_type = UNION;
-	CubitBoolean boolean_regularize = GeometryModifyTool::instance()->boolean_regularize();
+  // check if the boolean operation is regularized or nonregularized
+  BOOL_TYPE bool_type = UNION;
+  CubitBoolean boolean_regularize = GeometryModifyTool::instance()->boolean_regularize();
 
-	if (boolean_regularize == FALSE)
-	{
-		bool_type = NONREG_UNION;
-	}
+  if(boolean_regularize == FALSE)
+    bool_type = NONREG_UNION;
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( bodies, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
   DLIList<BODY*> old_BODY_list;
   DLIList<BodySM*> old_Body_list;
 
@@ -6181,9 +7043,7 @@
 
   BODY *master = this->copy_BODY(BODYPtr, delete_attribs);
   if (master == NULL)
-  {
     return CUBIT_FAILURE; // Nothing to clean up at this point.
-  }
 
 
     // Note: one iteration less because we already pulled out one body above
@@ -6200,15 +7060,13 @@
     }
 
 
-	// Do the union of the master and the copy.
+    // Do the union of the master and the copy.
     // If this is successful, the result is master and copy will be deleted
     // outcome result = api_unite(copy, master);
-	// replaced with the api_boolean call in order to do nonregularize boolean operation
+    // replaced with the api_boolean call in order to do nonregularize boolean operation
 
-	 outcome result = api_boolean (copy,master,bool_type);
+    outcome result = api_boolean (copy,master,bool_type);
 
-
-
     if (!result.ok() || (master && master->lump() == NULL))
     {
       // If there are no LUMPs in the resulting BODY, return with a failure
@@ -6228,58 +7086,57 @@
       old_Body_list.append(BodyPtr);
       old_BODY_list.append(BODYPtr);
     }
+    
+    //For nonregularized boolean, find all internal surfaces and delete
 
-		//For nonregularized boolean, find all internal surfaces and delete
+    if( bool_type == NONREG_UNION)
+    {
+      outcome result1;
+      // ENTITY_LIST FACES;
+      DLIList<FACE*>  FACE_list ;
+      FACE *this_FACE;
+      AcisQueryEngine::instance()->get_FACEs(master,FACE_list);
+      // loop through all faces
+      for( int i = 0; i< FACE_list.size(); i++)
+      {
+        this_FACE = FACE_list.get_and_step();
+        assert( this_FACE != NULL );
+        // Make sure this is a DOUBLE_SIDED FACE
+        if (this_FACE->sides() == DOUBLE_SIDED)
+        {
+          if (this_FACE->cont()==BOTH_INSIDE)
+          {
+            // found internal faces
+            // Now we have the FACE - unhook it  from the BODY.  Keep track of new
+            // BODIES that are created as this is done.
+             PRINT_INFO( " Unhooking and deleting each internal surface...\n" );
+             BODY *new_BODY_ptr;
+             result1 = api_unhook_face( this_FACE, new_BODY_ptr );
+             if( !result1.ok() )
+             {
+               AcisModifyEngine::instance()->get_acis_query_engine()->ACIS_API_error( result1 );
+               PRINT_ERROR( " Face unhooking during rebuild of volume didn't work\n" );
+               return CUBIT_FAILURE;
+             }
+	     AcisQueryEngine::instance()->delete_ACIS_BODY (new_BODY_ptr);
+           }
+         }
+       }
 
-	if ( bool_type == NONREG_UNION)
-	{
-		  outcome result1;
-		  // ENTITY_LIST FACES;
-          DLIList<FACE*>  FACE_list ;
-		  FACE *this_FACE;
-          AcisQueryEngine::instance()->get_FACEs(master,FACE_list);
-		   // loop through all faces
-		  for( int i = 0; i< FACE_list.size(); i++)
-		  {
-			  this_FACE = FACE_list.get_and_step();
-			  assert( this_FACE != NULL );
-			  // Make sure this is a DOUBLE_SIDED FACE
-			  if (this_FACE->sides() == DOUBLE_SIDED)
-			  {
-				  if (this_FACE->cont()==BOTH_INSIDE)
-				  {
-					  // found internal faces
-					  // Now we have the FACE - unhook it  from the BODY.  Keep track of new
-					  // BODIES that are created as this is done.
-					   PRINT_INFO( " Unhooking and deleting each internal surface...\n" );
-					   BODY *new_BODY_ptr;
-					   result1 = api_unhook_face( this_FACE, new_BODY_ptr );
-					   if( !result1.ok() )
-					   {
-						   AcisModifyEngine::instance()->get_acis_query_engine()->ACIS_API_error( result1 );
-						   PRINT_ERROR( " Face unhooking during rebuild of volume didn't work\n" );
-						   return CUBIT_FAILURE;
-					   }
-					   AcisQueryEngine::instance()->delete_ACIS_BODY (new_BODY_ptr);
-				  }
-			  }
-		  }
-
-		 // heal the leftover body
+// heal the leftover body
 //
-//		   PRINT_INFO(" Healing the leftover volume...\n");
-//		   if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
-//		   {
-//			   int percent_before, percent_after, number_splines_simplified;
-//			   if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
-//				   percent_after, number_splines_simplified ) == CUBIT_FAILURE )
-//				   PRINT_ERROR( "Error healing the combined volume\n" );
-//			   else
-//				   PRINT_INFO( "Successfully healed the combined volume!\n" );
-//			   AcisHealerTool::instance()->end_BODY_for_healing( master );
-//		   }
-	}
-
+//     PRINT_INFO(" Healing the leftover volume...\n");
+//     if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
+//     {
+//	 int percent_before, percent_after, number_splines_simplified;
+//	 if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
+//	        percent_after, number_splines_simplified ) == CUBIT_FAILURE )
+//	        PRINT_ERROR( "Error healing the combined volume\n" );
+//       else
+//         PRINT_INFO( "Successfully healed the combined volume!\n" );
+//	 AcisHealerTool::instance()->end_BODY_for_healing( master );
+//     }
+    }
   }
 
   AcisQueryEngine::instance()->clear_bounding_box( master );
@@ -6288,6 +7145,9 @@
   BodySM *newBodyPtr = get_new_Body(old_Body_list, old_BODY_list, master, keep_old);
   newBodies.append( newBodyPtr );
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( newBodies, history_object ); 
+
   return CUBIT_SUCCESS;
 }
 
@@ -6304,27 +7164,25 @@
       (GeometryModifyTool::instance()->get_new_ids() || keep_old);
 
   // check if the boolean operation is regularized or nonregularized
-     BOOL_TYPE bool_type = SUBTRACTION;
-	CubitBoolean boolean_regularize = GeometryModifyTool::instance()->boolean_regularize();
+  BOOL_TYPE bool_type = SUBTRACTION;
+  CubitBoolean boolean_regularize = GeometryModifyTool::instance()->boolean_regularize();
 
-	if (boolean_regularize == FALSE)
-	{
-		bool_type = NONREG_SUBTRACTION;
-	}
+  if(boolean_regularize == FALSE)
+    bool_type = NONREG_SUBTRACTION;
 
   int ii;
   DLIList<CubitBox*> tool_boxes;
 
   CubitBox tool_box;
 
-
   DLIList<BODY*> tool_BODY_list;
   DLIList<BODY*> tool_BODY_list_copy;
 
   // get acis bodies, and copy them
   tool_body_list.reset();
 
-  for (ii = tool_body_list.size(); ii > 0; ii--) {
+  for (ii = tool_body_list.size(); ii > 0; ii--) 
+  {
     CubitBox *temp_box = new CubitBox(
 	    AcisQueryEngine::instance()->bounding_box(tool_body_list.get()));
     tool_boxes.append(temp_box);
@@ -6343,6 +7201,13 @@
     return CUBIT_FAILURE;
   }
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( from_bodies, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
 
   DLIList<BODY*> from_BODY_list;
   DLIList<BODY*> from_BODY_list_copy;
@@ -6350,7 +7215,8 @@
   // get acis bodies, and copy them
   from_bodies.reset();
 
-  for (ii = from_bodies.size(); ii > 0; ii--) {
+  for (ii = from_bodies.size(); ii > 0; ii--) 
+  {
     BODY *BODYPtr1 = AcisQueryEngine::get_BODY(from_bodies.get_and_step());
     from_BODY_list.append(BODYPtr1);
 
@@ -6365,7 +7231,6 @@
     return CUBIT_FAILURE;
   }
 
-
   // now, subtract the tool from the list of bodies
   tool_BODY_list.reset();
   tool_BODY_list_copy.reset();
@@ -6455,55 +7320,54 @@
           tool_BODY_list_copy.change_to(tool_BODY_copy);
         }
       
-				//For nonregularized boolean, find all internal surfaces and delete
-
+	//For nonregularized boolean, find all internal surfaces and delete
 	if ( bool_type == NONREG_SUBTRACTION)
 	{
-		  outcome result1;
+	  outcome result1;
 		  // ENTITY_LIST FACES;
           DLIList<FACE*>  FACE_list ;
-		  FACE *this_FACE;
+          FACE *this_FACE;
           AcisQueryEngine::instance()->get_FACEs(from_BODY_copy,FACE_list);
-		   // loop through all faces
-		  for( int i = 0; i< FACE_list.size(); i++)
-		  {
-			  this_FACE = FACE_list.get_and_step();
-			  assert( this_FACE != NULL );
-			  // Make sure this is a DOUBLE_SIDED FACE
-			  if (this_FACE->sides() == DOUBLE_SIDED)
-			  {
-				  if (this_FACE->cont()==BOTH_INSIDE)
-				  {
-					  // found internal faces
-					  // Now we have the FACE - unhook it  from the BODY.  Keep track of new
-					  // BODIES that are created as this is done.
-					   PRINT_INFO( " Unhooking and deleting each internal surface...\n" );
-					   BODY *new_BODY_ptr;
-					   result1 = api_unhook_face( this_FACE, new_BODY_ptr );
-					   if( !result1.ok() )
-					   {
-						   AcisModifyEngine::instance()->get_acis_query_engine()->ACIS_API_error( result1 );
-						   PRINT_ERROR( " Face unhooking during rebuild of volume didn't work\n" );
-						   return CUBIT_FAILURE;
-					   }
-					   AcisQueryEngine::instance()->delete_ACIS_BODY (new_BODY_ptr);
-				  }
-			  }
-		  }
+          // loop through all faces
+          for( int i = 0; i< FACE_list.size(); i++)
+          {
+            this_FACE = FACE_list.get_and_step();
+            assert( this_FACE != NULL );
+            // Make sure this is a DOUBLE_SIDED FACE
+            if (this_FACE->sides() == DOUBLE_SIDED)
+            {
+              if (this_FACE->cont()==BOTH_INSIDE)
+              {
+                // found internal faces
+                // Now we have the FACE - unhook it  from the BODY.  Keep track of new
+                // BODIES that are created as this is done.
+                 PRINT_INFO( " Unhooking and deleting each internal surface...\n" );
+                 BODY *new_BODY_ptr;
+                 result1 = api_unhook_face( this_FACE, new_BODY_ptr );
+                 if( !result1.ok() )
+                 {
+                   AcisModifyEngine::instance()->get_acis_query_engine()->ACIS_API_error( result1 );
+                                                 PRINT_ERROR( " Face unhooking during rebuild of volume didn't work\n" );
+                                             return CUBIT_FAILURE;
+                 }
+	        AcisQueryEngine::instance()->delete_ACIS_BODY (new_BODY_ptr);
+	      }
+            }
+          }
 
-		 // heal the leftover body
+          // heal the leftover body
 //
-//		   PRINT_INFO(" Healing the leftover volume...\n");
-//		   if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
-//		   {
-//			   int percent_before, percent_after, number_splines_simplified;
-//			   if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
-//				   percent_after, number_splines_simplified ) == CUBIT_FAILURE )
-//				   PRINT_ERROR( "Error healing the combined volume\n" );
-//			   else
-//				   PRINT_INFO( "Successfully healed the combined volume.\n" );
-//			   AcisHealerTool::instance()->end_BODY_for_healing( master );
-//		   }
+//        PRINT_INFO(" Healing the leftover volume...\n");
+//	  if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
+//	  {
+//	    int percent_before, percent_after, number_splines_simplified;
+//	    if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
+//	        percent_after, number_splines_simplified ) == CUBIT_FAILURE )
+//	        PRINT_ERROR( "Error healing the combined volume\n" );
+//          else
+//            PRINT_INFO( "Successfully healed the combined volume.\n" );
+//          AcisHealerTool::instance()->end_BODY_for_healing( master );
+//        }
 	}
 
            // done with this j iteration; write out count, if necessary
@@ -6534,20 +7398,20 @@
   from_BODY_list.reset();
   from_bodies.reset();
 
-  for (ii = 0; ii< from_BODY_list_copy.size(); ii++)
+  for(ii = 0; ii< from_BODY_list_copy.size(); ii++)
   {
-      BODY *old_BODY = from_BODY_list.get();
-      BODY *new_BODY = from_BODY_list_copy.get();
+    BODY *old_BODY = from_BODY_list.get();
+    BODY *new_BODY = from_BODY_list_copy.get();
 
-      BodySM *new_body = NULL;
-      if (old_BODY != new_BODY)
-         new_body = get_new_Body(from_bodies.get(), old_BODY, new_BODY, keep_old);
+    BodySM *new_body = NULL;
+    if(old_BODY != new_BODY)
+      new_body = get_new_Body(from_bodies.get(), old_BODY, new_BODY, keep_old);
 
-      if (new_body)
-      {
-        new_from_bodies.append(new_body);
-        from_bodies.change_to(NULL);
-      }
+    if (new_body)
+    {
+      new_from_bodies.append(new_body);
+      from_bodies.change_to(NULL);
+    }
 
       // now step all the lists
     from_BODY_list.step();
@@ -6559,6 +7423,9 @@
   from_bodies.reset();
   new_from_bodies.reset();
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( new_from_bodies, history_object ); 
+
   for(ii = tool_BODY_list_copy.size(); ii>0; ii--)
      AcisQueryEngine::instance()->delete_ACIS_BODY(tool_BODY_list_copy.get_and_step(), CUBIT_TRUE);
 
@@ -7384,6 +8251,14 @@
   if (from_BODY_list.is_in_list(NULL))
     return CUBIT_FAILURE;
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( from_body_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
   // set the free_edges acis option
   if ( GeometryModifyTool::get_all_edges_imprint() )
   {
@@ -7567,12 +8442,14 @@
     }
   }
 
-
   PRINT_INFO("Group imprint finished.\n");
 
   // reset the free_edges acis option
   api_set_int_option("all_free_edges", FALSE );
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( new_from_body_list, history_object ); 
+
   return success;
 }
 
@@ -7604,7 +8481,8 @@
     SPAtransf t= get_owner_transf(EDGE_in_ptr);
     in_crv = EDGE_in_ptr->geometry()->trans_curve(t);
   }
-
+  
+  API_BEGIN
   if(in_crv && in_srf)
   {
     // create the curve
@@ -7648,6 +8526,7 @@
     // make the edge
     new_EDGE= ACIS_NEW EDGE(svert,evert,the_curve,FORWARD,EDGE_cvty_unknown,in_range);
   }
+  API_END
 
   if(in_crv)
     ACIS_DELETE in_crv;
@@ -7741,8 +8620,22 @@
 
   project_edges(ref_face_list, ref_edge_list_in, ref_edge_list_new);
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> bridges;
+    for( int i=ref_face_list.size(); i--; )
+      bridges.append( ref_face_list.get_and_step()->bodysm() );
+    bridges.uniquify_unordered();
+    AcisModifyEngine::instance()->start_tracking_history( bridges, history_object ); 
+  }
+
   // imprint Surface with curves
-  status = imprint(ref_face_list, ref_edge_list_new, new_body_list, keep_old_body );
+  DLIList<TopologyBridge*> temporary_bridges;
+  status = imprint(ref_face_list, ref_edge_list_new, temporary_bridges, new_body_list, keep_old_body );
+  temporary_bridges.uniquify_ordered();
+  while(temporary_bridges.size())
+    delete temporary_bridges.pop();
 
   if (keep_free_edges)
     return  status;
@@ -7762,6 +8655,15 @@
         "due to\n       this unsuccessful deletion.\n" );
     }
   }
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( CUBIT_FAILURE == status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+    else
+      history_object.remove_attributes();
+  }
+
   return status;
 }
 
@@ -7789,8 +8691,22 @@
 
   project_edges(ref_face_list, ref_edge_list_in, ref_edge_list_new);
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> bridges;
+    for( int i=ref_face_list.size(); i--; )
+      bridges.append( ref_face_list.get_and_step()->bodysm() );
+    bridges.uniquify_unordered();
+    AcisModifyEngine::instance()->start_tracking_history( bridges, history_object ); 
+  }
+
   // imprint bodies with curves
-  status = imprint(body_list,ref_edge_list_new,new_body_list, keep_old_body );
+  DLIList<TopologyBridge*> temporary_bridges;
+  status = imprint(body_list,ref_edge_list_new,new_body_list, temporary_bridges, keep_old_body );
+  temporary_bridges.uniquify_ordered();
+  while(temporary_bridges.size())
+    delete temporary_bridges.pop();
 
   if (keep_free_edges)
     return  status;
@@ -7810,6 +8726,15 @@
         "due to\n       this unsuccessful deletion.\n" );
     }
   }
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( CUBIT_FAILURE == status )
+      AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+    else
+      history_object.remove_attributes();
+  }
+
   return status;
 }
 
@@ -7833,7 +8758,6 @@
   bool delete_attribs =
       (GeometryModifyTool::instance()->get_new_ids() || keep_old);
 
-
   int ii;
   CubitBox tool_box = AcisQueryEngine::instance()->bounding_box(tool_body);
 
@@ -7843,7 +8767,16 @@
   // get acis bodies, and copy them
   from_bodies.reset();
 
-  for (ii = from_bodies.size(); ii > 0; ii--) {
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( from_bodies, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  for (ii = from_bodies.size(); ii > 0; ii--) 
+  {
     BODY *BODYPtr1 = AcisQueryEngine::get_BODY(from_bodies.get_and_step());
     from_BODY_list.append(BODYPtr1);
     BODYPtr1 = this->copy_BODY(BODYPtr1, delete_attribs);
@@ -7858,9 +8791,7 @@
   CubitBoolean boolean_regularize = GeometryModifyTool::instance()->boolean_regularize();
 
   if (boolean_regularize == FALSE)
-  {
     bool_type = NONREG_INTERSECTION;
-  }
 
   // now, intersect the tool with the list of bodies
   from_BODY_list.reset();
@@ -7870,7 +8801,8 @@
   CubitStatus int_stat = CUBIT_SUCCESS;
 
     // intersect the tool body with each body in the list
-  for (ii = 1; ii <= from_BODY_list.size(); ii++) {
+  for (ii = 1; ii <= from_BODY_list.size(); ii++) 
+  {
     BODY *from_BODY = from_BODY_list.get();
     BODY *from_BODY_copy = from_BODY_list_copy.get();
     BodySM *from_Body = from_bodies.get();
@@ -7878,21 +8810,19 @@
 
       // first, check bounding SPAbox; if they don't intersect, don't do the intersection
 
-    if (from_Body == tool_body) {
+    if (from_Body == tool_body) 
       PRINT_ERROR("Can't intersect volume with itself.\n");
-    }
 
-    else if (tool_box.overlap(SPAresabs, box1)) {
-
-        // the bodies overlap; proceed with the intersect
+    else if (tool_box.overlap(SPAresabs, box1)) 
+    {
+       // the bodies overlap; proceed with the intersect
       BODY* tool_BODY = AcisQueryEngine::get_BODY(tool_body);
       BODY *tool_BODY_copy = this->copy_BODY(tool_BODY);
 
+       // Intersect body1 with body2.
+       //outcome result = api_intersect( tool_BODY_copy, from_BODY_copy );
+      outcome result = api_boolean(tool_BODY_copy, from_BODY_copy, bool_type );
 
-        // Intersect body1 with body2.
-        //outcome result = api_intersect( tool_BODY_copy, from_BODY_copy );
-       outcome result = api_boolean(tool_BODY_copy, from_BODY_copy, bool_type );
-
         // We may or may not get an error if the resulting BODY is
         // empty
         // Also check the result.
@@ -7908,17 +8838,14 @@
 
           //I might need to take this out.  Not sure. CDE 10/17/2003
           if (tool_BODY_copy != NULL)
-          {
             AcisQueryEngine::instance()->delete_ACIS_BODY(tool_BODY_copy, CUBIT_TRUE);
-          }
         }
         else
           PRINT_ERROR("Intersection operation failed.\n"
                       "       Empty volume created and will be deleted.\n");
+
         if (from_BODY_copy != NULL)
-        {
           AcisQueryEngine::instance()->delete_ACIS_BODY(from_BODY_copy, CUBIT_TRUE);
-        }
 
           // we had an error, so put the original body into the copy list
         from_BODY_list_copy.change_to(from_BODY);
@@ -7926,52 +8853,52 @@
 
       if ( bool_type == NONREG_INTERSECTION)
       {
-		    outcome result1;
-		    // ENTITY_LIST FACES;
-            DLIList<FACE*>  FACE_list ;
-		    FACE *this_FACE;
-            AcisQueryEngine::instance()->get_FACEs(from_BODY_copy,FACE_list);
-		     // loop through all faces
-		    for( int i = 0; i< FACE_list.size(); i++)
-		    {
-			    this_FACE = FACE_list.get_and_step();
-			    assert( this_FACE != NULL );
-			    // Make sure this is a DOUBLE_SIDED FACE
-			    if (this_FACE->sides() == DOUBLE_SIDED)
-			    {
-				    if (this_FACE->cont()==BOTH_INSIDE)
-				    {
-					    // found internal faces
-					    // Now we have the FACE - unhook it  from the BODY.  Keep track of new
-					    // BODIES that are created as this is done.
-					     PRINT_INFO( " Unhooking and deleting each internal surface...\n" );
-					     BODY *new_BODY_ptr;
-					     result1 = api_unhook_face( this_FACE, new_BODY_ptr );
-					     if( !result1.ok() )
-					     {
-						     AcisModifyEngine::instance()->get_acis_query_engine()->ACIS_API_error( result1 );
-						     PRINT_ERROR( " Face unhooking during rebuild of volume didn't work\n" );
-						     return CUBIT_FAILURE;
-					     }
-					     AcisQueryEngine::instance()->delete_ACIS_BODY (new_BODY_ptr);
-				    }
-			    }
-		    }
+	outcome result1;
+        // ENTITY_LIST FACES;
+        DLIList<FACE*>  FACE_list ;
+        FACE *this_FACE;
+        AcisQueryEngine::instance()->get_FACEs(from_BODY_copy,FACE_list);
+        // loop through all faces
+        for( int i = 0; i< FACE_list.size(); i++)
+	{
+	  this_FACE = FACE_list.get_and_step();
+	  assert( this_FACE != NULL );
+	  // Make sure this is a DOUBLE_SIDED FACE
+          if (this_FACE->sides() == DOUBLE_SIDED)
+          {
+            if (this_FACE->cont()==BOTH_INSIDE)
+            {
+              // found internal faces
+              // Now we have the FACE - unhook it  from the BODY.  Keep track of new
+              // BODIES that are created as this is done.
+              PRINT_INFO( " Unhooking and deleting each internal surface...\n" );
+              BODY *new_BODY_ptr;
+              result1 = api_unhook_face( this_FACE, new_BODY_ptr );
+              if( !result1.ok() )
+              {
+                AcisModifyEngine::instance()->get_acis_query_engine()->ACIS_API_error( result1 );
+                PRINT_ERROR( " Face unhooking during rebuild of volume didn't work\n" );
+                return CUBIT_FAILURE;
+              }
+              AcisQueryEngine::instance()->delete_ACIS_BODY (new_BODY_ptr);
+            }
+          }
+        }
 
-		 // heal the leftover body
+        // heal the leftover body
 //
-//		   PRINT_INFO(" Healing the leftover volume...\n");
-//		   if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
-//		   {
-//			   int percent_before, percent_after, number_splines_simplified;
-//			   if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
-//				   percent_after, number_splines_simplified ) == CUBIT_FAILURE )
-//				   PRINT_ERROR( "Error healing the combined volume\n" );
-//			   else
-//				   PRINT_INFO( "Successfully healed the combined volume.\n" );
-//			   AcisHealerTool::instance()->end_BODY_for_healing( master );
-//		   }
-	    }
+//	PRINT_INFO(" Healing the leftover volume...\n");
+//	if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
+//	{
+//	  int percent_before, percent_after, number_splines_simplified;
+//	  if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
+//	      percent_after, number_splines_simplified ) == CUBIT_FAILURE )
+//	     PRINT_ERROR( "Error healing the combined volume\n" );
+//	  else
+//	    PRINT_INFO( "Successfully healed the combined volume.\n" );
+//	  AcisHealerTool::instance()->end_BODY_for_healing( master );
+//	}
+      }
 
       // done with this j iteration; write out count, if necessary
 //      if (from_bodies.size() > 1) {
@@ -7983,7 +8910,8 @@
 //      }
     }
 
-    else {
+    else 
+    {
       AcisQueryEngine::instance()->delete_ACIS_BODY(from_BODY_copy, CUBIT_TRUE);
       from_BODY_list_copy.change_to(from_BODY);
     }
@@ -8001,21 +8929,23 @@
   from_BODY_list.reset();
   from_bodies.reset();
 
-  for (ii = from_BODY_list_copy.size(); ii > 0; ii--) {
-
+  for (ii = from_BODY_list_copy.size(); ii > 0; ii--) 
+  {
     BODY *old_BODY = from_BODY_list.get();
     BODY *new_BODY = from_BODY_list_copy.get();
 
     BodySM *new_body = NULL;
     if (old_BODY != new_BODY)
       new_body = get_new_Body(from_bodies.get(), old_BODY, new_BODY, keep_old);
-    else if (!keep_old && int_stat == CUBIT_SUCCESS) {
+    else if (!keep_old && int_stat == CUBIT_SUCCESS) 
+    {
       //GeometryQueryTool::instance()->delete_Body(from_bodies.get());
       AcisQueryEngine::instance()->delete_solid_model_entities(from_bodies.get());
       from_bodies.change_to(NULL);
     }
 
-    if (new_body) {
+    if (new_body) 
+    {
       new_from_bodies.append(new_body);
       from_bodies.change_to(NULL);
     }
@@ -8030,6 +8960,9 @@
   from_bodies.reset();
   new_from_bodies.reset();
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( new_from_bodies, history_object ); 
+
   if (int_stat == CUBIT_SUCCESS && !keep_old )
     //GeometryQueryTool::instance()->delete_Body(tool_body);
     AcisQueryEngine::instance()->delete_solid_model_entities(tool_body);
@@ -9621,6 +10554,237 @@
    return sweep_status;
 }
 
+//-------------------------------------------------------------------------
+// Purpose       : Perform a face sweep operation to a target body
+//
+// Special Notes : 
+//
+// Creator       : Derek Quam
+//
+// Creation Date : 12/01/08
+//-------------------------------------------------------------------------
+CubitStatus AcisModifyEngine::sweep_to_body(Surface *source_surface,
+                                            BodySM *target_body,
+                                            CubitVector distance,
+                                            DLIList<BodySM*> &new_bodies) const
+{
+  // Declare local variables
+  BodyACIS *target_acis;
+  sweep_options *opts = new sweep_options();
+  outcome result;
+  BODY *new_body;
+
+  // Make sure we have an ACIS body
+  target_acis = dynamic_cast<BodyACIS*>(target_body);
+  if (!target_acis)
+  {
+    PRINT_ERROR("Target must be an Acis body!\n");
+    return CUBIT_FAILURE;
+  }
+
+  // Set the sweep vector
+  SPAvector vec(distance.x(), distance.y(), distance.z());
+
+  // Copy the ACIS BODY because it will be deleted at the sweep
+  BODY *target = AcisModifyEngine::instance()->copy_BODY(target_acis->get_BODY_ptr());
+
+  // Set the target and whether solids will be created
+  opts->set_sweep_to_body(target);
+
+  SurfaceACIS *temp = dynamic_cast<SurfaceACIS*>(source_surface);
+
+  // Make sure the curves are ACIS curves
+  if (!temp)
+  {
+    PRINT_ERROR("Profile must be an Acis surface!\n");
+    return CUBIT_FAILURE;
+  }
+
+  // Copy the original face
+  ENTITY *copy;
+  result = api_down_copy_entity((ENTITY*)temp->get_FACE_ptr(), copy);
+  if (!result.ok())
+  {
+    PRINT_ERROR("Failed to copy FACE.\n");
+    AcisQueryEngine::instance()->ACIS_API_error(result);
+    return CUBIT_FAILURE;
+  }
+
+  // Perform the sweep
+  PRINT_INFO("Sweeping surface %d\n", temp->get_saved_id());
+  result = api_sweep_with_options(copy, vec, opts, new_body);
+  if (!result.ok())
+  {
+    PRINT_ERROR("Surface failed to sweep!\n");
+    AcisQueryEngine::instance()->ACIS_API_error(result);
+    return CUBIT_FAILURE;
+  }
+
+  copy = new_body->lump()->shell()->first_face();
+
+  // Add the new BodySM to the return list
+  new_bodies.append(AcisQueryEngine::instance()->populate_topology_bridges(new_body));
+
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Perform a curve sweep operation to a target body
+//
+// Special Notes : As of right now (12/01/08), this will result in sheet
+//                 bodies.  You also cannot sweep to a solid body.  This
+//                 method attempts to create a WIRE out of the given EDGEs
+//                 and sweep that.  If that fails, it passes the paramters
+//                 to ??? to try and perform the sweep.
+//
+// Creator       : Derek Quam
+//
+// Creation Date : 11/21/08
+//-------------------------------------------------------------------------
+CubitStatus AcisModifyEngine::sweep_to_body(DLIList<Curve*> curve_list,
+                                            BodySM *target_body,
+                                            CubitVector distance,
+                                            DLIList<BodySM*> &new_bodies,
+                                            bool unite) const
+{
+  // Declare local variables
+  outcome result;
+  BodyACIS *target_acis;
+  BODY *new_body;
+  sweep_options *opts = new sweep_options();
+  DLIList<BODY*> unite_bodies;
+
+  // Make sure we have an ACIS body
+  target_acis = dynamic_cast<BodyACIS*>(target_body);
+  if (!target_acis)
+  {
+    PRINT_ERROR("Target must be an Acis body!\n");
+    return CUBIT_FAILURE;
+  }
+
+  // Set the sweep vector
+  SPAvector vec(distance.x(), distance.y(), distance.z());
+
+  for (int i = 0; i < curve_list.size(); i++)
+  {
+    // Copy the ACIS BODY because it will be deleted at the sweep
+    BODY *target = AcisModifyEngine::instance()->copy_BODY(target_acis->get_BODY_ptr());
+
+    // Set the target and whether sheets will be created
+    opts->set_sweep_to_body(target);
+    if (target_acis->is_sheet_body())
+    {
+      opts->set_two_sided(TRUE);
+      opts->set_solid(FALSE);
+    }
+
+    // Copy the edge
+    EDGE *copy;
+    Curve *cur = curve_list.get_and_step();
+    result = api_edge(((CurveACIS*)cur)->get_EDGE_ptr(), copy);
+    if (!result.ok())
+    {
+      PRINT_ERROR("ACIS EDGE failed to copy.\n");
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
+    }
+
+    // Perform the sweep
+    result = api_sweep_with_options((ENTITY*)copy, vec, opts, new_body);
+    if (!result.ok())
+    {
+      PRINT_ERROR("Curve %d failed to sweep!\n", cur->get_saved_id());
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
+    }
+
+    // Add the new BodySM to the return list or unite list
+    if (new_body)
+    {
+      if (unite)
+        unite_bodies.append(new_body);
+      else    
+        new_bodies.append(AcisQueryEngine::instance()->populate_topology_bridges(new_body));
+    }
+  }
+  for (int i = 1; i < unite_bodies.size(); i++)
+  {
+    result = api_unite(unite_bodies[i], unite_bodies[0]);
+    if (!result.ok())
+    {
+      PRINT_ERROR("Failed to unite swept bodies. Try sweeping with the unite flag off.\n");
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
+    }
+  }
+  if (unite_bodies.size() > 0)
+    new_bodies.append(AcisQueryEngine::instance()->populate_topology_bridges(unite_bodies[0]));
+  return CUBIT_SUCCESS;
+/*
+  if (curve_list.size() > 1)
+  {
+    // Declare the EDGE array
+    const int num_edges = curve_list.size();
+    EDGE **edges = ACIS_NEW EDGE*[num_edges];
+
+    // Fill the EDGE array
+    for (int i = 0; i < num_edges; i++)
+    {
+      // Copy the edge
+      EDGE *copy;
+      result = api_edge(((CurveACIS*)curve_list.get_and_step())->get_EDGE_ptr(), copy);
+
+      // Check the copy operation
+      if (!result.ok())
+      {
+        PRINT_ERROR("ACIS EDGE failed to copy.\n");
+        AcisQueryEngine::instance()->ACIS_API_error(result);
+        return CUBIT_FAILURE;
+      }
+      edges[i] = copy;
+    }
+
+    // Create the WIRE
+    result = api_make_ewires(num_edges, edges, n_bodies, wire_body);
+
+    if (!result.ok())
+    {
+      PRINT_ERROR("Failed to build WIRE!  Try sweeping one curve at a time.\n");
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
+    }
+
+    PRINT_INFO("%d WIRE(s) created.\n", n_bodies);
+
+    // Copy the ACIS BODY because it will be deleted at the sweep
+    BODY *target = AcisModifyEngine::instance()->copy_BODY(target_acis->get_BODY_ptr());
+
+    // Set the target and whether sheets will be created
+    opts->set_sweep_to_body(target);
+    if (target_acis->is_sheet_body())
+    {
+      opts->set_two_sided(TRUE);
+      opts->set_solid(FALSE);
+    }
+
+    // Perform the sweep
+    result = api_sweep_with_options((ENTITY*)wire_body[0], vec, opts, new_body);
+    if (!result.ok())
+    {
+      PRINT_ERROR("Curve failed to sweep!\n");
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
+    }
+
+    // Add the new BodySM to the return list
+    if (new_body)
+      new_bodies.append(AcisQueryEngine::instance()->populate_topology_bridges(new_body));
+    else
+      new_bodies.append(AcisQueryEngine::instance()->populate_topology_bridges(wire_body[0]));
+  }
+*/
+}
+
   //-------------------------------------------------------------------------
   // Purpose       : Sections the list of bodies (cuts in half).  This is
   //                 when trying to see a cross section of the model.
@@ -9672,6 +10836,14 @@
       return CUBIT_FAILURE;
    }
 
+   AcisHistory history_object;
+   if( GeometryQueryTool::instance()->history().is_tracking() )
+   {
+     DLIList<TopologyBridge*> my_bridges;
+     CAST_LIST( section_body_list, my_bridges, TopologyBridge );
+     AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+   }
+
     // Copy BODYs
   i = section_body_list.size();
   DLIList<BODY*>  tool_BODY_list(i);
@@ -9767,8 +10939,6 @@
         if( body_acis )
         {
           BodySM *body_sm = CAST_TO(body_acis, BodySM );
-          TopologyEntity *topo_entity = body_sm->topology_entity();
-          RefEntity *ref_entity = CAST_TO(topo_entity, RefEntity);
           section_body_list.remove( body_sm );
         }
       }
@@ -9843,6 +11013,9 @@
                   new_body_list,
                   keep_old );
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+
   return CUBIT_SUCCESS;
 }
 
@@ -9862,8 +11035,10 @@
                                       const CubitVector &vecVertex1,
                                       const CubitVector &vecVertex2,
                                       const CubitVector &vecVertex3,
+                                      DLIList<BodySM*>& neighbor_imprint_list,
                                       DLIList<BodySM*>& results_list,
-                                      bool imprint ) const
+                                      ImprintType imprint_type,
+                                      bool preview) const
 {
    //int webcut_debug_flag = 18;
    //int webcut_debug_flag_on = DEBUG_FLAG(webcut_debug_flag);
@@ -9902,13 +11077,30 @@
 
    else
    {
+      AcisHistory history_object;
+
+      if( GeometryQueryTool::instance()->history().is_tracking() )
+      {
+        DLIList<TopologyBridge*> my_bridges;
+        CAST_LIST( webcut_body_list, my_bridges, TopologyBridge );
+        AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+      }
+
         // Use the BODY to perform webcut
       CubitStatus stat =
-          this->webcut(webcut_body_list, cutting_tool_ptr, results_list, imprint) ;
+          this->webcut(webcut_body_list, cutting_tool_ptr, 
+                       neighbor_imprint_list,
+                       results_list, imprint_type, preview) ;
 
         // Delete the BODY that was created to be used as a tool
       AcisQueryEngine::instance()->delete_ACIS_BODY(cutting_tool_ptr, CUBIT_TRUE) ;
       cutting_tool_ptr = NULL;
+       
+      if( GeometryQueryTool::instance()->history().is_tracking() )
+      {
+        if( stat )
+          AcisModifyEngine::instance()->stop_tracking_history( results_list, history_object ); 
+      }
 
       return stat ;
    }
@@ -9927,8 +11119,10 @@
 //-------------------------------------------------------------------------
 CubitStatus AcisModifyEngine::webcut( DLIList<BodySM*>& webcut_body_list,
                                       BodySM const* tool_body,
+                                      DLIList<BodySM*>& neighbor_imprint_list,
                                       DLIList<BodySM*>& results_list,
-                                      bool imprint ) const
+                                      ImprintType imprint_type,
+                                      bool preview) const
 {
      // check the tool body if it is made of AcisModifyEngine
    if( !is_modify_engine(tool_body))
@@ -9950,51 +11144,81 @@
       return CUBIT_FAILURE;
    }
 
-   return this->webcut( webcut_body_list, tool_BODY, results_list, imprint );
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( webcut_body_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
+  CubitStatus status = this->webcut( webcut_body_list, tool_BODY, 
+                        neighbor_imprint_list,
+                        results_list, imprint_type, preview );
+
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    if( CUBIT_SUCCESS == status ) 
+      AcisModifyEngine::instance()->stop_tracking_history( results_list, history_object ); 
+  }
+
+  return status;
 }
 
-  //-------------------------------------------------------------------------
-  // Purpose       : webcuts a list of bodies using another Body as the tool.
-  //                 The newly created bodies are merged and imprinted
-  //                 depending on the respective flags.
-  // Special Notes :
-  //
-  // Creator       : Jihong Ma
-  //
-  // Creation Date : 12/17/96
-  //-------------------------------------------------------------------------
-  CubitStatus AcisModifyEngine::webcut( 
-				       DLIList<BodySM*>& webcut_body_list,
-				       BODY* tool_BODY,
-				       DLIList<BodySM*>& results_list,
-				       bool imprint) const 
-    {
-      CubitBoolean delete_bodies = (GeometryModifyTool::instance()->get_new_ids() ?
-				    CUBIT_FALSE : CUBIT_TRUE);
+//-------------------------------------------------------------------------
+// Purpose       : webcuts a list of bodies using another Body as the tool.
+//                 The newly created bodies are merged and imprinted
+//                 depending on the respective flags.
+// Special Notes :
+//
+// Creator       : Jihong Ma
+//
+// Creation Date : 12/17/96
+//-------------------------------------------------------------------------
+CubitStatus AcisModifyEngine::webcut( DLIList<BodySM*>& webcut_body_list,
+                                      BODY* tool_BODY,
+                                      DLIList<BodySM*>& neighbor_imprint_list,
+                                      DLIList<BodySM*>& results_list,
+                                      ImprintType imprint_type,
+                                      bool preview) const
+{
 
-      // Number of bodies that were webcut
-      int count = 0 ;
+  // preview the tool
+  if (preview)
+  {
+    GfxPreview::clear();
+    AcisDrawTool::instance()->draw_ENTITY( tool_BODY, CUBIT_BLUE, CUBIT_TRUE, CUBIT_FALSE );
+    GfxPreview::flush();
 
+    return CUBIT_SUCCESS;
+  }
+
+  CubitBoolean delete_bodies = (GeometryModifyTool::instance()->get_new_ids() ?
+                                CUBIT_FALSE : CUBIT_TRUE);
+
+    // Number of bodies that were webcut
+   int count = 0 ;
+
       bool cutting_with_sheet = BodyACIS::is_sheet_body(tool_BODY);
       BodySM* Body_to_be_webcut = NULL;
       BODY* BODY_to_be_webcut = NULL;
 
-      // List to maintain thew newly created BODYs
-      DLIList<BODY*> new_webcut_BODY_list;
+     // List to maintain thew newly created BODYs
+   DLIList<BODY*> new_webcut_BODY_list;
 
-      // List of old bodies that did get webcut
-      DLIList<BodySM*> old_body_list;
-      DLIList<BODY*> old_BODY_list;
+     // List of old bodies that did get webcut
+   DLIList<BodySM*> old_body_list;
+   DLIList<BODY*> old_BODY_list;
 
-      // Variables to get the results of webcut from another routine.
-      BODY* BODY_result1 = NULL;
-      BODY* BODY_result2 = NULL;
+     // Variables to get the results of webcut from another routine.
+   BODY* BODY_result1 = NULL;
+   BODY* BODY_result2 = NULL;
 
-      // For each Body in the input list, make sure that it is associated
-      // with AGE before the webcutting is done.
-      CubitStatus status = CUBIT_FAILURE;
-      webcut_body_list.reset() ;
-      int i;
+     // For each Body in the input list, make sure that it is associated
+     // with AGE before the webcutting is done.
+   CubitStatus status = CUBIT_FAILURE;
+   webcut_body_list.reset() ;
+   int i;
 
       // step 1: bodies taken from webcut_body_list and webcut; if
       //    successful, the old Body and BODY are put on old_Body(BODY)_list
@@ -10054,123 +11278,24 @@
 	      results_list.append_unique( Body_to_be_webcut );
 	    }
 	}
+  
+   finish_webcut( NULL, old_body_list, old_BODY_list, 
+                  new_webcut_BODY_list, neighbor_imprint_list,
+                  imprint_type, results_list );
 
-      // A list to hold the newly created Bodies due to imprint operations
-      // on the remaining Bodys in the Model. The new Bodys replace the old
-      // Bodys if any of the new BODYs created by webcutting imprint
-      // on the old Bodys.
-      DLIList<BodySM*>  new_webcut_body_list;
+   // Return CUBIT_SUCCESS as long as one body is webcut, earlier failures should
+   // return CUBIT_FAILURE independently of these return statments
+   if (count>0)
+   {
+     return CUBIT_SUCCESS;
+   }
+   else
+   {
+     return CUBIT_FAILURE;
+   }
+}
 
-      DLIList<BODY*> just_webcut_list;
-      // A list to get the BODY's created that were webcut from the imprint
-      // operation.
 
-
-      // Perform the imprinting operations, if required. Note that this
-      // operation needs to be performed *after* the model has been cleared of
-      // Bodies that were already webcut. Also, note that it returns a list
-      // of all the new Bodies created during the imprint operation. This
-      // list is then enhanced by adding any new Bodies created due to the
-      // actual cutting of an old Body, before it is sent into the webcut_merge
-      // procedure. This is the list of Bodies that is "merged".
-      if (new_webcut_BODY_list.size() > 0)
-	{
-	  DLIList<BODY*> old_model_BODY_list;
-	  DLIList<BodySM*> old_model_Body_list;
-
-	  if ( imprint == CUBIT_TRUE )
-	    {
-	      // Work-in-progress message
-	      PRINT_INFO ("      Performing the imprint operations...\n");
-
-	      // Imprint away :)
-	      webcut_imprint(tool_BODY, old_body_list, new_webcut_BODY_list,
-			     just_webcut_list, results_list,
-			     old_model_Body_list, old_model_BODY_list) ;
-	    }
-	  if ( just_webcut_list.size() == 0 )
-	    just_webcut_list = new_webcut_BODY_list;
-
-	  // Work-in-progress message
-	  PRINT_INFO ("      Creating the new (webcut) volumes...\n");
-
-	  // Now create the new Bodies from the ACIS BODYs that were created
-	  // by webcutting the original BODYs using the Cutting Tool.
-	  BodySM* new_body_ptr = NULL;
-	  BODY* webcut_BODY_ptr = NULL;
-	  new_webcut_BODY_list.reset();
-	  old_body_list.reset();
-	  old_BODY_list.reset();
-	  old_model_Body_list.reset();
-	  old_model_BODY_list.reset();
-
-	  for ( i = 0 ; i < new_webcut_BODY_list.size(); i++ )
-	    {
-	      DLIList<BODY*> temp_BODY_list;
-	      DLIList<BodySM*> temp_body_list;
-	      BodySM *old_Body;
-	      BODY *old_BODY;
-
-	      webcut_BODY_ptr = new_webcut_BODY_list.get_and_step();
-	      temp_BODY_list.append(webcut_BODY_ptr);
-	      // in call to get_new_Body, don't delete old bodies if
-	      // they were successfully webcut (need to do it that way to
-	      // preserve name propagation as before); otherwise, delete the
-	      // imprinted bodies
-	      if (imprint == CUBIT_FALSE || just_webcut_list.move_to(webcut_BODY_ptr)) {
-		webcut_BODY_ptr = new_webcut_BODY_list.get_and_step();
-		temp_BODY_list.append(webcut_BODY_ptr);
-		i++;
-		old_Body = old_body_list.get_and_step();
-		old_BODY = old_BODY_list.get_and_step();
-		status = get_new_Body( old_Body, old_BODY, temp_BODY_list, temp_body_list,
-				       false, delete_bodies );
-	      }
-	      else {
-		old_Body = old_model_Body_list.get_and_step();
-		old_BODY = old_model_BODY_list.get_and_step();
-		BodySM* new_Body = get_new_Body( old_Body, old_BODY, webcut_BODY_ptr,
-						 false, true, true );
-		status = CUBIT_SUCCESS;
-		if (new_Body)
-		  temp_body_list.append(new_Body);
-	      }
-
-	      if (status == CUBIT_FAILURE) {
-		PRINT_ERROR("Failed to build new volume in AGE::webcut.\n");
-	      }
-
-	      // if we didn't get any new bodies back from get_new_Body,
-	      // that means that an imprinted body wasn't really imprinted
-	      if (temp_body_list.size() > 0) {
-		temp_BODY_list.reset();
-		temp_body_list.reset();
-		for (int j = 0; j < temp_BODY_list.size(); j++) {
-		  webcut_BODY_ptr = temp_BODY_list.get_and_step();
-		  new_body_ptr = temp_body_list.get_and_step();
-
-		  new_webcut_body_list.append(new_body_ptr);
-		  results_list.append_unique(new_body_ptr);
-		}
-	      }
-	      else
-		new_webcut_body_list.append(old_Body);
-
-	    }
-	}
-      // Return CUBIT_SUCCESS as long as one body is webcut, earlier failures should
-      // return CUBIT_FAILURE independently of these return statments
-      if (count>0)
-	{
-	  return CUBIT_SUCCESS;
-	}
-      else
-	{
-	  return CUBIT_FAILURE;
-	}
-    }
-
-
 //-------------------------------------------------------------------------
 // Purpose       : This function creates a Point, given coordinates.  The
 //                 particular type of Point object that is created depends on
@@ -10216,6 +11341,18 @@
                  "Possible incompatible geometry engines.\n");
      return (Curve *)NULL;
   }
+
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() ) 
+  {
+    history_object.highLevelCopying = true;
+    DLIList<TopologyBridge*> my_bridges(1);
+    TopologyBridge *tb = CAST_TO( curve_ptr, TopologyBridge );
+    my_bridges.append( tb );
+    bool ignore_parents = true;
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object, ignore_parents ); 
+  }
+
   EDGE_ptr = curve_ACIS->get_EDGE_ptr();
 
   outcome result = api_edge( EDGE_ptr, new_EDGE_ptr );
@@ -10229,7 +11366,16 @@
 
     // Create a new CurveACIS object
     // Use the new EDGE to create a new CurveACIS
-  return AcisQueryEngine::instance()->populate_topology_bridges(new_EDGE_ptr);
+  Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges(new_EDGE_ptr);
+
+  if( GeometryQueryTool::instance()->history().is_tracking() ) 
+  {
+    DLIList<TopologyBridge*> new_curves(1);
+    new_curves.append( new_curve );
+    AcisModifyEngine::instance()->stop_tracking_history( new_curves, history_object ); 
+  }
+
+  return new_curve;
 }
 
 //-------------------------------------------------------------------------
@@ -10306,6 +11452,91 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : This function creates a spline with the given vectors 
+//                 in point_list.  point_tangents can be used to specify
+//                 curvature of the spline.
+//
+// Special Notes : size of point list and tangents must be the same. 
+//                 values in the tangent list may be null.
+//
+// Creator       : 
+//
+// Creation Date : 04/14/2009
+//-------------------------------------------------------------------------
+Curve* AcisModifyEngine::make_Curve( DLIList<CubitVector*>& point_list,
+                   DLIList<CubitVector*>& point_tangents) const
+{
+    if (point_list.size() != point_tangents.size())
+    {
+        PRINT_ERROR("AcisModifyEngine::make_Curve\n"
+                    "    point list and tangent list must have same size\n");
+        return (Curve *)NULL;
+    }
+
+    DLIList<Curve*> new_curves;
+    
+
+    DLIList<CubitVector*> points;
+    CubitVector* point1_vector;
+    CubitVector* start_vector = NULL;
+    CubitVector* end_vector = NULL;
+    CubitVector* tangent_vector;
+    int i = 0;
+    for (i = 0; i < point_list.size(); i++)
+    {
+        point1_vector = point_list.get_and_step();
+        tangent_vector = point_tangents.get_and_step();
+
+        
+        points.append(point1_vector);
+        if (tangent_vector != NULL)
+        {
+            start_vector = end_vector;
+            end_vector = tangent_vector;
+
+            if (start_vector != NULL && end_vector != NULL)
+            {
+                EDGE* new_EDGE_ptr = NULL;
+                new_EDGE_ptr = instance()->make_spline_EDGE(points, start_vector, end_vector);
+                
+                if (new_EDGE_ptr == NULL)
+                {
+                    PRINT_ERROR("In AcisModifyEngine::make_Curve\n"
+                        "       Cannot make Curve object.\n");
+                    Curve* tmp_curve_ptr = NULL;
+                    CurveACIS* tmp_acis_curve = NULL;
+                    EDGE* tmp_EDGE_ptr = NULL;
+                    for (i = 0; i < new_curves.size(); i++)
+                    {
+                        tmp_curve_ptr = new_curves.get_and_step();
+                        tmp_acis_curve = CAST_TO(tmp_curve_ptr, CurveACIS);
+                        tmp_EDGE_ptr = tmp_acis_curve->get_EDGE_ptr();
+                        api_delent( tmp_EDGE_ptr );
+                    }
+                    return (Curve *)NULL;
+                }
+
+                Curve* curve_ptr = AcisQueryEngine::instance()->populate_topology_bridges(new_EDGE_ptr);
+                new_curves.append(curve_ptr);
+
+                // reset point array to keep track of the next 2 points
+                points.clean_out();
+                points.append(point1_vector);
+            }
+        }
+    }
+
+    // combine new EDGE* into single curve
+    Curve* new_curve_ptr = NULL;
+    CubitStatus result;
+    result = AcisEdgeTool::instance()->create_curve_combine(new_curves, new_curve_ptr);
+    if (result)
+        return new_curve_ptr;
+    else
+        return (Curve *)NULL;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : This function creates a Curve of type, curve_type,
 //                 given the end points of the curve and an intermediate
 //                 point.  The particular type of Curve object that is
@@ -10499,44 +11730,125 @@
                                            bool extended_from) const
 {
      //Get the surface ACIS.
-   SurfaceACIS *surf_ACIS = CAST_TO(old_surface_ptr, SurfaceACIS );
-   if (surf_ACIS == NULL)
-   {
-      PRINT_ERROR("surface is not created from acis.\n");
-      return (Surface*) NULL;
-   }
 
-     //Get the acis face.
-   FACE *FACE_ptr = surf_ACIS->get_FACE_ptr();
-
-     //use this to make a FACE.
-   if (FACE_ptr == NULL )
-   {
+  SurfaceACIS *surf_ACIS = CAST_TO(old_surface_ptr, SurfaceACIS );
+  if (surf_ACIS == NULL)
+  {
      PRINT_ERROR("surface is not created from acis.\n");
      return (Surface*) NULL;
-   }
-   FACE *new_FACE_ptr = NULL;
+  }
 
-   new_FACE_ptr = make_FACE( FACE_ptr, extended_from );
-   if (new_FACE_ptr == NULL)
-   {
-     PRINT_ERROR("In AcisModifyEngine::make_Surface\n"
-                 "       Cannot make Surface object.\n");
-     return (Surface *)NULL;
-   }
+    //Get the acis face.
+  FACE *FACE_ptr = surf_ACIS->get_FACE_ptr();
 
-   //populate the bridges from the body
-   BODY *body_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY(new_FACE_ptr);
-   BodySM *body_sm = AcisQueryEngine::instance()->populate_topology_bridges( body_ptr );
-   DLIList<Surface*> surfs;
-   body_sm->surfaces( surfs );
-   Surface *surface = surfs.get();
+    //use this to make a FACE.
+  if (FACE_ptr == NULL )
+  {
+    PRINT_ERROR("surface is not created from acis.\n");
+    return (Surface*) NULL;
+  }
+  FACE *new_FACE_ptr = NULL;
 
-   return surface;
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() && !extended_from ) 
+  {
+    history_object.highLevelCopying = true;
+    DLIList<TopologyBridge*> my_bridges(1);
+    TopologyBridge *tb = CAST_TO( old_surface_ptr, TopologyBridge );
+    my_bridges.append( tb );
+    bool ignore_parents = true;
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object, ignore_parents ); 
+  }
 
+  new_FACE_ptr = make_FACE( FACE_ptr, extended_from );
+  if (new_FACE_ptr == NULL)
+  {
+    PRINT_ERROR("In AcisModifyEngine::make_Surface\n"
+                "       Cannot make Surface object.\n");
+    return (Surface *)NULL;
+  }
+
+  //populate the bridges from the body
+  BODY *body_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY(new_FACE_ptr);
+  BodySM *body_sm = AcisQueryEngine::instance()->populate_topology_bridges( body_ptr );
+  DLIList<Surface*> surfs;
+  body_sm->surfaces( surfs );
+  Surface *surface = surfs.get();
+
+  if( GeometryQueryTool::instance()->history().is_tracking() && !extended_from ) 
+  {
+    DLIList<BodySM*> new_bodies(1);
+    new_bodies.append( body_sm );
+    AcisModifyEngine::instance()->stop_tracking_history( new_bodies, history_object ); 
+  }
+
+  return surface;
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : This function creates a sheet body by extending out a
+//                 set of surfaces.  The sheet body is a double sided face
+//                 with no volume.
+//
+// Special Notes :
+//
+// Creator       : Steve Storm
+//
+// Creation Date : 2/27/08
+//-------------------------------------------------------------------------
+
+BodySM* AcisModifyEngine::make_extended_sheet( DLIList<Surface*> &surface_list,
+                                               CubitBox *clip_box_ptr,
+                                               bool preview ) const
+{
+  // Get the FACE list
+  int i;
+  Surface *surf_ptr;
+  SurfaceACIS *surfACIS_ptr;
+  FACE *FACE_ptr;
+  DLIList<FACE*> FACE_list;
+  surface_list.reset() ;
+  for( i=surface_list.size(); i--; )
+  {
+    surf_ptr = surface_list.get_and_step() ;
+    surfACIS_ptr = CAST_TO(const_cast<Surface*>(surf_ptr), SurfaceACIS) ;
+
+    // Make sure that we don't get NULL pointers after the cast down.
+    if ( surfACIS_ptr == NULL )
+    {
+      PRINT_ERROR("In AcisModifyEngine::make_extended_sheet\n"
+        "       Got a NULL pointer to SurfaceACIS\n") ;
+      assert ( surfACIS_ptr != NULL ) ;
+    }
+
+    // Get the FACE
+    FACE_ptr = surfACIS_ptr->get_FACE_ptr() ;
+
+    // Add the FACE to the list of FACEs to be used to make a FACE
+    FACE_list.append(FACE_ptr);
+  }
+
+  // Do the work
+  BODY *ext_BODY_ptr = make_extended_sheet( FACE_list, clip_box_ptr );
+
+  if( !ext_BODY_ptr )
+    return 0;
+
+  if( preview )
+  {
+    GfxPreview::clear();
+    AcisDrawTool::instance()->draw_ENTITY( ext_BODY_ptr, CUBIT_BLUE, CUBIT_TRUE, 
+      CUBIT_TRUE );
+
+    api_delent( ext_BODY_ptr );
+    return 0;
+  }
+
+  // Return a BodySM
+  return AcisQueryEngine::instance()->populate_topology_bridges(ext_BODY_ptr);
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : This function creates a Surface of type,
 //                 surface_type, given the list of curves.
 //
@@ -10552,10 +11864,12 @@
                                            bool check_edges ) const
 {
   DLIList<RefEdge*> copied_ref_edges;
+  DLIList<Curve*> curve_copies;
   int i;
   if( check_edges )
   {
     DLIList<RefEdge*> edge_list;
+    curve_list.reset();
     for( i=curve_list.size(); i--; )
     {
       RefEdge *tmp_ref_edge = NULL;
@@ -10572,6 +11886,9 @@
     //also pick up the case where edges already belong to a face.
     DLIList<RefEdge*> vtx_edges;
     DLIList<RefVertex*> vtx_list;
+    DLIList<Curve*> curves_to_make_surface;
+    curve_list.reset();
+    edge_list.reset();
     for ( i = edge_list.size(); i > 0; i-- )
     {
       RefEdge *ref_edge = edge_list.get();
@@ -10595,28 +11912,22 @@
 
       if ( other_edge || (ref_edge->get_parents() > 0) )
       {
-        RefEdge *replacement_edge = GeometryModifyTool::instance()->make_RefEdge( ref_edge );
-        if (!replacement_edge)
-        {
-          PRINT_WARNING("Creation of Surface Unsuccessful\n");
-          return (Surface *)NULL;
-        }
-        edge_list.change_to( replacement_edge );
-        copied_ref_edges.append( replacement_edge );
+        Curve *new_curve = make_Curve( curve_list.get() );
+        curve_copies.append( new_curve );
+        curves_to_make_surface.append( new_curve );
       }
+      else
+      {
+        curves_to_make_surface.append( curve_list.get() );
+      }
+
       edge_list.step();
+      curve_list.step();
     }
 
     curve_list.clean_out();
-    for( i=edge_list.size(); i--; )
-    {
-      Curve *tmp_curve = NULL;
-      tmp_curve =
-      CAST_TO( edge_list.get_and_step()->bridge_manager()->topology_bridge(), Curve);
-      if( tmp_curve )
-        curve_list.append( tmp_curve );
-    }
-  }
+    curve_list += curves_to_make_surface;
+  } 
 
    DLIList<EDGE*> EDGE_list ;
      // List of EDGEs to use to create the FACE from which we can make
@@ -10626,10 +11937,8 @@
    Curve const* curve_ptr = NULL ;
    CurveACIS* curveACIS_ptr = NULL ;
    EDGE* EDGE_ptr = NULL ;
-
+ 
    curve_list.reset() ;
-
-
    for ( i = 0 ; i < curve_list.size() ; i++ )
    {
       curve_ptr = curve_list.get_and_step() ;
@@ -10647,8 +11956,9 @@
       EDGE_ptr = curveACIS_ptr->get_EDGE_ptr() ;
 
         // Add the EDGE to the list of EDGEs to be used to make a FACE
-      EDGE_list.append(EDGE_ptr) ;
+      EDGE_list.append(EDGE_ptr);
    }
+   
 
      // Use the EDGEs to make a FACE
    FACE* FACE_ptr = this->make_FACE(surface_type, EDGE_list,
@@ -10656,9 +11966,8 @@
 
    if (FACE_ptr == NULL)
    {
-     //delete all the copied ref edges...copied just for creating this surface
-     for(i=copied_ref_edges.size(); i--; )
-       GeometryQueryTool::instance()->delete_RefEdge( copied_ref_edges.get_and_step() );
+     for( i=curve_copies.size(); i--; )
+       AcisQueryEngine::instance()->delete_solid_model_entities( curve_copies.get_and_step() ); 
 
      PRINT_ERROR("In AcisModifyEngine::make_Surface\n"
                   "       Cannot make Surface object.\n");
@@ -10903,7 +12212,6 @@
    BODY *acis_BODY = this->copy_BODY(old_BODY, new_ids);
 
    outcome result = api_clean_entity( (ENTITY*) acis_BODY);
-   //outcome result = api_regularise_entity( (ENTITY*) acis_BODY);
    if (!result.ok() || acis_BODY == NULL ||
        acis_BODY->lump() == NULL )
    {
@@ -11030,7 +12338,7 @@
 		  AcisQueryEngine::instance()->ACIS_API_error (result);
 		  AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY_ptr, not_new_ids);
 		  return CUBIT_FAILURE;
-	  }
+    }
   }
 
   // clean VERTEX
@@ -11047,12 +12355,179 @@
 		  return CUBIT_FAILURE;
 	  }
   }
+
   //rebuild the cubit geometry
   new_body_ptr = get_new_Body( body_ptr,  BODY_ptr , copied_BODY_ptr , false);
   if (new_body_ptr) return CUBIT_SUCCESS;
 	   else return CUBIT_FAILURE;
 }
 
+CubitStatus AcisModifyEngine::test_regularize_entity( GeometryEntity *old_refentity_ptr)
+{
+  CubitBoolean new_ids = GeometryModifyTool::instance()->get_new_ids();
+  CubitBoolean not_new_ids = (new_ids ? CUBIT_FALSE : CUBIT_TRUE);
+
+  BODY *copied_BODY_ptr;
+  SurfaceACIS *ref_face = CAST_TO(old_refentity_ptr, SurfaceACIS);
+  CurveACIS *ref_edge= CAST_TO(old_refentity_ptr, CurveACIS);
+  PointACIS *ref_vertex= CAST_TO(old_refentity_ptr, PointACIS);
+
+  DLIList<SurfaceACIS*> reg_face_list;
+  DLIList<FACE*> FACE_list;
+
+  DLIList<CurveACIS*> reg_edge_list;
+  DLIList<EDGE*> EDGE_list;
+
+  DLIList<PointACIS*> reg_vertex_list;
+  DLIList<VERTEX*> VERTEX_list;
+
+  // get the copied_BODY_ptr and FACE_list to clean
+  if (ref_face)
+  {
+	  reg_face_list.append(ref_face);
+    if (get_copied_FACES_of_body( reg_face_list, FACE_list, copied_BODY_ptr )== CUBIT_FAILURE )
+	  {
+      return CUBIT_FAILURE;
+	  }
+  }
+
+// get the copied_BODY_ptr and EDGE_list to clean
+  if (ref_edge)
+  {
+	  reg_edge_list.append(ref_edge);
+    if(get_copied_EDGES_of_body( reg_edge_list, EDGE_list, copied_BODY_ptr )== CUBIT_FAILURE )
+	  {
+      return CUBIT_FAILURE;
+	  }
+  }
+
+ if (ref_vertex)
+  {
+	  reg_vertex_list.append(ref_vertex);
+    if (get_copied_VERTICES_of_body( reg_vertex_list, VERTEX_list, copied_BODY_ptr )== CUBIT_FAILURE )
+	  {
+      return CUBIT_FAILURE;
+	  }
+  }
+
+  if (!ref_face && !ref_edge && !ref_vertex)
+  {
+    AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY_ptr, not_new_ids);
+	  return CUBIT_FAILURE;
+  }
+
+  int i;
+  FACE *acis_FACE;
+  EDGE *acis_EDGE;
+  VERTEX *acis_VERTEX;
+
+ //clean FACE
+  for (i=0;i<FACE_list.size();i++)
+  {
+	  acis_FACE = FACE_list.get_and_step();
+	  outcome result = api_clean_entity( (ENTITY*) acis_FACE);
+	  if (!result.ok() || acis_FACE == NULL )
+	  {
+		 AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY_ptr, not_new_ids);
+		 return CUBIT_FAILURE;
+	  }
+  }
+
+  // clean EDGE
+  for (i=0;i<EDGE_list.size();i++)
+  {
+	  acis_EDGE = EDGE_list.get_and_step();
+    ENTITY_LIST verts, edges;
+    /*
+    int j, num_verts;
+    api_get_vertices(acis_EDGE, verts);
+    num_verts = verts.count();
+    int prev_num_edges = 0;
+    int new_num_edges = 0;
+    int expected_diff = 2;
+    if(num_verts == 1)
+      expected_diff = 1;
+    for(j=0; j<num_verts; j++)
+    {
+      edges.clear();
+      api_get_edges(verts[j], edges);
+      prev_num_edges += edges.count();
+    }
+    */
+    api_get_edges(copied_BODY_ptr, edges);
+    int prev_size = edges.count();
+	  outcome result = api_clean_entity( (ENTITY*) acis_EDGE);
+    edges.clear();
+    api_get_edges(copied_BODY_ptr, edges);
+    int new_size = edges.count();
+    /*
+    for(j=0; j<num_verts; j++)
+    {
+      edges.clear();
+      api_get_edges(verts[j], edges);
+      new_num_edges += edges.count();
+    }
+    */
+
+	  if (!result.ok() || acis_EDGE == NULL || prev_size == new_size )
+	  {
+		  AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY_ptr, not_new_ids);
+		  return CUBIT_FAILURE;
+    }
+  }
+
+  // clean VERTEX
+  for (i=0;i<VERTEX_list.size();i++)
+  {
+	  acis_VERTEX = VERTEX_list.get_and_step();
+	  outcome result = api_clean_entity( (ENTITY*) acis_VERTEX);
+	  if (!result.ok() || acis_VERTEX == NULL )
+	  {
+		  AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY_ptr, not_new_ids);
+		  return CUBIT_FAILURE;
+	  }
+  }
+
+	AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY_ptr, not_new_ids);
+  return CUBIT_SUCCESS;
+}
+
+
+CubitStatus AcisModifyEngine::split_free_curve( Curve *curve, 
+                                                CubitVector &split_location,
+                                                DLIList<Curve*> &new_curves )
+{
+  //get the acis curve
+  EDGE* EDGE_ptr = AcisQueryEngine::get_EDGE( curve );
+
+  //make a copy of the curve
+  EDGE* copied_EDGE_ptr;
+  outcome result = api_edge( EDGE_ptr, copied_EDGE_ptr );
+
+  //call the ACIS api for curve splitting
+  SPAposition split_point( split_location.x(), split_location.y(), split_location.z() );
+  ENTITY_LIST new_edges; 
+  result = api_split_curve( copied_EDGE_ptr, &split_point, NULL, new_edges );
+
+  if( !result.ok() )
+  {
+    AcisQueryEngine::instance()->ACIS_API_error (result);
+    PRINT_ERROR( "Unable to split curve\n" );
+    api_delent( copied_EDGE_ptr );
+    return CUBIT_FAILURE;
+  }
+  
+  int i;
+  for( i=0; i<new_edges.count(); i++ )
+  {
+    Curve *curve_ptr = AcisQueryEngine::instance()->populate_topology_bridges( (EDGE*)new_edges[i] ); 
+    new_curves.append( curve_ptr );
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+
 CubitStatus AcisModifyEngine::split_body( BodySM *body_ptr,
                                           DLIList<BodySM*> &new_bodies )
 {
@@ -11078,12 +12553,149 @@
    for (int i = 0; i < n_body; i++)
      new_BODYs.append(new_BODY_list[i]);
 
+   ACIS_DELETE [] STD_CAST new_BODY_list;
+
    CubitStatus status = get_new_Body(body_ptr, old_BODY,
                                      new_BODYs, new_bodies,
                                      CUBIT_FALSE);
    return status;
 }
 
+CubitStatus AcisModifyEngine::separate_surfaces( DLIList<Surface*> &surface_list,
+                                                 DLIList<BodySM*> &new_bodies )
+{
+  DLIList<SurfaceACIS*> copied_surface_list(surface_list.size());
+  CAST_LIST(surface_list, copied_surface_list, SurfaceACIS);
+  if (surface_list.size() != copied_surface_list.size())
+  {
+    PRINT_ERROR("Found a non-ACIS surface where ACIS was expected\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Loop on FACEs.  We will work on separating surfaces from one body at a time.
+  copied_surface_list.reset();
+  while( copied_surface_list.size() )
+  {
+    BODY *copied_BODY_ptr1;
+    DLIList<FACE*> separate_FACE_list1;
+    DLIList<SurfaceACIS*> separate_surface_list1;
+    if( get_copied_FACES_of_body( copied_surface_list, separate_FACE_list1,
+      separate_surface_list1, copied_BODY_ptr1 ) == CUBIT_FAILURE )
+      return CUBIT_FAILURE; 
+
+    // Get original Body and BODY
+    BodySM *body_ptr = AcisQueryEngine::instance()->
+      get_body_sm_of_ENTITY( copied_BODY_ptr1 );
+    BODY *BODY_ptr = AcisQueryEngine::get_BODY(body_ptr);
+
+    // Check for special case where all FACEs are being separated from a given
+    // BODY.  In this case we do want to separate the BODY but that is it.
+    DLIList<FACE*> tmp_FACE_list;
+    AcisQueryEngine::instance()->get_FACEs( copied_BODY_ptr1, tmp_FACE_list );
+    if( separate_FACE_list1.size() == tmp_FACE_list.size() )
+    {
+      // Just separate this BODY and continue
+      api_delent( copied_BODY_ptr1 );
+
+      if( split_body( body_ptr, new_bodies ) == CUBIT_FAILURE )
+      {
+        // Bomb out since we had an error
+        return new_bodies.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
+      }
+      continue;
+    }
+
+    // Make a second copy of the BODY
+    BODY *copied_BODY_ptr2;
+    DLIList<FACE*> separate_FACE_list2;
+    if( get_copied_FACES_of_body( separate_surface_list1, separate_FACE_list2,
+      copied_BODY_ptr2 ) == CUBIT_FAILURE )
+    {
+      api_delent( copied_BODY_ptr1 );
+      break;
+    }
+
+    // Remove separate_FACE_list1 from BODY_ptr1
+    if( remove_FACEs_from_BODY( copied_BODY_ptr1, separate_FACE_list1 )
+      == CUBIT_FAILURE )
+    {
+      api_delent( copied_BODY_ptr1 );
+      api_delent( copied_BODY_ptr2 );
+      return new_bodies.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
+    }
+
+    // Remove all but separate_FACE_list2 from BODY_ptr2
+    if( remove_FACEs_from_BODY_except( copied_BODY_ptr2, separate_FACE_list2 )
+      == CUBIT_FAILURE )
+    {
+      api_delent( copied_BODY_ptr1 );
+      api_delent( copied_BODY_ptr2 );
+      return new_bodies.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
+    }
+
+    // Remove duplicate Cubit owner attributes from copied_BODY_ptr2
+    remove_dup_owners( copied_BODY_ptr1, copied_BODY_ptr2 );
+
+    // Separate the BODIES
+    BODY **new_BODY_arr = 0;
+    int n_body;
+    bool old_flg = ATTRIB_CUBIT_OWNER::set_split_copy( true );
+    outcome result = api_separate_body( copied_BODY_ptr1, n_body, new_BODY_arr );
+    ATTRIB_CUBIT_OWNER::set_split_copy( old_flg );
+    if (!result.ok())
+    {
+      api_delent( copied_BODY_ptr1 );
+      api_delent( copied_BODY_ptr2 );
+      PRINT_ERROR("problem in separating the new sheet bodies.\n");
+      return CUBIT_FAILURE;
+    }
+
+    int i;
+    DLIList<BODY*> new_BODY_list;
+    for( i=0; i<n_body; i++ )
+     new_BODY_list.append( new_BODY_arr[i] );
+
+    ACIS_DELETE [] STD_CAST new_BODY_arr;
+    new_BODY_arr = 0;
+    n_body = 0;
+
+    ATTRIB_CUBIT_OWNER::set_split_copy( true );
+    result = api_separate_body( copied_BODY_ptr2, n_body, new_BODY_arr );
+    ATTRIB_CUBIT_OWNER::set_split_copy( old_flg );
+    if (!result.ok())
+    {
+      while( new_BODY_list.size() )
+        api_delent( new_BODY_list.pop() );
+      api_delent( copied_BODY_ptr2 );
+      PRINT_ERROR("problem in separating the new sheet bodies.\n");
+      return CUBIT_FAILURE;
+    }
+
+    for( i=0; i<n_body; i++ )
+     new_BODY_list.append( new_BODY_arr[i] );
+
+    ACIS_DELETE [] STD_CAST new_BODY_arr;
+
+    // Cleanup duplicate BODY owners
+    if( new_BODY_list.size() > 1 )
+    {
+      new_BODY_list.reset();
+      BODY *ref_BODY_ptr = new_BODY_list.get_and_step();
+      for( i=1; i<new_BODY_list.size(); i++ )
+      {
+        BODY *tmp_BODY_ptr = new_BODY_list.get_and_step();
+        remove_dup_owners( ref_BODY_ptr, tmp_BODY_ptr, BODY_TYPE );
+      }
+    }
+
+    if( get_new_Body(body_ptr, BODY_ptr, new_BODY_list, new_bodies,
+                     CUBIT_FALSE ) == CUBIT_FAILURE )
+      return CUBIT_FAILURE;                            
+  }
+
+  return CUBIT_SUCCESS;
+}
+
 CubitStatus AcisModifyEngine::split_periodic( BodySM *body_ptr,
                                               BodySM *&new_body)
 {
@@ -11120,6 +12732,14 @@
 EDGE *
 AcisModifyEngine::make_spline_EDGE( DLIList<CubitVector*> &vec_list )
 {
+    return make_spline_EDGE(vec_list, NULL, NULL);
+}
+
+EDGE *
+AcisModifyEngine::make_spline_EDGE( DLIList<CubitVector*> &vec_list, 
+                                    CubitVector* start_direction,
+                                    CubitVector* end_direction)
+{
   int i;
   EDGE *new_EDGE_ptr = NULL;
 
@@ -11138,7 +12758,19 @@
     vec_list.step();
   }
 
-  outcome result = api_curve_spline(num_pnts, pos_array, NULL, NULL, new_EDGE_ptr);
+  SPAunit_vector* start_ptr = NULL;
+  SPAunit_vector* end_ptr = NULL;
+
+  if (start_direction != NULL && end_direction != NULL)
+  {
+      SPAunit_vector start(start_direction->x(), start_direction->y(), start_direction->z());
+      SPAunit_vector end(end_direction->x(), end_direction->y(), end_direction->z());
+
+      start_ptr = &start;
+      end_ptr = &end;
+  }
+
+  outcome result = api_curve_spline(num_pnts, pos_array, start_ptr, end_ptr, new_EDGE_ptr);
   delete [] pos_array;
   if( !result.ok() || new_EDGE_ptr == NULL )
   {
@@ -11165,12 +12797,18 @@
   if (!body_ptr)
     return CUBIT_FAILURE;
 
+  BodyACIS* acis_body = dynamic_cast<BodyACIS*>(body_to_reverse);
+
   outcome result = api_reverse_body( body_ptr );
   if (!result.ok())
   {
     AcisQueryEngine::instance()->ACIS_API_error( result, "reversing BODY." );
     return CUBIT_FAILURE;
   }
+  //api_reverse_body turns sheet body to 1D...
+  //change it back to 2D
+  if( !acis_body->is_sheet_body() )
+    api_body_to_2d( body_ptr );
 
   return CUBIT_SUCCESS;
 }
@@ -11195,289 +12833,7 @@
 
 }
 
-void AcisModifyEngine::webcut_imprint(
-    BODY* cutting_tool_BODY_ptr,
-    DLIList<BodySM*> &old_body_list,
-    DLIList<BODY*>& new_webcut_BODY_list,
-    DLIList<BODY*>& just_webcut_BODY_list,
-    DLIList<BodySM*>& results_list,
-    DLIList<BodySM*> &imprinted_Body_from_Model_list,
-    DLIList<BODY*> &imprinted_BODY_from_Model_list) const
-{
-     // This procedure takes care of the imprint operations that are required
-     // by the webcut operation. Each of the BODYs in the new_webcut_BODY_list
-     // is tested against every other BODY in the model as well as every other
-     // BODY in the same list for interference. If interference exists, then
-     // the BODYs are imprinted with each other and new (corresponding) Bodies
-     // are created. Pointers to these new Bodies are inserted into the list,
-     // new_webcut_body_list.
 
-     // MJP Note:
-     // Note that this procedure takes care of imprinting the existing Bodies
-     // (i.e., the ones in the model) and creating new Bodies when necessary
-     // to replace these. However, new Body's are *not* created from the list
-     // of ACIS BODYs in the input list, new_webcut_BODY_list. These are simply
-     // returned to the calling routine, where it is expected that new Bodies
-     // will be created, as required.
-
-   int webcut_debug_flag = 18;
-   int webcut_debug_flag_on = DEBUG_FLAG(webcut_debug_flag);
-
-   int i = 0;
-   int j = 0;
-
-     // Make copies of the input BODYs
-   DLIList<BODY*> copy_new_webcut_BODY_list ;
-   DLIList<BODY*> new_results_BODYS;
-   new_webcut_BODY_list.reset() ;
-   for (i = 0; i < new_webcut_BODY_list.size() ; i++)
-   {
-      BODY* old_BODY = new_webcut_BODY_list.get_and_step() ;
-      BODY* new_BODY = this->copy_BODY(old_BODY,
-                                       GeometryModifyTool::instance()->get_new_ids()) ;
-
-        // Make sure the the new BODY is a valid BODY
-      assert( new_BODY != NULL) ;
-
-        // Add the new BODY to the backup list
-      copy_new_webcut_BODY_list.append(new_BODY) ;
-   }
-
-     // Loop over each of the new BODYs and imprint it with any other new BODY
-     // that touches it.
-   BODY* first_BODY_ptr = NULL;
-   BODY* second_BODY_ptr = NULL;
-   copy_new_webcut_BODY_list.reset() ;
-   for (i = 0; i < (copy_new_webcut_BODY_list.size() - 1); i++)
-   {
-        // Get the first BODY
-      first_BODY_ptr = copy_new_webcut_BODY_list.get_and_step();
-
-      for (j = (i + 1); j < copy_new_webcut_BODY_list.size(); j++)
-      {
-           // Get the second BODY
-         second_BODY_ptr = copy_new_webcut_BODY_list.get_and_step();
-
-           // If these BODYs touch, then imprint them
-         CubitBoolean result_interfer =
-             BODYs_interfering( first_BODY_ptr,second_BODY_ptr );
-
-         if ( result_interfer == CUBIT_TRUE )
-         {
-            CubitStatus resultImprint =
-                imprint_BODYs( first_BODY_ptr, second_BODY_ptr );
-
-            if( resultImprint == CUBIT_FAILURE )
-            {
-               PRINT_WARNING ("Imprint operation failed.\n"
-                              "         Going back to the previous state");
-
-                 // Delete the new BODYs and return.
-               copy_new_webcut_BODY_list.reset() ;
-               for (int k = 0 ; k < copy_new_webcut_BODY_list.size() ; k++)
-               {
-                  first_BODY_ptr = copy_new_webcut_BODY_list.get_and_step() ;
-                  AcisQueryEngine::instance()->delete_ACIS_BODY(first_BODY_ptr) ;
-               }
-               return ;
-            }
-         }
-      }
-
-        // Go to the (i+1)th element of the list
-      copy_new_webcut_BODY_list.reset() ;
-      copy_new_webcut_BODY_list.step(i+1) ;
-
-   }
-
-/*
-  CDE-- commented out this code.  For now, we've decided that when webcutting 
-  with the 'imprint' option, the imprint should occur between bodies involved
-  in the webcut.  This code was imprinting all resulting pieces of the webcut 
-  with all the other Bodies in the model.
-
-     // Get the Bodys in the Model
-   DLIList<Body*> Body_in_Model_list_tmp;
-   GeometryQueryTool::instance()->bodies(Body_in_Model_list_tmp);
-   DLIList<BodySM*> Body_in_Model_list;
-   Body_in_Model_list_tmp.reset();
-   for (i = Body_in_Model_list_tmp.size(); i--; )
-    Body_in_Model_list.append( Body_in_Model_list_tmp.get_and_step()->get_body_sm_ptr());
-
-     // Loop over each of the new BODYs and imprint it with any of the
-     // BODYs already existing in the model, if they touch.
-
-     // List of new imprinted BODYs -- Bodies need to be created from these
-   DLIList<BODY*> copy_imprinted_BODY_from_Model_list;
-
-   BodySM* model_Body_ptr = NULL;
-   BODY* model_BODY_ptr = NULL;
-   BODY* new_model_BODY_ptr = NULL;
-   BODY* new_BODY_ptr = NULL ;
-   int copy_made = CUBIT_FALSE;
-
-   Body_in_Model_list.reset();
-     // Loop over all the existing Bodies
-   for (i = 0; i < Body_in_Model_list.size(); i++)
-   {
-        // Get this existing Body's parent ACIS BODY
-      model_Body_ptr = Body_in_Model_list.get_and_step() ;
-      model_BODY_ptr = AcisQueryEngine::get_BODY(model_Body_ptr) ;
-
-        // Make sure that model_BODY_ptr is not the Cutting Tool as the
-        // user is allowed to use an existing Body as a Cutting Tool.
-        // If this is the case, then don't involve it in the imprint
-        // operations.
-      if (model_BODY_ptr == cutting_tool_BODY_ptr || old_body_list.move_to(model_Body_ptr))
-      {
-           // Don't do anything
-         continue;
-      }
-
-        // Loop over all the newly created (by webcutting) ACIS BODYs and test
-        // the existing Body against them (for imprinting purposes, if there
-        // is interference)
-      copy_made = CUBIT_FALSE;
-      new_model_BODY_ptr = NULL;
-      copy_new_webcut_BODY_list.reset();
-
-      for (j = 0; j < copy_new_webcut_BODY_list.size(); j++)
-      {
-           // Get the BODY that we're going to test the existing Body against
-         new_BODY_ptr = copy_new_webcut_BODY_list.get_and_step() ;
-
-           // DEBUG stuff
-         if (webcut_debug_flag_on)
-         {
-              //Save the two BODYs
-            AcisQueryEngine::instance()->save_ENTITY_as_sat_file(new_BODY_ptr, "BODY1.sat", "w");
-            AcisQueryEngine::instance()->save_ENTITY_as_sat_file(model_BODY_ptr, "BODY2.sat", "w");
-         }
-
-           // If these BODYs touch, then ...
-         if ( BODYs_interfering(new_BODY_ptr, model_BODY_ptr) == CUBIT_TRUE )
-         {
-              // DEBUG stuff
-            if (webcut_debug_flag_on)
-            {
-               AcisQueryEngine::instance()->save_ENTITY_as_sat_file(new_BODY_ptr,
-                                             "BODY1_after_test.sat",
-                                             "w");
-               AcisQueryEngine::instance()->save_ENTITY_as_sat_file(new_model_BODY_ptr,
-                                             "BODY2_after_test.sat",
-                                             "w");
-            }
-
-              // Because of the fact that the RefEntity datastructure is
-              // nonmanifold and hence shares underlying ACIS ENTITYs, I have to:
-              //   a) make a copy of the parent ACIS BODY of the Body being
-              //      deactivated (this is done only once for the inner loop)
-              //   b) then all imprinting is done with this copy instead of
-              //     with the original parent ACIS BODY.
-              // deactivateRefStructure takes care of detaching the RefEntities
-              // and their associated ACIS ENTITYs (removing the double links
-              // between them).
-            if (!copy_made) // Make this copy at most once per outer loop iteration
-            {
-                 // Make a copy of the parent ACIS BODY.
-               new_model_BODY_ptr = this->copy_BODY(model_BODY_ptr,
-                                                    GeometryModifyTool::instance()->get_new_ids());
-
-                 // Make sure a valid copy was made. If not, then we need to exit
-                 // this loop (i.e., stop testing this Body for imprinting
-                 // and go on to the next one).
-               if (new_model_BODY_ptr == NULL)
-               {
-                  PRINT_ERROR("Cannot test imprinting for volume.\n" );
-                  break;
-               }
-               else
-               {
-                  copy_made = CUBIT_TRUE;
-                  if ( results_list.move_to(model_Body_ptr) )
-                    new_results_BODYS.append( new_model_BODY_ptr );
-                  imprinted_Body_from_Model_list.append(model_Body_ptr) ;
-                  imprinted_BODY_from_Model_list.append(model_BODY_ptr) ;
-                  copy_imprinted_BODY_from_Model_list.append(new_model_BODY_ptr) ;
-               }
-            }
-
-              // Imprint the BODYs (use the new copied BODY). If the imprint
-              // operation fails, the state of these BODYs is left unchanged.
-            if (imprint_BODYs(new_BODY_ptr, new_model_BODY_ptr) ==  CUBIT_SUCCESS )
-            {
-                 // DEBUG stuff, if the imprint operation succeeded.
-               if (webcut_debug_flag_on)
-               {
-                  AcisQueryEngine::instance()->save_ENTITY_as_sat_file(new_BODY_ptr,
-                                                "BODY1_after_imprint.sat",
-                                                "w");
-                  AcisQueryEngine::instance()->save_ENTITY_as_sat_file(new_model_BODY_ptr,
-                                                "BODY2_after_imprint.sat",
-                                                "w");
-               }
-            }
-
-            else
-            {
-               PRINT_WARNING ("Imprint operation failed.\n"
-                              "         Going back to the previous state");
-
-                 // Delete the new BODYs and return.
-               copy_new_webcut_BODY_list.reset() ;
-               int k;
-               for (k = 0 ; k < copy_new_webcut_BODY_list.size() ; k++)
-               {
-                  new_BODY_ptr = copy_new_webcut_BODY_list.get_and_step() ;
-                  AcisQueryEngine::instance()->delete_ACIS_BODY(first_BODY_ptr) ;
-               }
-
-               copy_imprinted_BODY_from_Model_list.reset() ;
-               for (k = 0 ; k < copy_imprinted_BODY_from_Model_list.size() ; k++)
-               {
-                  new_model_BODY_ptr = copy_imprinted_BODY_from_Model_list.get_and_step() ;
-                  AcisQueryEngine::instance()->delete_ACIS_BODY(new_model_BODY_ptr) ;
-               }
-
-               return ;
-            }
-         }
-      } // Loop over the new (webcut) BODYs
-
-   } // Loop over the existing Bodies in Model
-*/
-     // Now that we have come so far successfully, create the final list
-     // of new BODYs that will be used to create VGI Bodys.
-   new_webcut_BODY_list.clean_out() ;
-
-     // First the BODYs that were copies of the webcut BODYs
-   BODY* new_BODY_ptr = NULL ;
-   copy_new_webcut_BODY_list.reset() ;
-   for (i = 0 ; i < copy_new_webcut_BODY_list.size() ; i++)
-   {
-      new_BODY_ptr = copy_new_webcut_BODY_list.get_and_step() ;
-      new_webcut_BODY_list.append(new_BODY_ptr) ;
-   }
-   just_webcut_BODY_list = new_webcut_BODY_list;
-
-/*
-     // Then the BODYs that were copies of Model BODYs
-   copy_imprinted_BODY_from_Model_list.reset() ;
-   for (i = 0 ; i < copy_imprinted_BODY_from_Model_list.size() ; i++)
-   {
-      new_BODY_ptr = copy_imprinted_BODY_from_Model_list.get_and_step() ;
-      new_webcut_BODY_list.append(new_BODY_ptr) ;
-   }
-*/
-     // now, two important lists:
-     // a) just_webcut_BODY_list: bodies in original bodies-to-be-webcut list
-     //        that were modified, either by webcut or by imprint
-     // b) new_webcut_BODY_list: all bodies modified by webcut or imprint,
-     //        including model bodies affected by imprint
-
-   return;
-}
-
 BODY* AcisModifyEngine::create_infinite_plane_cutting_tool(
     const CubitVector &input_p1,
     const CubitVector &input_p2,
@@ -11714,7 +13070,8 @@
 CubitStatus AcisModifyEngine::create_solid_bodies_from_surfs( DLIList<Surface*> &ref_face_list,
                                                       DLIList<BodySM*> &new_bodies,
                                                       bool keep_old,
-                                                      bool heal ) const
+                                                      bool heal,
+                                                      bool sheet ) const
 {
   int ii;
   Surface* ref_face;
@@ -11900,7 +13257,6 @@
 //  BODY *new_master = master;
   if ( heal )
   {
-
       // Now heal the combined body
     PRINT_INFO(" Healing the combined volume...\n");
     if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
@@ -11950,6 +13306,27 @@
     return CUBIT_FAILURE;
   }
 
+  //sheet options says that the caller is ok with an open body 
+  //being created
+  if( sheet == false )
+  {
+    //make sure that body has volume
+    mass_props_options mp_options;
+    mp_options.set_level( VOLUME_ONLY );
+    mass_props tmp_mass_props;
+    api_body_mass_props( new_master, tmp_mass_props, &mp_options );
+
+    if( tmp_mass_props.get_volume() < GEOMETRY_RESABS )
+    {
+      PRINT_ERROR("Failing because resulting body has no volume.\n"
+                  "      Examine your set of surfaces to make sure\n"
+                  "      there are no gaps and none are overlapping\n");
+      api_delent( new_master );
+
+      return CUBIT_FAILURE;
+    }
+  }
+
   //separate the bodies so that you have no multi-volume bodies
   ENTITY_LIST separated_bodies;
   BODY **new_BODY_list;
@@ -11961,8 +13338,7 @@
   for( i=0; i<n_bodies; i++ )
     new_BODIES.append( new_BODY_list[i] );
 
-  CubitStatus success =
-    get_new_Body(old_entities, new_BODIES, new_bodies, keep_old);
+  get_new_Body(old_entities, new_BODIES, new_bodies, keep_old);
 
   if ( new_bodies.size() == 0 )
   {
@@ -11978,7 +13354,9 @@
                                                  Surface* top_surf_ptr,
                                                  Surface* bottom_surf_ptr,
                                                  DLIList<BodySM*>& ,
-                                                 bool  ) const
+                                                 DLIList<BodySM*>& ,
+                                                 ImprintType imprint_type,
+                                                 bool /*preview*/) const
 {
    CubitVector top_orig, top_norm, bottom_orig, bottom_norm;
    double top_orig_pnt[3], top_norm_vec[3], bottom_orig_pnt[3], bottom_norm_vec[3];
@@ -12188,6 +13566,7 @@
 CubitStatus AcisModifyEngine::imprint( DLIList<BodySM*> &body_list,
                                        DLIList<Curve*> &ref_edge_list,
                                        DLIList<BodySM*>& new_body_list,
+                                       DLIList<TopologyBridge*> &temporary_bridges,
                                        bool keep_old_body,
                                        bool show_messages) const
 {
@@ -12196,6 +13575,14 @@
    CubitStatus status = CUBIT_SUCCESS;
    CubitBoolean imprint_worked = CUBIT_FALSE;
 
+   AcisHistory history_object;
+   if( GeometryQueryTool::instance()->history().is_tracking() )
+   {
+      DLIList<TopologyBridge*> my_bridges;
+      CAST_LIST( body_list, my_bridges, TopologyBridge );
+      AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+   }
+
    Curve* ref_edge_ptr;
    BodySM *body_ptr;
 
@@ -12300,10 +13687,47 @@
            status = CUBIT_FAILURE;
          }
          else
-           imprint_worked = CUBIT_TRUE;
+         {
+            imprint_worked = CUBIT_TRUE;
+            ENTITY_LIST tmp_edges;
+            api_get_edges((ENTITY*)wire_BODY_ptr, tmp_edges);
+            ENTITY *tmp_ent;
+            tmp_edges.init();
+            while((tmp_ent = tmp_edges.next()))
+            {
+              Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges((EDGE*)tmp_ent);
+              if(new_curve)
+                temporary_bridges.append(new_curve);
+            }
+         }
       }
       if( imprint_worked )
       {
+
+        //examine all the edges in the new body for CSA's
+        ENTITY_LIST corey_edges;
+        api_get_edges(copied_BODY_ptr, corey_edges);
+
+        int kk;
+        for( kk=0; kk<corey_edges.count(); kk++ )
+        {
+          EDGE *tmp_edge = (EDGE*)corey_edges[kk];
+
+          ATTRIB_SNL_SIMPLE *attribute =
+            (ATTRIB_SNL_SIMPLE *) find_attrib( tmp_edge,
+                                              ATTRIB_SNL_TYPE,
+                                              ATTRIB_SNL_SIMPLE_TYPE);
+          for(;attribute != NULL;attribute = (ATTRIB_SNL_SIMPLE *)
+                find_next_attrib(attribute,
+                                ATTRIB_SNL_TYPE,
+                                ATTRIB_SNL_SIMPLE_TYPE))
+          {
+            CubitSimpleAttrib *csa = attribute->get_CSA();
+            PRINT_INFO("I have this attrib after on an edge:\n");
+            csa->print();
+          }
+        }
+
           api_set_int_option("all_free_edges", FALSE );
 
           DLIList<EDGE*> new_edges = AcisModifyEngine::instance()->find_new_EDGES(copied_BODY_ptr);
@@ -12324,10 +13748,16 @@
           }
       }
    }
+  
+   if( GeometryQueryTool::instance()->history().is_tracking() )
+     AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
 
+
    // Free memory
+   /*
    for( i=0; i<ewire_list.size(); i++ )
       api_delent( ewire_list.get_and_step() );
+      */
    if ( imprint_worked && status != CUBIT_SUCCESS )
      status = CUBIT_SUCCESS;
    return status;
@@ -12340,6 +13770,7 @@
 // a body, but the curves just have to be valid ACIS EDGEs.
 CubitStatus AcisModifyEngine::imprint( DLIList<Surface*> &surface_list,
                                        DLIList<Curve*> &curve_list,
+                                       DLIList<TopologyBridge*> &temporary_bridges,
                                        DLIList<BodySM*>& new_body_list,
                                        bool keep_old_body ) const
 {
@@ -12402,6 +13833,14 @@
     EDGE_list.append( copied_EDGE_ptr );
   }
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( surface_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
   // Loop on FACEs.  We will work on imprinting surfaces from one body at a time.
   copied_surface_list.reset();
   while( copied_surface_list.size() )
@@ -12420,7 +13859,7 @@
     if( delete_attribs )
       AcisQueryEngine::instance()->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
 
-    if( imprint( copied_BODY_ptr, imprint_FACE_list, EDGE_list ) == CUBIT_FAILURE )
+    if( imprint( copied_BODY_ptr, imprint_FACE_list, EDGE_list, temporary_bridges ) == CUBIT_FAILURE )
     {
       // This only fails if there is a serious error - delete the copied Body
         api_delent( copied_BODY_ptr );
@@ -12446,6 +13885,9 @@
     }
   }
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+
   // Free the memory allocated when copying edges
   for( i=0; i<EDGE_list.size(); i++ )
   {
@@ -12460,7 +13902,8 @@
 // are modified but EDGEs are not.
 CubitStatus AcisModifyEngine::imprint( BODY *BODY_ptr,
                                        DLIList<FACE*> &FACE_list,
-                                       DLIList<EDGE*> &EDGE_list ) const
+                                       DLIList<EDGE*> &EDGE_list,
+                                       DLIList<TopologyBridge*> &temporary_bridges) const
 {
   // Imprint the edges to the surfaces on this body
   outcome result;
@@ -12487,7 +13930,7 @@
       // Get the FACE to imprint to
       FACE_ptr = FACE_list.get_and_step();
 
-      if( imprint( BODY_ptr, FACE_ptr, EDGE_ptr ) == CUBIT_FAILURE )
+      if( imprint( BODY_ptr, FACE_ptr, EDGE_ptr, temporary_bridges ) == CUBIT_FAILURE )
       {
         PRINT_ERROR( "Unable to imprint EDGE to FACE\n" );
         continue;
@@ -12528,131 +13971,297 @@
 
 CubitStatus AcisModifyEngine::imprint( BODY *BODY_ptr,
                                        FACE *FACE_ptr,
-                                       EDGE *EDGE_ptr ) const
+                                       EDGE *EDGE_ptr,
+                                       DLIList<TopologyBridge*> &temporary_bridges,
+                                       bool expand ) const
 {
   outcome result;
-
+  
   BODY* tbody = NULL;
   BODY* bbody = NULL;    // Blank body
   FACE* bface = NULL;    // Blank face
   surface* tsurf = NULL; // Tool surface
   EDGE* edge = NULL;
 
-  //EXCEPTION_TRY
-
   bbody = BODY_ptr;
   bface = FACE_ptr;
   edge = EDGE_ptr;
 
-  // Get the geometry of the blank face.
-  surface const& bsurf = bface->geometry()->equation();
-
-  // Create an empty tool body
-  tbody = ACIS_NEW BODY( (LUMP*) NULL );
-
-  // Create the tool body which consists of a single face
-  // with a "cross surface" geometric support and no loops.
-  const curve &temp_cur = edge->geometry()->equation();
-  SPAinterval cur_range = temp_cur.param_range();
-  SPAinterval edge_range = edge->param_range();
-  if (edge->sense() == REVERSED)
-    edge_range = -edge_range;
-  if (edge_range == cur_range)
-    tsurf = cross_surface( edge->geometry()->equation(),
-    bsurf, *(pcurve*) NULL_REF);
+  surface const & surf_to_trim = bface->geometry()->equation();
+  SPAposition pos;
+  SPAunit_vector normal;
+  CubitBoolean planar = surf_to_trim.planar(pos, normal);
+  
+  if (!planar)
+   {
+   // AcisDrawTool::instance()->draw_EDGE( edge, CUBIT_YELLOW, true );
+    //AcisDrawTool::instance()->draw_FACE( bface, CUBIT_BLUE, true );
+   // GfxDebug::mouse_xforms();
+    
+    
+    BODY *wire_body_orig;
+    EDGE *edge_list[1];
+    edge_list[0] = edge;
+    result = api_make_ewire(1, edge_list, wire_body_orig);
+    if( !result.ok())
+    {
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "Could not create wire\n");
+      return CUBIT_FAILURE;
+    }
+    
+    // copy the edge
+    BODY *wire_body1 = NULL;
+    BODY *wire_body3 = NULL;
+    result = api_copy_body( wire_body_orig, wire_body1 );
+    if( !result.ok())
+    {
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "Could not copy wire\n");
+      return CUBIT_FAILURE;
+    }
+    result = api_copy_body( wire_body_orig, wire_body3 );
+    if( !result.ok())
+    {
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "Could not copy wire\n");
+      return CUBIT_FAILURE;
+    }
+    
+    // get center point of the curve
+    SPAposition curv_center = edge->mid_pos();
+    
+    // get the length of the curve
+    double curve_length = edge->length();
+    
+    // get the normal on the surface to the center of the curve
+    SPAunit_vector surf_normal = surf_to_trim.point_normal(curv_center);
+    
+    // make wires and translate one along the normal and one in the opposite direction
+    double xyz[3];
+    xyz[0] = surf_normal.x()*curve_length*0.5;
+    xyz[1] = surf_normal.y()*curve_length*0.5;
+    xyz[2] = surf_normal.z()*curve_length*0.5;
+    SPAvector normal_trans(xyz[0], xyz[1], xyz[2]);
+    SPAvector minus_normal_trans(-xyz[0], -xyz[1], -xyz[2]);
+    
+    SPAtransf plus_trans, minus_trans;
+    plus_trans = translate_transf(normal_trans);
+    minus_trans = translate_transf(minus_normal_trans);
+    
+    result = api_apply_transf( wire_body1, plus_trans );
+    if( !result.ok())
+    {
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "error #4\n");
+    }
+    result = api_apply_transf( wire_body3, minus_trans );
+    if( !result.ok())
+    {
+      AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "error #5\n");
+    }
+    
+    // now skin the wires
+    BODY *wire_list[2];
+    wire_list[0] = wire_body1;
+    wire_list[1] = wire_body3;
+    skin_options tmp_skin_options;
+    tmp_skin_options.set_solid(0);
+    BODY *trim_tool;
+    result = api_skin_wires(2, wire_list, trim_tool, RULED_SKINNING, &tmp_skin_options);
+    if( !result.ok())
+    {
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_WARNING( "Could not create the surface to split with\n");
+      return CUBIT_FAILURE;
+    }
+    
+    ENTITY_LIST trim_tool_edges;
+    result = api_get_edges(trim_tool, trim_tool_edges);
+    if( !result.ok() )
+    {
+      api_delent( trim_tool );
+      trim_tool = NULL;
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "Could not get the edges of the trimming surface\n");
+      return CUBIT_FAILURE;
+    }
+    
+    if (expand)
+    {
+      SPAposition trim_tool_box_high(0,0,0);
+      SPAposition trim_tool_box_low(0,0,0);
+    
+      // now extend the sheetbody
+      lop_options lop_opt = lop_options();
+      lop_opt.set_repair_self_int(TRUE);
+    
+      result = api_extend_sheetbody(trim_tool_edges, 0.003, trim_tool_box_low, trim_tool_box_high, &lop_opt);
+      //result = api_extend_sheetbody(trim_tool_edges, 0.01, trim_tool_box_low, trim_tool_box_high, &lop_opt);
+      if( !result.ok() )
+      {
+        //AcisQueryEngine::instance()->ACIS_API_error(result);
+        PRINT_ERROR( "Unable to extend the trimming surface\n" );
+        return CUBIT_FAILURE;
+      }
+    }
+    
+    ENTITY_LIST trim_tool_faces;
+    result = api_get_faces(trim_tool, trim_tool_faces);
+    if( !result.ok())
+    {
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_ERROR( "Could not get the faces of the trimming surface\n");
+      return CUBIT_FAILURE;
+    }
+    FACE *trim_tool_face = (FACE*)trim_tool_faces.first();
+    
+    // do a face to face intersection
+    BODY *split_wire_body = NULL;
+    result = api_fafa_int(trim_tool_face, bface, split_wire_body);
+    if( !result.ok())
+    {
+      // as mentioned below in the original code this function will fail rather frequently 
+      // however that rarely seems to cause a problem.
+      api_delent( trim_tool_face );
+      return CUBIT_SUCCESS;
+    }
+    
+    // Imprint the wire-body onto the BODY
+    result = api_imprint( split_wire_body, bbody );
+    if( !result.ok() && result.error_number()!=200 && result.error_number()!=15020)
+    {
+      //AcisQueryEngine::instance()->ACIS_API_error(result);
+      PRINT_WARNING( "problem splitting face\n");
+      return CUBIT_FAILURE;
+    }
+    
+    TopologyBridge *tb = AcisQueryEngine::instance()->populate_topology_bridges(trim_tool);
+    if(tb)
+      temporary_bridges.append(tb);
+    
+    return CUBIT_SUCCESS;
+  }
   else
-  {
-    // Create using a subsetted copy of the curve
-    curve* subset_cur = temp_cur.subset(edge_range&cur_range);
-    tsurf = cross_surface( *subset_cur, bsurf, *(pcurve*) NULL_REF);
-    ACIS_DELETE subset_cur;
-  }
-  if( !tsurf )
-  {
-    PRINT_ERROR( "Unable to make imprint surface on body\n" );
-    return CUBIT_FAILURE;
-  }
-  FACE* tface = ACIS_NEW FACE( NULL, NULL, make_surface( *tsurf ), FORWARD );
-  ACIS_DELETE tsurf; // SRS Added 10-29-99
-  tbody->set_lump( ACIS_NEW LUMP( ACIS_NEW SHELL( tface, NULL, NULL ), NULL ) );
+  {    
+    // Get the geometry of the blank face.
+    surface const& surf_to_trim = bface->geometry()->equation();
 
-  // Now, imprint the two bodies and throw away the tool body. The
-  // resultant blank body will have the edge imprinted on the
-  // selected face.
-  EDGE* ssi_edges[1];
-  FACE* tfaces[1];
-  FACE* bfaces[1];
+    // Create an empty tool body
+    tbody = ACIS_NEW BODY( (LUMP*) NULL );
 
-  ssi_edges[0] = edge;
-  tfaces[0] = tface;
-  bfaces[0] = bface;
+    // Create the tool body which consists of a single face
+    // with a "cross surface" geometric support and no loops.
+    const curve &temp_cur = edge->geometry()->equation();
+    SPAinterval cur_range = temp_cur.param_range();
+    SPAinterval edge_range = edge->param_range();
+    if (edge->sense() == REVERSED)
+      edge_range = -edge_range;
+    if (edge_range == cur_range)
+      tsurf = cross_surface( edge->geometry()->equation(),
+                            surf_to_trim, *(pcurve*) NULL_REF);
+    else
+    {
+      // Create using a subsetted copy of the curve
+      curve* subset_cur = temp_cur.subset(edge_range&cur_range);
+      tsurf = cross_surface( *subset_cur, surf_to_trim, *(pcurve*) NULL_REF);
+      ACIS_DELETE subset_cur;
+    }
+    
+    if( !tsurf )
+    {
+      PRINT_ERROR( "Unable to make imprint surface on body\n" );
+      return CUBIT_FAILURE;
+    }
+    FACE* tface = ACIS_NEW FACE( NULL, NULL, make_surface( *tsurf ), FORWARD );
+  
+    ACIS_DELETE tsurf; // SRS Added 10-29-99
+    tbody->set_lump( ACIS_NEW LUMP( ACIS_NEW SHELL( tface, NULL, NULL ), NULL ) );
+    
+    // Now, imprint the two bodies and throw away the tool body. The
+    // resultant blank body will have the edge imprinted on the
+    // selected face.
+    EDGE* ssi_edges[1];
+    FACE* tfaces[1];
+    FACE* bfaces[1];
 
-  result = api_boolean_start( tbody, bbody );
+    ssi_edges[0] = edge;
+    tfaces[0] = tface;
+    bfaces[0] = bface;
 
-  if( result.ok() )
-  {
-    // If the edge is known to lie on the face, some expensive
-    // checking can be ommited by changing the last argument from
-    // TRUE to FALSE.
-    result = api_update_intersection( tface, *(SPAtransf *)NULL_REF, bface,
-      *(SPAtransf *)NULL_REF, 1, ssi_edges, TRUE);
+    result = api_boolean_start( tbody, bbody );
 
     if( result.ok() )
     {
-      result = api_selectively_intersect( 1, tfaces, bfaces );
+      // If the edge is known to lie on the face, some expensive
+      // checking can be ommited by changing the last argument from
+      // TRUE to FALSE.
+      result = api_update_intersection( tface, *(SPAtransf *)NULL_REF, bface,
+        *(SPAtransf *)NULL_REF, 1, ssi_edges, TRUE );
+    
       if( result.ok() )
       {
-        result = api_imprint_complete( tbody, bbody );
-        if( !result.ok() )
+        result = api_selectively_intersect( 1, tfaces, bfaces );
+        if( result.ok() )
         {
-          PRINT_ERROR( "problem in completing imprint for curve on surface\n" );
+          result = api_imprint_complete( tbody, bbody );
+          if( !result.ok() )
+          {
+            PRINT_ERROR( "problem in completing imprint for curve on surface\n" );
+            AcisQueryEngine::instance()->ACIS_API_error(result);
+            api_delent( tbody );
+            return CUBIT_FAILURE;
+          }
+        }
+        else
+        {
+          PRINT_ERROR( "problem in selective intersect for curve on surface\n" );
           AcisQueryEngine::instance()->ACIS_API_error(result);
           api_delent( tbody );
           return CUBIT_FAILURE;
         }
       }
-      else
+      else if( result.error_number()!=200 && result.error_number()!=615
+        && result.error_number()!=715 )
       {
-        PRINT_ERROR( "problem in selective intersect for curve on surface\n" );
-        AcisQueryEngine::instance()->ACIS_API_error(result);
+        // Error 200 can occur when the imprint does nothing (curve that's
+        // a surface boundary, curve away from surface).  Errors 615/715 can occur
+        // when imprinting a remnant of the same FACE again with the same curve.
+        // The orignal FACE_ptr remains after an imprint - it lives as one
+        // of the remnants.  Then, when we attempt to imprint the other pieces
+        // with the same curves, we are getting error 715.  The same error
+        // can occur when trying to use one of the surfaces own edges to
+        // imprint with.  This has been reported to Spatial and logged as r6294.
+        // It's not fatal so for now we ignore it.
+
+        // We get these all the time, and they don't seem to hurt us.
+      
         api_delent( tbody );
-        return CUBIT_FAILURE;
+        return CUBIT_SUCCESS;
       }
     }
-    else if( result.error_number()!=200 && result.error_number()!=615
-      && result.error_number()!=715 )
+    else
     {
-      // Error 200 can occur when the imprint does nothing (curve that's
-      // a surface boundary, curve away from surface).  Errors 615/715 can occur
-      // when imprinting a remnant of the same FACE again with the same curve.
-      // The orignal FACE_ptr remains after an imprint - it lives as one
-      // of the remnants.  Then, when we attempt to imprint the other pieces
-      // with the same curves, we are getting error 715.  The same error
-      // can occur when trying to use one of the surfaces own edges to
-      // imprint with.  This has been reported to Spatial and logged as r6294.
-      // It's not fatal so for now we ignore it.
-
-      // We get these all the time, and they don't seem to hurt us.
+      PRINT_ERROR( "problem starting boolean for curve on surface\n" );
+      AcisQueryEngine::instance()->ACIS_API_error(result);
       api_delent( tbody );
-      return CUBIT_SUCCESS;
+      return CUBIT_FAILURE;
     }
-  }
-  else
-  {
-    PRINT_ERROR( "problem starting boolean for curve on surface\n" );
-    AcisQueryEngine::instance()->ACIS_API_error(result);
-    api_delent( tbody );
-    return CUBIT_FAILURE;
-  }
 
-  //EXCEPTION_CATCH(TRUE)
+    //EXCEPTION_CATCH(TRUE)
 
-  // Remove temporary objects
-  api_delent( tbody );
+    // Remove temporary objects
+    //  api_delent( tbody );
+    TopologyBridge *tb = AcisQueryEngine::instance()->populate_topology_bridges(tbody);
+    if(tb)
+      temporary_bridges.append(tb);
 
-  //EXCEPTION_END
+    //EXCEPTION_END
 
-  return CUBIT_SUCCESS;
+    return CUBIT_SUCCESS;
+  }
+  return CUBIT_FAILURE;
 }
 
 //- Imprints a list of Surfaces with list of Curves, sorted per
@@ -12663,7 +14272,10 @@
 CubitStatus AcisModifyEngine::imprint( DLIList<Surface*> &surface_list,
                                        DLIList<DLIList<Curve*>*> &curve_lists_list,
                                        BodySM*& new_body,
-                                       bool keep_old_body ) const
+                                       bool keep_old_body,
+                                       bool expand,
+                                       DLIList<TopologyBridge*> *new_tbs,
+                                       DLIList<TopologyBridge*> *att_tbs  ) const
 {
   // Calling code has already ensured that all the Surfaces are from the
   // same body
@@ -12736,6 +14348,14 @@
       EDGE_list_ptr->append( EDGE_ptr );
     }
   }
+  
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( surface_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
 
   // Copy the BODY and get the corresponding FACEs on the copied BODY that need
   // to be imprinted
@@ -12751,16 +14371,89 @@
   if( delete_attribs )
     AcisQueryEngine::instance()->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
 
+  // Get the edges on the original faces to be split.  When we are done
+  // with the split we will check to see if any of the split edges
+  // are the "same" as any of the original edges and if they are we
+  // will call them "new" for the sake of interoperability.  This way
+  // if the edge was hidden in a composite it will then be 
+  // reintroduced even though the ACIS surface being split wasn't
+  // actually split at all.
+  DLIList<DLIList<EDGE*>*> lists_of_EDGES_on_original_FACES;
+  DLIList<EDGE*> *list_ptr;
+  if(new_tbs)
+  {
+    for(i=copied_FACE_list.size(); i--;)
+    {
+      list_ptr = new DLIList<EDGE*>;
+      lists_of_EDGES_on_original_FACES.append( list_ptr );
+
+      FACE *FACE_ptr = copied_FACE_list.get_and_step();
+      ENTITY_LIST face_edges;
+      api_get_edges((ENTITY*)FACE_ptr, face_edges);
+      
+      ENTITY *tmp_ent;
+      face_edges.init();
+      while((tmp_ent = face_edges.next()))
+        list_ptr->append((EDGE*)tmp_ent);
+    }
+  }
+
   // Imprint the temporary EDGEs to the FACEs
-  if( imprint( copied_BODY_ptr, copied_FACE_list, EDGE_lists_list ) == CUBIT_FAILURE )
+
+  if( imprint( copied_BODY_ptr, copied_FACE_list, EDGE_lists_list, expand ) == CUBIT_FAILURE )
   {
     api_delent( copied_BODY_ptr );
     while( EDGE_lists_list.size() ) delete EDGE_lists_list.pop();
     return CUBIT_FAILURE;
   }
+
   DLIList<EDGE*> new_edges = AcisModifyEngine::instance()->find_new_EDGES(copied_BODY_ptr);
+
+  DLIList<ENTITY*> new_ENTITIES, att_ENTITIES;
+  if(copied_BODY_ptr && new_tbs)
+  {
+    get_new_ENTITIES(copied_BODY_ptr, new_ENTITIES, &lists_of_EDGES_on_original_FACES, 
+      &EDGE_lists_list);
+  }
+
   new_body = get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr, false);
 
+  if (new_body)
+  {
+    // Get entities with composite attributes.
+    if(copied_BODY_ptr && att_tbs)
+      get_att_ENTITIES(copied_BODY_ptr, att_ENTITIES, "COMPOSITE_GEOM");
+  }
+  else
+  {
+    // Get entities with composite attributes.
+    if(att_tbs)
+      get_att_ENTITIES(BODY_ptr, att_ENTITIES, "COMPOSITE_GEOM");
+  }
+ 
+  // Convert the new_ENTITIES/att_ENTITIES lists into
+  // topology bridge lists.
+  if(new_tbs)
+  {
+    for(i=new_ENTITIES.size(); i--;)
+    {
+      ENTITY *cur_ENT = new_ENTITIES.get_and_step();
+      AcisBridge *acis_bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_ENT);
+      if(dynamic_cast<TopologyBridge*>(acis_bridge))
+        new_tbs->append_unique(dynamic_cast<TopologyBridge*>(acis_bridge));
+    }
+  }
+  if(att_tbs)
+  {
+    for(i=att_ENTITIES.size(); i--;)
+    {
+      ENTITY *cur_ENT = att_ENTITIES.get_and_step();
+      AcisBridge *acis_bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_ENT);
+      if(dynamic_cast<TopologyBridge*>(acis_bridge))
+        att_tbs->append_unique(dynamic_cast<TopologyBridge*>(acis_bridge));
+    }
+  }
+  
   // Add a imprint feature to the topo edges
   for (int edge_count = new_edges.size(); edge_count-- && new_body; ) 
   {
@@ -12772,6 +14465,13 @@
   // Free memory allocated in EDGE_lists_list
   while( EDGE_lists_list.size() ) delete EDGE_lists_list.pop();
 
+  if( GeometryQueryTool::instance()->history().is_tracking() && new_body )
+  {
+    DLIList<BodySM*> new_body_list(1);
+    new_body_list.append( new_body );
+    AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+  }
+
   return new_body ? CUBIT_SUCCESS : CUBIT_FAILURE;
 }
 
@@ -12800,8 +14500,9 @@
 // list positions)
 CubitStatus AcisModifyEngine::imprint( BODY *BODY_ptr,
                                        DLIList<FACE*> &FACE_list,
-                                       DLIList<DLIList<EDGE*>*> &EDGE_lists_list ) const
-{
+                                       DLIList<DLIList<EDGE*>*> &EDGE_lists_list,
+                                       bool expand) const
+{  
   // Imprint the edges to the surfaces on this body
   outcome result;
   FACE *FACE_ptr = 0;
@@ -12839,12 +14540,19 @@
 
         FACES_BEFORE.clean_out();
         AcisQueryEngine::instance()->get_FACEs( (ENTITY *)BODY_ptr, FACES_BEFORE );
-
-        if( imprint( BODY_ptr, FACE_ptr, EDGE_ptr ) == CUBIT_FAILURE )
+        
+        DLIList<TopologyBridge*> temporary_bridges;
+        if( imprint( BODY_ptr, FACE_ptr, EDGE_ptr, temporary_bridges, expand ) == CUBIT_FAILURE )
         {
-          PRINT_ERROR( "Unable to imprint EDGE to FACE\n" );
+          // PRINT_ERROR( "Unable to imprint EDGE to FACE\n" ); With new split surface algorithm this is not an error
+          temporary_bridges.uniquify_ordered();
+          while(temporary_bridges.size())
+            delete temporary_bridges.pop();
           continue;
         }
+        temporary_bridges.uniquify_ordered();
+        while(temporary_bridges.size())
+          delete temporary_bridges.pop();
 
         // Check against an assumption that if invalid, will
         // cause a crash.  The assumption is that the imprinted
@@ -12888,13 +14596,21 @@
                                        DLIList<BodySM*>& new_body_list,
                                        bool keep_old_body,
                                        DLIList<TopologyBridge*> *new_tbs,
-                                       DLIList<TopologyBridge*> *att_tbs ) const
+                                       DLIList<TopologyBridge*> *att_tbs,
+                                       double *tol_in,
+                                       bool clean_up_slivers) const
 {
    // Until Spatial fixes imprinting with vertices, implement a hack
    // (Steve Storm, Caterpillar Inc.)
    int i, j, k;
    outcome result;
-   double tol = 1e-3;
+   double tol;
+   if(tol_in)
+     tol = *tol_in;
+   else
+     tol = GEOMETRY_RESABS;
+//   double tol = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+   double tol_sq = tol*tol;
    //CubitStatus status = CUBIT_SUCCESS;
 
    CubitVector* vector_ptr;
@@ -12926,6 +14642,14 @@
   DLIList<ENTITY*> new_ENTITIES;
   DLIList<ENTITY*> att_ENTITIES;
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( body_list, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
    body_list.reset();
    for( i=0; i<body_list.size(); i++ )
    {
@@ -12938,10 +14662,6 @@
       // Copy the body before working with it
       copied_BODY_ptr = copy_BODY( BODY_ptr, delete_attribs );
 
-      // Get all the vertices of the BODY
-      DLIList<VERTEX*> VERTEX_list;
-      AcisQueryEngine::instance()->get_VERTICEs( (ENTITY*)BODY_ptr, VERTEX_list );
-
       // Get all the FACES of the *original* BODY
       DLIList<FACE*> FACE_list;
       AcisQueryEngine::instance()->get_FACEs( (ENTITY*)BODY_ptr, FACE_list );
@@ -12953,7 +14673,13 @@
       {
          vector_ptr = vector_list.get_and_step();
          SPAposition test_point( vector_ptr->x(), vector_ptr->y(), vector_ptr->z() );
+         APOINT *apt = new APOINT(test_point);
+         VERTEX *vert = new VERTEX(apt);
 
+         // Get all the vertices of the BODY
+         DLIList<VERTEX*> VERTEX_list;
+         AcisQueryEngine::instance()->get_VERTICEs( (ENTITY*)copied_BODY_ptr, VERTEX_list );
+
          CubitBoolean on_vertex = CUBIT_FALSE;
          VERTEX_list.reset();
          for( k=0; k<VERTEX_list.size(); k++ )
@@ -12962,9 +14688,11 @@
 
             SPAposition VERTEX_coords = VERTEX_ptr->geometry()->coords();
 
-            if (( fabs(VERTEX_coords.x() - vector_ptr->x()) < tol) &&
-               ( fabs(VERTEX_coords.y() - vector_ptr->y()) < tol) &&
-               ( fabs(VERTEX_coords.z() - vector_ptr->z()) < tol))
+            CubitVector vec(VERTEX_coords.x() - vector_ptr->x(),
+                            VERTEX_coords.y() - vector_ptr->y(),
+                            VERTEX_coords.z() - vector_ptr->z());
+
+            if(vec.length_squared() < tol_sq)
             {
                on_vertex = CUBIT_TRUE;
                break; // Skip - coincident with a vertex
@@ -12972,7 +14700,10 @@
          }
 
          if( on_vertex )
+         {
+            api_del_entity(vert);
             continue; // No imprinting necessary
+         }
 
          // Get all the EDGES of the copied BODY
          DLIList<EDGE*> EDGE_list;
@@ -12989,7 +14720,34 @@
                continue; // Check next edge
 
             //const curve* acis_curve = &EDGE_ptr->geometry()->equation();
+            SPAposition vert_pos, edge_pos;
+            double dist = 0.0;
+            api_entity_entity_distance(vert, EDGE_ptr, vert_pos, edge_pos, dist);
 
+            if(dist < tol)
+            {
+              on_edge = CUBIT_TRUE;
+              VERTEX *new_vertex = ACIS_NEW VERTEX(ACIS_NEW APOINT(edge_pos));
+
+              API_BEGIN;
+              sg_split_edge_at_vertex( EDGE_ptr, new_vertex );  
+              API_END;
+
+              if( !result.ok() && result.error_number()!=200 )
+              {
+                AcisQueryEngine::instance()->ACIS_API_error(result);
+                PRINT_ERROR( "problem imprinting curve onto volume\n");
+              }
+
+              break;
+            }
+            else
+              continue;  // Check next edge
+
+
+
+
+/*
             SPAtransf ftrans;
 
             point_edge_containment pe_rel;
@@ -13018,10 +14776,14 @@
 
               break;
             }
+            */
          }
 
          if( on_edge )
+         {
+            api_del_entity(vert);
             continue; // Already imprinted onto the body - check next vertex
+         }
 
          // Check the FACES
          FACE_list.reset();
@@ -13032,6 +14794,71 @@
             if (FACE_ptr->geometry() == NULL)
                continue; // Check next face
 
+
+            SPAposition vert_pos, face_pos;
+            double dist = 0.0;
+            api_entity_entity_distance(vert, FACE_ptr, vert_pos, face_pos, dist);
+
+            if(dist < tol)
+            {
+               // Create a short curve normal to the surface at the vertex and imprint it
+               SPAunit_vector norm;
+               norm = FACE_ptr->geometry()->equation().point_normal( face_pos );
+
+               if ( FACE_ptr->sense() == REVERSED )
+                  norm = -norm;
+
+               // Find the end point
+               SPAposition end_point;
+               end_point.set_x( face_pos.x() + (0.001 * norm.x()) );
+               end_point.set_y( face_pos.y() + (0.001 * norm.y()) );
+               end_point.set_z( face_pos.z() + (0.001 * norm.z()) );
+
+               // Create the curve
+               EDGE* new_EDGE_ptr = NULL;
+               result = api_mk_ed_line ( face_pos, end_point, new_EDGE_ptr );
+               if (!result.ok() || new_EDGE_ptr == NULL)
+               {
+                  AcisQueryEngine::instance()->ACIS_API_error (result);
+                  PRINT_WARNING("Unable to make short normal curve for imprint operation\n" );
+                  continue;
+               }
+
+               // Create a wire from the short curve
+               BODY *wire_BODY_ptr = NULL;
+               result = api_make_ewire( 1, &new_EDGE_ptr, wire_BODY_ptr );
+               if (!result.ok())
+               {
+                  AcisQueryEngine::instance()->ACIS_API_error (result);
+                  PRINT_WARNING( "Unable to make ACIS WIRE from short imprint curve\n" );
+
+                  if( wire_BODY_ptr )
+                     api_delent( wire_BODY_ptr );
+                  else
+                     api_delent( new_EDGE_ptr );
+                  continue;
+               }
+
+               // Imprint the wire-body onto the BODY
+               result = api_imprint( wire_BODY_ptr, copied_BODY_ptr );
+
+               if( !result.ok() && result.error_number()!=200 )
+               {
+                  AcisQueryEngine::instance()->ACIS_API_error(result);
+                  PRINT_ERROR( "problem imprinting short curve onto volume\n");
+               }
+
+               api_delent( wire_BODY_ptr );
+
+               break; // Done imprinting with this vertex
+
+            }
+            else
+              continue; // Check next face
+
+
+
+/*
             SPAtransf ftrans;
 
             point_face_containment pf_rel = point_in_face( test_point, FACE_ptr, ftrans );
@@ -13048,9 +14875,9 @@
 
                // Find the end point
                SPAposition end_point;
-               end_point.set_x( test_point.x() + (tol * norm.x()) );
-               end_point.set_y( test_point.y() + (tol * norm.y()) );
-               end_point.set_z( test_point.z() + (tol * norm.z()) );
+               end_point.set_x( test_point.x() + (0.001 * norm.x()) );
+               end_point.set_y( test_point.y() + (0.001 * norm.y()) );
+               end_point.set_z( test_point.z() + (0.001 * norm.z()) );
 
                // Create the curve
                EDGE* new_EDGE_ptr = NULL;
@@ -13098,10 +14925,13 @@
             }
             else if( pf_rel == point_unknown_face )
                continue; // Check next face
+               */
          }
+         api_del_entity(vert);
       }
 
-      AcisModifyEngine::instance()->cleanup_slivers( copied_BODY_ptr );
+      if(clean_up_slivers)
+        AcisModifyEngine::instance()->cleanup_slivers( copied_BODY_ptr );
 
       // Get the new entities (just edges for now)
       // created by the imprint operation.
@@ -13131,9 +14961,11 @@
         if(att_tbs)
           get_att_ENTITIES(BODY_ptr, att_ENTITIES, "COMPOSITE_GEOM");
       }
-
    }
 
+   if( GeometryQueryTool::instance()->history().is_tracking() )
+     AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+
     // Convert the new_ENTITIES/att_ENTITIES lists into
     // topology bridge lists.
     if(new_tbs)
@@ -13354,6 +15186,44 @@
   return CUBIT_SUCCESS;
 }
 
+CubitStatus
+AcisModifyEngine::split_curve( Curve* curve_to_split,
+							   const CubitVector& split_location,
+							   DLIList<Curve*>& created_curves )
+{
+	//Expose api_split_curve to Cubit
+	EDGE* EDGE_ptr = AcisQueryEngine::get_EDGE( curve_to_split );
+	if( EDGE_ptr == NULL )
+		return CUBIT_FAILURE;
+
+	SPAposition split_position( split_location.x() , split_location.y() , split_location.z() );
+	EDGE* cutting_EDGE = NULL;
+	ENTITY* new_ENT = NULL;
+	ENTITY_LIST new_ENTs;
+
+	//call api function
+    outcome result = api_split_curve( EDGE_ptr, &split_position , cutting_EDGE , new_ENTs );
+	if( !result.ok() )
+    {
+		AcisQueryEngine::instance()->ACIS_API_error (result);
+		PRINT_ERROR( "Unable to split curve\n" );
+		return CUBIT_FAILURE;
+	}
+	if( new_ENTs.count() == 0 )
+	{
+		PRINT_ERROR( "Split curves not created\n" );
+		return CUBIT_FAILURE;
+	}
+	for(int i=0; i < new_ENTs.count(); i++)
+    {
+	  new_ENT = static_cast<EDGE*>(new_ENTs[i]);
+      Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges((EDGE*)new_ENT);
+      if(new_curve)
+        created_curves.append(new_curve);
+    }
+	return CUBIT_SUCCESS;
+}
+
 Curve*
 AcisModifyEngine::trim_curve( Curve* trim_curve,
                               const CubitVector& trim_vector,
@@ -13753,6 +15623,12 @@
   // to the RefFace's).
   copied_BODY_ptr = copy_BODY(BODY_ptr, CUBIT_FALSE);
 
+  if (!copied_BODY_ptr)
+  {
+      PRINT_ERROR( "Unable to copy ACIS body.\n" );
+      return CUBIT_FAILURE;
+  }
+
   // Loop through the copied BODY's FACES to find which one's
   // match to the original BODY's RefFaces.
   ENTITY_LIST ENTITIES;
@@ -13818,6 +15694,219 @@
 }
 
 CubitStatus
+AcisModifyEngine::get_copied_FACES_and_EDGES_of_body( DLIList<SurfaceACIS*>& ref_face_list,
+                                                      DLIList<CurveACIS*>& ref_edge_list,
+                                                      DLIList<FACE*>& FACE_list,
+                                                      DLIList<EDGE*>& EDGE_list,
+                                                      DLIList<SurfaceACIS*>& removed_ref_faces,
+                                                      DLIList<CurveACIS*>& removed_ref_edges,
+                                                      BODY*& copied_BODY_ptr ) const
+{
+  int i, num_faces, num_edges;
+
+  // Note: we will be pulling surfaces/curves out of incoming ref_face_list/ref_edge_list.
+  SurfaceACIS* ref_face_ptr;
+  CurveACIS* ref_edge_ptr;
+
+  BODY *BODY_ptr;
+  BODY *BODY_ptr2;
+
+  copied_BODY_ptr = NULL;
+
+  outcome result;
+
+  DLIList<SurfaceACIS*> body_face_list;
+  DLIList<CurveACIS*> body_edge_list;
+
+  ref_face_list.reset();
+  ref_edge_list.reset();
+
+  if(ref_face_list.size())
+  {
+    BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_entity( ref_face_list.get() );
+    if( BODY_ptr == NULL )
+    {
+      PRINT_ERROR( "Unable to get volume from FACE\n" );
+      return CUBIT_FAILURE;
+    }
+  }
+  else if(ref_edge_list.size())
+  {
+    BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_entity( ref_edge_list.get() );
+    if( BODY_ptr == NULL )
+    {
+      PRINT_ERROR( "Unable to get volume from EDGE\n" );
+      return CUBIT_FAILURE;
+    }
+  }
+
+  // Add all remaining faces from this same body to face list
+  num_faces = ref_face_list.size();
+  for( i=0; i<num_faces; i++ )
+  {
+    ref_face_ptr = ref_face_list.get();
+
+    BODY_ptr2 = AcisQueryEngine::instance()->get_BODY_of_entity( ref_face_ptr );
+
+    if( BODY_ptr == BODY_ptr2 )
+    {
+      body_face_list.append_unique( ref_face_ptr );
+      ref_face_list.remove();
+      removed_ref_faces.append( ref_face_ptr );
+    }
+    else
+      ref_face_list.step();
+  }
+  // Add all remaining faces from this same body to face list
+  num_edges = ref_edge_list.size();
+  for( i=0; i<num_edges; i++ )
+  {
+    ref_edge_ptr = ref_edge_list.get();
+
+    BODY_ptr2 = AcisQueryEngine::instance()->get_BODY_of_entity( ref_edge_ptr );
+
+    if( BODY_ptr == BODY_ptr2 )
+    {
+      body_edge_list.append_unique( ref_edge_ptr );
+      ref_edge_list.remove();
+      removed_ref_edges.append( ref_edge_ptr );
+    }
+    else
+      ref_edge_list.step();
+  }
+
+  // Now we have all the faces and edges from this particular BODY.
+
+  // Copy the body before working with it.  Here we keep the
+  // attributes on the BODY so we can get back to the TE's
+  // in CUBIT from the copy (to find which FACE's to correlate
+  // to the RefFace's).
+  copied_BODY_ptr = copy_BODY(BODY_ptr, CUBIT_FALSE);
+
+  // Loop through the copied BODY's FACES to find which one's
+  // match to the original BODY's RefFaces.
+  ENTITY_LIST ENTITIES;
+  result = api_get_faces( copied_BODY_ptr, ENTITIES );
+  if( !result.ok() )
+  {
+    PRINT_ERROR( "Unable to get ACIS FACES from volume\n" );
+    api_delent( copied_BODY_ptr );
+    copied_BODY_ptr = NULL;
+    return CUBIT_FAILURE;
+  }
+
+  ENTITIES.init();
+  ENTITY* ENTITY_ptr;
+  int index = -1;
+  DLIList<int> index_list;
+  DLIList<FACE*> temp_FACE_list;
+  while( (ENTITY_ptr = ENTITIES.next() ) != NULL )
+  {
+    AcisBridge* ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITY_ptr);
+    ref_face_ptr = CAST_TO( ab_ptr, SurfaceACIS );
+    if( ref_face_ptr == NULL )
+    {
+      PRINT_ERROR( "Unable to find RefFace from ACIS FACE!\n" );
+      api_delent( copied_BODY_ptr );
+      copied_BODY_ptr = NULL;
+      return CUBIT_FAILURE;
+    }
+
+    index = body_face_list.where_is_item( ref_face_ptr );
+    if( index != -1 )
+    {
+      index_list.append( index );
+      temp_FACE_list.append( (FACE *)ENTITY_ptr );
+    }
+    if( temp_FACE_list.size() == body_face_list.size() )
+      break;
+  }
+  ENTITIES.clear();
+
+  if( temp_FACE_list.size() != body_face_list.size() )
+  {
+    PRINT_ERROR( "Internal error correlating FACE lists\n" );
+    api_delent( copied_BODY_ptr );
+    copied_BODY_ptr = NULL;
+    return CUBIT_FAILURE;
+  }
+
+  // Re-sort the list into the proper order
+  temp_FACE_list.reset();
+  index_list.reset();
+  for( i=0; i<index_list.size(); i++ )
+  {
+    // Find the FACE with the corresponding index
+    index = index_list.where_is_item( i );
+    temp_FACE_list.reset();
+    temp_FACE_list.step( index );
+
+    FACE_list.append( temp_FACE_list.get() );
+  }
+
+  // Loop through the copied BODY's EDGES to find which one's
+  // match to the original BODY's RefEdges.
+  ENTITIES.clear();
+  result = api_get_edges( copied_BODY_ptr, ENTITIES );
+  if( !result.ok() )
+  {
+    PRINT_ERROR( "Unable to get ACIS EDGES from volume\n" );
+    api_delent( copied_BODY_ptr );
+    copied_BODY_ptr = NULL;
+    return CUBIT_FAILURE;
+  }
+
+  ENTITIES.init();
+  index = -1;
+  index_list.clean_out();
+  DLIList<EDGE*> temp_EDGE_list;
+  while( (ENTITY_ptr = ENTITIES.next() ) != NULL )
+  {
+    AcisBridge* ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITY_ptr);
+    ref_edge_ptr = CAST_TO( ab_ptr, CurveACIS );
+    if( ref_edge_ptr == NULL )
+    {
+      PRINT_ERROR( "Unable to find RefEdge from ACIS EDGE!\n" );
+      api_delent( copied_BODY_ptr );
+      copied_BODY_ptr = NULL;
+      return CUBIT_FAILURE;
+    }
+
+    index = body_edge_list.where_is_item( ref_edge_ptr );
+    if( index != -1 )
+    {
+      index_list.append( index );
+      temp_EDGE_list.append( (EDGE *)ENTITY_ptr );
+    }
+    if( temp_EDGE_list.size() == body_edge_list.size() )
+      break;
+  }
+  ENTITIES.clear();
+
+  if( temp_EDGE_list.size() != body_edge_list.size() )
+  {
+    PRINT_ERROR( "Internal error correlating EDGE lists\n" );
+    api_delent( copied_BODY_ptr );
+    copied_BODY_ptr = NULL;
+    return CUBIT_FAILURE;
+  }
+
+  // Re-sort the list into the proper order
+  temp_EDGE_list.reset();
+  index_list.reset();
+  for( i=0; i<index_list.size(); i++ )
+  {
+    // Find the FACE with the corresponding index
+    index = index_list.where_is_item( i );
+    temp_EDGE_list.reset();
+    temp_EDGE_list.step( index );
+
+    EDGE_list.append( temp_EDGE_list.get() );
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus
 AcisModifyEngine::get_copied_FACES_of_body( DLIList<SurfaceACIS*>& ref_face_list,
                                               DLIList<FACE*>& FACE_list,
                                               BODY*& copied_BODY_ptr ) const
@@ -14670,9 +16759,7 @@
 
 CubitStatus AcisModifyEngine::scale( BodySM *&body, const CubitVector& f )
 {
-#if CUBIT_ACIS_VERSION < 1100
-  api_initialize_operators();
-#elif defined(WIN32) || defined(MACOSX)
+#if defined(WIN32) || defined(MACOSX)
   api_initialize_warp();
 #endif
    BODY *new_BODY = NULL;
@@ -14688,9 +16775,7 @@
 
   CubitStatus result = AcisQueryEngine::instance()->transform( new_BODY, scale_transf( f.x(), f.y(), f.z() ) );
 
-#if CUBIT_ACIS_VERSION < 1100
-  api_terminate_operators();
-#elif defined(WIN32) || defined(MACOSX)
+#if defined(WIN32) || defined(MACOSX)
   api_terminate_warp();
 #endif
 
@@ -14705,9 +16790,9 @@
 }
 
 CubitStatus AcisModifyEngine::tolerant_imprint( DLIList<BodySM*> &bodies_in,
-                                                 DLIList<BodySM*> &new_bodies,
-                                                  DLIList<TopologyBridge*> *new_tbs,
-                                                  DLIList<TopologyBridge*> *att_tbs ) const
+                                                DLIList<BodySM*> &new_bodies,
+                                                DLIList<TopologyBridge*> *new_tbs,
+                                                DLIList<TopologyBridge*> *att_tbs ) const
 {
   //make sure all bodies are from the same modify engine
   DLIList<BodySM*> new_body_list;
@@ -14719,56 +16804,53 @@
      progress_tool->start(0, 100, "Tolerant Imprinting" );
   }
 
+  AcisHistory history_object;
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+  {
+    DLIList<TopologyBridge*> my_bridges;
+    CAST_LIST( bodies_in, my_bridges, TopologyBridge );
+    AcisModifyEngine::instance()->start_tracking_history( my_bridges, history_object ); 
+  }
+
   CubitStatus status = imprint_overlapping_curves( bodies_in, new_body_list, progress_tool );
 
   status = imprint_overlapping_surfaces( bodies_in, new_body_list, progress_tool );
 
   status = imprint_overlapping_curves( bodies_in, new_body_list, progress_tool, new_tbs, att_tbs );
+ 
+  //clear out bounding boxes
+  int i;
+  for( i=new_body_list.size(); i--; )
+  {
+    BodyACIS *body_acis = dynamic_cast<BodyACIS*>( new_body_list.get_and_step() );
+    if( body_acis )
+    {
+      BODY *acis_BODY = body_acis->get_BODY_ptr();
+      AcisQueryEngine::instance()->clear_bounding_box( acis_BODY );
+    }
+  }
 
+  if( GeometryQueryTool::instance()->history().is_tracking() )
+    AcisModifyEngine::instance()->stop_tracking_history( new_body_list, history_object ); 
+
   if( progress_tool )
     progress_tool->end();
 
   return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisModifyEngine::imprint_overlapping_curves( DLIList<BodySM*> &body_sms,
-                                                          DLIList<BodySM*> &new_body_sms,
-                                                          ProgressTool *progress_tool,
-                                                          DLIList<TopologyBridge*> *new_tbs,
-                                                          DLIList<TopologyBridge*> *att_tbs ) const
+CubitStatus AcisModifyEngine::imprint_overlapping_curves( 
+      DLIList< DLIList<Curve*>* > &lists_of_mergeable_curves,
+      DLIList< DLIList<Curve*>* > &lists_of_overlapping_curves,
+      std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+      std::multimap<BodySM*, CubitVector> &body_vertex_imprint_map,
+      DLIList<BodySM*> &new_body_sms,
+      ProgressTool *progress_tool,
+      DLIList<TopologyBridge*> *new_tbs,
+      DLIList<TopologyBridge*> *att_tbs ) const
 {
-  //find all mergeable curves between the bodies
-  CubitStatus status;
-#ifdef BOYD16
-  DLIList<RefEntity*> entities;
-#endif
-  DLIList< DLIList<Curve*>* > lists_of_mergeable_curves;
+  int i, j;
 
-  status = MergeTool::instance()->find_only_mergeable_curves( body_sms, lists_of_mergeable_curves );
-  
-  int i,j;
-  //increment 4%
-  if( progress_tool )
-  {
-    for( i=4; i--; )
-      progress_tool->step();
-  }
-
-  //find all overlapping curves between the bodies
-  std::map<Curve*, DLIList<Curve*>* > curve_to_list_map;
-  DLIList< DLIList<Curve*>* > lists_of_overlapping_curves;
-  //for each list, curves 2-n overlap the first curve
-  
-  SurfaceOverlapTool::instance()->find_overlapping_curves( body_sms, lists_of_overlapping_curves,
-                                                           curve_to_list_map );
-
-  //increment 8%
-  if( progress_tool )
-  {
-    for( i=9; i--; )
-      progress_tool->step();
-  }
-
   //remove idential groups and sub-groups of mergeable curves from
   //overlapping groups.  For example:  If curves A,B,C,D are in a mergeable group
   //the following groups will have no need for imprinting, becasue the curves are
@@ -14849,14 +16931,14 @@
 
   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
 
-  DLIList<BodySM*> imprint_body_order;
+  //DLIList<BodySM*> imprint_body_order;
   lists_of_overlapping_curves.reset();
   //Now setup multi-map for imprinting vertices onto bodies
   //This is how the curve - vertex imprinting should be done:
   // -imprint vertices of curve 1 in list onto curves 2 - n
   // -imprint vertcies of curve 2 - n onto curve 1
-  std::multimap<BodySM*, CubitVector* > body_point_imprint_map;
-  std::multimap<BodySM*, CubitVector* >::iterator tmp_iter, upper_iter;
+  std::multimap<BodySM*, CubitVector > body_point_imprint_map;
+  std::multimap<BodySM*, CubitVector >::iterator tmp_iter, upper_iter;
 
   for( i=lists_of_overlapping_curves.size(); i--; )
   {
@@ -14865,7 +16947,9 @@
     Curve *first_curve = curve_list->get_and_step();
 
     DLIList<Point*> curve_1_points;
-    first_curve->points( curve_1_points );
+    DLIList<TopologyBridge*> tmp_tb_list;
+    first_curve->get_children_virt(tmp_tb_list);
+    CAST_LIST(tmp_tb_list, curve_1_points, Point);
     Point *s_point1 = curve_1_points.get_and_step();
     Point *e_point1 = curve_1_points.get_and_step();
 
@@ -14874,8 +16958,11 @@
     while( curve_list->size() > 1 )
     {
       Curve *other_curve = curve_list->pop();
+      
       DLIList<Point*> curve_2_points;
-      other_curve->points( curve_2_points );
+      tmp_tb_list.clean_out();
+      other_curve->get_children_virt(tmp_tb_list);
+      CAST_LIST(tmp_tb_list, curve_2_points, Point);
       Point *s_point2 = curve_2_points.get_and_step();
       Point *e_point2 = curve_2_points.get_and_step();
 
@@ -14885,7 +16972,8 @@
       first_curve->closest_point_trimmed( s_point2->coordinates(), close_pt );
 
       if( close_pt.distance_between( s_point1->coordinates() ) > tolerance &&
-          close_pt.distance_between( e_point1->coordinates() ) > tolerance )
+          close_pt.distance_between( e_point1->coordinates() ) > tolerance &&
+          close_pt.distance_between( s_point2->coordinates() ) <= tolerance )
       {
         //are there any other points within tolerance to this point
         //to be imprinted onto this body?
@@ -14893,34 +16981,33 @@
         bool consider_point = true;
         if( tmp_iter != body_point_imprint_map.end() )
         {
-          CubitVector *tmp_vec = tmp_iter->second;
+          CubitVector tmp_vec = tmp_iter->second;
           upper_iter = body_point_imprint_map.upper_bound( tmp_iter->first );
           
           for(; tmp_iter!=upper_iter; ++tmp_iter)
           {
             tmp_vec = tmp_iter->second;
-            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            if( close_pt.distance_between( tmp_vec ) < tolerance )
             {
               consider_point = false;
               break;
             }
           }
         }
-
+        
         if( consider_point ) 
         {
           //imprint body of curve1 with vertex at this location
-          CubitVector *tmp_vec = new CubitVector( close_pt );
           body_point_imprint_map.insert( std::multimap<BodySM*,
-              CubitVector*>::value_type( first_curve_body, tmp_vec ));
-          imprint_body_order.append_unique( first_curve_body );
+              CubitVector>::value_type( first_curve_body, close_pt ));
         }
       }
 
       first_curve->closest_point_trimmed( e_point2->coordinates(), close_pt );
 
       if( close_pt.distance_between( s_point1->coordinates() ) > tolerance &&
-          close_pt.distance_between( e_point1->coordinates() ) > tolerance )
+          close_pt.distance_between( e_point1->coordinates() ) > tolerance &&
+          close_pt.distance_between( e_point2->coordinates() ) <= tolerance )
       {
         //are there any other points within tolerance to this point
         //to be imprinted onto this body?
@@ -14928,13 +17015,13 @@
         bool consider_point = true;
         if( tmp_iter != body_point_imprint_map.end() )
         {
-          CubitVector *tmp_vec = tmp_iter->second;
+          CubitVector tmp_vec = tmp_iter->second;
           upper_iter = body_point_imprint_map.upper_bound( tmp_iter->first );
           
           for(; tmp_iter!=upper_iter; ++tmp_iter)
           {
             tmp_vec = tmp_iter->second;
-            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            if( close_pt.distance_between( tmp_vec ) < tolerance )
             {
               consider_point = false;
               break;
@@ -14945,17 +17032,16 @@
         if( consider_point ) 
         {
           //imprint body of curve1 with vertex at this location
-          CubitVector *tmp_vec = new CubitVector( close_pt );
           body_point_imprint_map.insert( std::multimap<BodySM*,
-              CubitVector*>::value_type( first_curve_body, tmp_vec ));
-          imprint_body_order.append_unique( first_curve_body );
+              CubitVector>::value_type( first_curve_body, close_pt ));
         }
       }
 
       other_curve->closest_point_trimmed( s_point1->coordinates(), close_pt );
 
       if( close_pt.distance_between( s_point2->coordinates() ) > tolerance &&
-          close_pt.distance_between( e_point2->coordinates() ) > tolerance )
+          close_pt.distance_between( e_point2->coordinates() ) > tolerance && 
+          close_pt.distance_between( s_point1->coordinates() ) <= tolerance )
       {
         //are there any other points within tolerance to this point
         //to be imprinted onto this body?
@@ -14963,13 +17049,13 @@
         bool consider_point = true;
         if( tmp_iter != body_point_imprint_map.end() )
         {
-          CubitVector *tmp_vec = tmp_iter->second;
+          CubitVector tmp_vec = tmp_iter->second;
           upper_iter = body_point_imprint_map.upper_bound( tmp_iter->first );
           
           for(; tmp_iter!=upper_iter; ++tmp_iter)
           {
             tmp_vec = tmp_iter->second;
-            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            if( close_pt.distance_between( tmp_vec ) < tolerance )
             {
               consider_point = false;
               break;
@@ -14980,17 +17066,16 @@
         if( consider_point ) 
         {
           //imprint body of curve1 with vertex at this location
-          CubitVector *tmp_vec = new CubitVector( close_pt );
           body_point_imprint_map.insert( std::multimap<BodySM*,
-              CubitVector*>::value_type( other_curve_body, tmp_vec ));
-          imprint_body_order.append_unique( other_curve_body );
+              CubitVector>::value_type( other_curve_body, close_pt ));
         }
       }
 
       other_curve->closest_point_trimmed( e_point1->coordinates(), close_pt );
 
       if( close_pt.distance_between( s_point2->coordinates() ) > tolerance &&
-          close_pt.distance_between( e_point2->coordinates() ) > tolerance )
+          close_pt.distance_between( e_point2->coordinates() ) > tolerance &&
+          close_pt.distance_between( e_point1->coordinates() ) <= tolerance )
       {
         //Are there already any other points within tolerance to this point
         //to be imprinted onto this body?
@@ -14999,13 +17084,13 @@
         bool consider_point = true;
         if( tmp_iter != body_point_imprint_map.end() )
         {
-          CubitVector *tmp_vec = tmp_iter->second;
+          CubitVector tmp_vec = tmp_iter->second;
           upper_iter = body_point_imprint_map.upper_bound( tmp_iter->first );
           
           for(; tmp_iter!=upper_iter; ++tmp_iter )
           {
             tmp_vec = tmp_iter->second;
-            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            if( close_pt.distance_between( tmp_vec ) < tolerance )
             {
               consider_point = false;
               break;
@@ -15016,39 +17101,67 @@
         if( consider_point ) 
         {
           //imprint body of curve1 with vertex at this location
-          CubitVector *tmp_vec = new CubitVector( close_pt );
           body_point_imprint_map.insert( std::multimap<BodySM*,
-              CubitVector*>::value_type( other_curve_body, tmp_vec ));
-          imprint_body_order.append_unique( other_curve_body );
+              CubitVector>::value_type( other_curve_body, close_pt ));
         }
       }
     }
   }
 
+  //append only unique positions 
+  std::multimap<BodySM*, CubitVector >::iterator iter;
+  iter = body_vertex_imprint_map.begin();
+  for(; iter != body_vertex_imprint_map.end(); iter++  )
+  {
+    BodySM *tmp_body_sm = iter->first;
+    CubitVector tmp_vec1 = iter->second;
+    bool consider_point = true;
+    
+    std::pair< std::multimap<BodySM*, CubitVector >::iterator,
+               std::multimap<BodySM*, CubitVector >::iterator > body_position_pair;
+
+    body_position_pair = body_point_imprint_map.equal_range( tmp_body_sm );
+
+    tmp_iter = body_position_pair.first; 
+    upper_iter = body_position_pair.second; 
+    for(; tmp_iter!=upper_iter; ++tmp_iter)
+    {
+      CubitVector tmp_vec2 = tmp_iter->second;
+      if( tmp_vec1.distance_between( tmp_vec2 ) < tolerance )
+      {
+        consider_point = false;
+        break;
+      }
+    }
+
+    if( consider_point )
+    {
+      body_point_imprint_map.insert( std::multimap<BodySM*,
+          CubitVector>::value_type( tmp_body_sm, tmp_vec1 ));
+    }
+  } 
+
   //Imprint Vertices-onto-Body
-  imprint_body_order.reset();
-  std::multimap<BodySM*, CubitVector*>::iterator point_iter, last_point_iter;
-  for( i=imprint_body_order.size(); i--; )
+  std::multimap<BodySM*, CubitVector>::iterator point_iter, last_point_iter, tmp_upper_iter;
+  point_iter = body_point_imprint_map.begin();
+  last_point_iter = body_point_imprint_map.end();
+  for(; point_iter != last_point_iter; )  
   {
-    BodySM *tmp_body_sm = imprint_body_order.get_and_step();
-    DLIList<BodySM*> body_to_imprint;
+    BodySM *tmp_body_sm = point_iter->first; 
+    DLIList<BodySM*> body_to_imprint(1);
     body_to_imprint.append( tmp_body_sm );
 
-    DLIList<CubitVector*> points_to_imprint;
-
     point_iter = body_point_imprint_map.find( tmp_body_sm );
-    last_point_iter = body_point_imprint_map.upper_bound( point_iter->first );
+    tmp_upper_iter = body_point_imprint_map.upper_bound( point_iter->first );
 
-    for(; point_iter!=last_point_iter; ++point_iter )
-      points_to_imprint.append( point_iter->second );
+    DLIList<CubitVector*> points_to_imprint;
+    for(; point_iter!=tmp_upper_iter; ++point_iter )
+      points_to_imprint.append( &(point_iter->second) );
 
     DLIList<BodySM*> new_bodies;
-    CubitStatus status = imprint( body_to_imprint, points_to_imprint, new_bodies, false, new_tbs, att_tbs );
+    imprint( body_to_imprint, points_to_imprint, new_bodies, false, new_tbs, att_tbs, &tolerance, false);
     if( new_bodies.size() )
       new_body_sms.append( new_bodies.get() );
-
-    for( j=points_to_imprint.size(); j--; )
-      delete points_to_imprint.get_and_step();
   }
 
   //increment 4%
@@ -15061,47 +17174,15 @@
   return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisModifyEngine::imprint_overlapping_surfaces( DLIList<BodySM*> &body_sms,
-                                                            DLIList<BodySM*> &new_body_sms,
-                                                            ProgressTool *progress_tool) const
-{
-  //Find all mergeable surfaces between the bodies
-  DLIList< DLIList<Surface*>* > lists_of_mergeable_surfaces;
-  CubitStatus status = MergeTool::instance()->
-      find_only_mergeable_surfaces( body_sms, lists_of_mergeable_surfaces );
 
-  if( progress_tool )
-    progress_tool->percent( 0.24 );
 
-  //Find all overlapping surfaces between the bodies
-  DLIList<Surface*> overlapping_surfaces1;
-  DLIList<Surface*> overlapping_surfaces2;
-  SurfaceOverlapTool::instance()->
-    find_overlapping_surfaces( body_sms, overlapping_surfaces1, overlapping_surfaces2 );
-
-  if( progress_tool )
-    progress_tool->percent( 0.57 );
-
-  //We only want the non-mergeable overlapping surfaces.
-  //Remove mergable surfaces from overlapping pairs.
+CubitStatus AcisModifyEngine::imprint_overlapping_surfaces(DLIList<Surface*> &overlapping_surfaces1,
+                                                           DLIList<Surface*> &overlapping_surfaces2,
+                                                           DLIList<BodySM*> &new_body_sms,
+                                                           ProgressTool *progress_tool,
+                                                           DLIList<Surface*> *new_surface_list) const
+{
   int i, j, k;
-  for( i=lists_of_mergeable_surfaces.size(); i--; )
-  {
-    DLIList<Surface*> *tmp_surface_list = lists_of_mergeable_surfaces.get_and_step();
-    for( j=tmp_surface_list->size(); j--; )
-    {
-      Surface *tmp_surface = tmp_surface_list->get_and_step();
-      while( overlapping_surfaces1.move_to( tmp_surface ) )
-        overlapping_surfaces1.change_to(NULL);
-      while( overlapping_surfaces2.move_to( tmp_surface ) )
-        overlapping_surfaces2.change_to(NULL);
-    }
-    delete tmp_surface_list;
-  }
-
-  if( progress_tool )
-    progress_tool->percent( 0.59 );
-
   //Surface A might be mergeable/overlapping with B and just ever-so-slightly
   //overlapping with C. Get rid of C or other overlapping surfaces
   //that might be in the list.
@@ -15265,6 +17346,9 @@
     //Get bounding box for later
     CubitBox bb_surf = overlapping_surface1->bounding_box();
 
+    CubitSense dummy_sense;
+    double geo_factor = GeometryQueryTool::get_geometry_factor();
+
     //remove overlapping curves between the 2 surfaces
     for( j=curves2.size(); j--; )
     {
@@ -15278,19 +17362,18 @@
         {
           Curve *tmp_curve_2 = curves1.get();
 
-          if( SurfaceOverlapTool::instance()->
-            check_overlap( tmp_curve, tmp_curve_2, NULL))
+          if((tmp_curve->bridge_manager() &&
+              tmp_curve->bridge_manager() == tmp_curve_2->bridge_manager()) ||
+              MergeTool::instance()->about_spatially_equal( tmp_curve, tmp_curve_2,
+                      dummy_sense, geo_factor)  
+              || 
+              SurfaceOverlapTool::instance()->
+              check_overlap( tmp_curve, tmp_curve_2, NULL) )
           {
-            //They should be about spatially equal too!
-//            CubitSense dummy_sense;
-//            if( MergeTool::instance()->about_spatially_equal( curves1.get(), curves2.get(),
-//                      dummy_sense, GeometryQueryTool::get_geometry_factor() ) )
-//            {
               curves1.change_to(NULL);
               curves2.change_to(NULL);
               overlap = true;
               break;
-//            }
           }
         }
         curves1.step();
@@ -15332,7 +17415,11 @@
               break;
             }
 
-            if( SurfaceOverlapTool::instance()->check_overlap( iter->second, tmp_curve, NULL ) )
+            if((tmp_curve->bridge_manager() &&
+                tmp_curve->bridge_manager() == iter->second->bridge_manager()) ||
+                MergeTool::instance()->about_spatially_equal( tmp_curve, iter->second,
+                        dummy_sense, geo_factor))
+        //    if( SurfaceOverlapTool::instance()->check_overlap( iter->second, tmp_curve, NULL ) )
             {
               match_found = true;
               break;
@@ -15390,7 +17477,11 @@
               break;
             }
 
-            if( SurfaceOverlapTool::instance()->check_overlap( iter->second, tmp_curve, NULL ) )
+            if((tmp_curve->bridge_manager() &&
+                tmp_curve->bridge_manager() == iter->second->bridge_manager()) ||
+                MergeTool::instance()->about_spatially_equal( tmp_curve, iter->second,
+                        dummy_sense, geo_factor))
+//            if( SurfaceOverlapTool::instance()->check_overlap( iter->second, tmp_curve, NULL ) )
             {
               match_found = true;
               break;
@@ -15405,7 +17496,6 @@
                                 overlapping_surface2, tmp_curve ));
             surface_ordering_list.append_unique( overlapping_surface2 );
           }
-
         }
       }
       curves1.step();
@@ -15445,9 +17535,8 @@
       percentage_per_surface = 0.16 / surface_ordering_list.size();
     else
       progress_tool->percent( 0.83 );
-
   }
-
+  double same_pos_tol_sq = GEOMETRY_RESABS*GEOMETRY_RESABS;
   //Now iterate of each surface that will be imprinted with curves.
   surface_ordering_list.reset();
   bool print_errors = false;
@@ -15471,46 +17560,139 @@
     surf_curve_last = final_surface_curve_imprint_map.upper_bound( surf_curve_iter->first );
     //For each curve that might be imprinted on the surface...
 
-     for(; surf_curve_iter!=surf_curve_last; ++surf_curve_iter )
-     {
-       DLIList<Curve*> tmp_curve_list1, tmp_curve_list2; 
-       Curve *original_curve = surf_curve_iter->second;
-       tmp_curve_list1.append( original_curve ); 
+    for(; surf_curve_iter!=surf_curve_last; ++surf_curve_iter )
+    {
+      DLIList<Curve*> tmp_curve_list1, tmp_curve_list2; 
+      Curve *original_curve = surf_curve_iter->second;
+      Curve *projected_curve = NULL;
 
-       //project
-       CubitStatus projected = project_edges( surface_list, tmp_curve_list1, tmp_curve_list2, print_errors );
 
-       if( projected == CUBIT_FAILURE )
-       {
-         AcisQueryEngine::instance()->delete_solid_model_entities( original_curve );
-         continue;
-       }
- 
-       Curve *projected_curve = tmp_curve_list2.get(); 
-       
-       //if midpoint of projected is far from original curve, continue 
-       CubitVector original_curve_mid_point = original_curve->center_point();
-       if( original_curve_mid_point.distance_between( projected_curve->center_point() ) > tolerance ) 
-       {
-         AcisQueryEngine::instance()->delete_solid_model_entities( original_curve );
-         AcisQueryEngine::instance()->delete_solid_model_entities( projected_curve );
-         continue;
-       }
-        
-       //now intersect
-       tmp_curve_list1.clean_out();
-       CubitStatus intersected =  curve_surface_intersection( tmp_surface, projected_curve, tmp_curve_list1 ); 
-      
-       //delete the curves
-       AcisQueryEngine::instance()->delete_solid_model_entities( original_curve );
-       AcisQueryEngine::instance()->delete_solid_model_entities( projected_curve );
+      // Ideally, we would always just project to the surface, intersect with the
+      // surface (trim to surface), and then imprint the resulting curve(s) onto
+      // the surface.  However, becuase of defficiencies in ACIS the projection
+      // and intersection are often flakey.  Projecting when you don't need to
+      // can cause problems and often times the intersection fails depending on
+      // whether you have projected or not.  So, we will try to dance around these
+      // bugs in ACIS and get something that works.
+      bool need_to_project = false;
+      DLIList<Curve*> final_curves_to_imprint;
 
-       if( intersected  == CUBIT_FAILURE) 
-         continue;
-       
-       curves_to_imprint += tmp_curve_list1;
-     }
+      // Check if it looks like we really need to project this curve or whether
+      // it appears to already be on the surface.
+      CubitVector pt_in, pt_out;
+      DLIList<double> params;
+      double start_param = original_curve->start_param();
+      double end_param = original_curve->end_param();
+      double range = end_param-start_param;
+      params.append(start_param + .2 * range);
+      params.append(start_param + .55 * range);
+      params.append(start_param + .87 * range);
+      int g;
+      for(g=params.size(); g>0 && !need_to_project; g--)
+      {
+        double cur_param = params.get_and_step();
+        original_curve->position_from_u(cur_param, pt_in);
+        tmp_surface->closest_point(pt_in, &pt_out);
+        if((pt_in-pt_out).length_squared() > same_pos_tol_sq)
+          need_to_project = true;
+      }
 
+      // If it doens't look like we need to project, attempt the curve surface intersection with 
+      // the original curve.  If this fails we will try projecting first and then doing the 
+      // intersection with the projected curve.
+      if(!need_to_project)
+      {
+        // Try to intersect.
+        tmp_curve_list1.clean_out();
+        curve_surface_intersection( tmp_surface, original_curve, tmp_curve_list1 ); 
+
+        // If we didn't get an intersection with the original curve attempt to project to
+        // see if this helps.
+        if(tmp_curve_list1.size() == 0)
+        {
+          tmp_curve_list1.clean_out();
+          tmp_curve_list1.append(original_curve); 
+          CubitStatus projected = project_edges( surface_list, tmp_curve_list1, tmp_curve_list2, print_errors );
+          if( projected == CUBIT_FAILURE )
+          {
+            // If we can't even project bail out.
+            AcisQueryEngine::instance()->delete_solid_model_entities(original_curve);
+            continue;
+          }
+          projected_curve = tmp_curve_list2.get(); 
+          //if midpoint of projected is far from original curve, continue 
+          CubitVector original_curve_mid_point = original_curve->center_point();
+          CubitVector projected_curve_mid_point = projected_curve->center_point();
+          if( original_curve_mid_point.distance_between( projected_curve_mid_point ) > tolerance ) 
+          {
+            CubitVector closest;
+            projected_curve->closest_point(original_curve_mid_point, closest);
+            if( original_curve_mid_point.distance_between( closest ) > tolerance ) 
+            {
+              AcisQueryEngine::instance()->delete_solid_model_entities( original_curve );
+              AcisQueryEngine::instance()->delete_solid_model_entities( projected_curve );
+              continue;
+            }
+          }
+
+          // Try to intersect with the projected curve.
+          tmp_curve_list1.clean_out();
+          curve_surface_intersection( tmp_surface, projected_curve, tmp_curve_list1 ); 
+          if(tmp_curve_list1.size() > 0)
+            final_curves_to_imprint = tmp_curve_list1; 
+        }
+        else
+        {
+          final_curves_to_imprint = tmp_curve_list1; 
+        }
+      }
+      else
+      {
+        // Project the curve.
+        tmp_curve_list1.clean_out();
+        tmp_curve_list1.append(original_curve); 
+        CubitStatus projected = project_edges( surface_list, tmp_curve_list1, tmp_curve_list2, print_errors );
+        if( projected == CUBIT_FAILURE )
+        {
+          // If we can't even project bail out.
+          AcisQueryEngine::instance()->delete_solid_model_entities(original_curve);
+          continue;
+        }
+        projected_curve = tmp_curve_list2.get(); 
+        //if midpoint of projected is far from original curve, continue 
+        CubitVector original_curve_mid_point = original_curve->center_point();
+        CubitVector projected_curve_mid_point = projected_curve->center_point();
+        if( original_curve_mid_point.distance_between( projected_curve_mid_point ) > tolerance ) 
+        {
+          CubitVector closest;
+          projected_curve->closest_point(original_curve_mid_point, closest);
+          if( original_curve_mid_point.distance_between( closest ) > tolerance ) 
+          {
+            AcisQueryEngine::instance()->delete_solid_model_entities( original_curve );
+            AcisQueryEngine::instance()->delete_solid_model_entities( projected_curve );
+            continue;
+          }
+        }
+
+        // Try to intersect with the projected curve.
+        tmp_curve_list1.clean_out();
+        curve_surface_intersection( tmp_surface, projected_curve, tmp_curve_list1 ); 
+        if(tmp_curve_list1.size() > 0)
+          final_curves_to_imprint = tmp_curve_list1; 
+      }
+
+      if(final_curves_to_imprint.size() == 0)
+      {
+        AcisQueryEngine::instance()->delete_solid_model_entities( original_curve );
+        if(projected_curve && projected_curve != original_curve)
+          AcisQueryEngine::instance()->delete_solid_model_entities( projected_curve );
+      }
+      else
+      {
+        curves_to_imprint += final_curves_to_imprint;
+      }
+    }
+
      //filter out small curves
      int j;
      for( j=curves_to_imprint.size(); j--; )
@@ -15542,9 +17724,33 @@
       {
         AcisDrawTool::instance()->draw_curve( curves_to_imprint.get_and_step(), kkk+5 );
         GfxDebug::mouse_xforms();
+      }    */
+
+      DLIList<Surface*> before_list;
+      if(new_surface_list)
+      {
+        BodySM *bsm = tmp_surface->bodysm();
+        if(bsm)
+        {
+          bsm->surfaces_ignore_virtual(before_list);
+          before_list.remove(tmp_surface);
+        }
       }
-*/
-      status = embed_curves_into_surface( tmp_surface, curves_to_imprint, new_body_sm );
+
+      DLIList<TopologyBridge*> temporary_bridges;
+      status = embed_curves_into_surface( tmp_surface, curves_to_imprint, temporary_bridges, new_body_sm );
+
+      if(new_surface_list && new_body_sm)
+      {
+        DLIList<Surface*> after_list;
+        new_body_sm->surfaces_ignore_virtual(after_list);
+        after_list -= before_list;
+        *new_surface_list += after_list;
+      }
+
+      temporary_bridges.uniquify_ordered();
+      while(temporary_bridges.size())
+        delete temporary_bridges.pop();
     }
 
     if( new_body_sm == NULL )
@@ -15556,21 +17762,28 @@
       AcisQueryEngine::instance()->delete_solid_model_entities( curves_to_imprint.get_and_step() );
 
   }
+
+  if(new_surface_list)
+    new_surface_list->uniquify_unordered();
+
   return CUBIT_SUCCESS;
 }
 
 
-//WARNING!!! Only use this function if you KNOW that the curves you want
-//to imprint line on the surface.....otherwise you'll get problems.
-//api_embed_wire_in_faces returns unexpected results if the curve
-//does not lie on the surface.
-CubitStatus AcisModifyEngine::embed_curves_into_surface( Surface *surface,
-                                                           DLIList<Curve*> &curves_to_imprint,
-                                                           BodySM *&new_body ) const
+CubitStatus AcisModifyEngine::tolerant_imprint_surface_with_curves(
+                                        Surface *surface,
+                                        DLIList<Curve*> &curves_to_imprint,
+                                        DLIList<TopologyBridge*> &temporary_bridges,
+                                        BodySM *&new_body,
+                                        DLIList<TopologyBridge*> *new_tbs,
+                                        DLIList<TopologyBridge*> *att_tbs  ) const
 {
   if( curves_to_imprint.size() == 0 )
     return CUBIT_FAILURE;
 
+  if( curves_to_imprint.size() == 1 )
+    return embed_curves_into_surface( surface, curves_to_imprint, temporary_bridges, new_body, new_tbs, att_tbs );
+
   BODY *copied_BODY = NULL;
   DLIList<FACE*> imprint_FACE_list;
   DLIList<SurfaceACIS*> acis_surfs;
@@ -15596,10 +17809,7 @@
 
   int i;
   EDGE *EDGEs[ 1 ];
-  ENTITY_LIST wire_BODYs;
-#ifdef BOYD16
-  outcome tmp_result;
-#endif
+  DLIList<BODY*> wire_BODYs;
   for( i=0; i<curves_to_imprint.size(); i++ )
   {
     //copy
@@ -15612,16 +17822,18 @@
     EDGEs[0] = copied_EDGE_ptr;
     BODY *tmp_BODY = NULL;
     tmp_result = api_make_ewire( 1, EDGEs, tmp_BODY );
-    wire_BODYs.add( (ENTITY*)tmp_BODY );
+    //wire_BODYs.add( (ENTITY*)tmp_BODY );
+    wire_BODYs.append( tmp_BODY );
   }
 
-  int number_wire_bodies = wire_BODYs.count();
+  int number_wire_bodies = wire_BODYs.size();
 
   if( number_wire_bodies == 0 )
     return CUBIT_FAILURE;
+  
+  wire_BODYs.reset();
+  BODY *wire_BODY_ptr = (BODY*)wire_BODYs.get_and_step();
 
-  BODY *wire_BODY_ptr = (BODY*)wire_BODYs[0];
-
   ENTITY_LIST *face_list = new ENTITY_LIST;
   FACE* imprint_FACE = imprint_FACE_list.get();
   face_list->add( (ENTITY*)imprint_FACE );
@@ -15634,13 +17846,27 @@
     result = api_embed_wire_in_faces( wire_BODY_ptr, copied_BODY, face_list, tolerance );
   API_END
 
-  for(i=1; i<number_wire_bodies; i++ )
+  ENTITY_LIST tmp_edges;
+  ENTITY *tmp_ent;
+  if(result.ok())
   {
-#ifdef BOYD16
-    bool embedded = false;
-#endif
-    wire_BODY_ptr = (BODY*)wire_BODYs[i];
+    api_get_edges((ENTITY*)wire_BODY_ptr, tmp_edges);
+    tmp_edges.init();
+    while((tmp_ent = tmp_edges.next()))
+    {
+      Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges((EDGE*)tmp_ent);
+      if(new_curve)
+        temporary_bridges.append(new_curve);
+    }
+  }
 
+  //now embed the rest of the wires
+  for(i=1; i<wire_BODYs.size(); i++ )
+  {
+    //wire_BODY_ptr = (BODY*)wire_BODYs[i];
+    wire_BODYs.reset();
+    wire_BODY_ptr = wire_BODYs.next( i );
+
     //get all the faces on the body
     ENTITY_LIST FACEs;
     api_get_faces( copied_BODY, FACEs );
@@ -15650,65 +17876,131 @@
     if( number_faces_before == FACEs.count()  )
     {
       result = api_embed_wire_in_faces( wire_BODY_ptr, copied_BODY, face_list, tolerance );
+      if(result.ok())
+      {
+        tmp_edges.clear();
+        api_get_edges((ENTITY*)wire_BODY_ptr, tmp_edges);
+        tmp_edges.init();
+        while((tmp_ent = tmp_edges.next()))
+        {
+          Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges((EDGE*)tmp_ent);
+          if(new_curve)
+            temporary_bridges.append(new_curve);
+        }
+      }
       continue;
     }
 
-    //need to determine which face to embed curve onto
-    //may be able to remove this later on and just embed into body
-    //just embed the remining wires into the body
-    //result = api_embed_wire_in_faces( wire_BODY_ptr, copied_BODY, NULL, tolerance );
-    //if( !result.ok() )
-    //  AcisQueryEngine::instance()->ACIS_API_error (result);
-
-    //get midpoint of curve to embed
     ENTITY_LIST wire_edge_list;
     api_get_edges( wire_BODY_ptr, wire_edge_list );
     EDGE *wire_edge = (EDGE*)wire_edge_list[0];
-    SPAposition mid_point = wire_edge->mid_pos();
 
     //get position at fraction 0.79 along curve
-#ifdef BOYD16
-    SPAposition start_point = wire_edge->start()->geometry()->coords();
-#endif
     SPAparameter s_param = wire_edge->start_param();
     SPAparameter e_param = wire_edge->end_param();
-
-    //SPAinterval param_interval = wire_edge->param_range();
     SPAparameter new_parameter = s_param + ((e_param - s_param ) * 0.79);
-
     if (wire_edge->sense() == REVERSED )
       new_parameter = -(new_parameter);
-
     SPAposition point_on_curve;
     wire_edge->geometry()->equation().eval(new_parameter, point_on_curve );
 
-    //find surface which contains point at parameter 0.79 and midpoint
-    //loop to find appropriate face
+    //find faces WITHOUT an owner attrib on them.
+    //this indicates faces which have been split.
     ENTITY *temp_ENT;
     FACEs.init();
-    FACE *embed_FACE = NULL;
     while( (temp_ENT = FACEs.next()) != NULL )
     {
       FACE *tmp_FACE = (FACE*)temp_ENT;
-      SPAposition point1;
-      api_find_cls_ptto_face(mid_point, tmp_FACE, point1 );
-      if ( distance_to_point( point1, mid_point ) < 0.0005 )
+      if(!ATTRIB_CUBIT_OWNER::cubit_owner( temp_ENT ) )
       {
-        api_find_cls_ptto_face(point_on_curve, tmp_FACE, point1 );
+        //project edge to surface
+        EDGE *projected_EDGE = project_EDGE( wire_edge, (FACE*)tmp_FACE, false );
+        if( projected_EDGE == NULL )
+          continue;
+        
+        //does projection coincide with original
+        curve const* projected_curve = &(projected_EDGE->geometry()->equation());
+        SPAposition result_pos;
+        SPAparameter result_param;
+        projected_curve->point_perp( point_on_curve, result_pos, 
+                                     *(SPAparameter*)NULL_REF,
+                                     result_param );
+        if( distance_to_point( point_on_curve, result_pos ) > tolerance )
+        {
+          //if no...continue
+          api_delent( (ENTITY*)projected_EDGE);
+          continue;
+        }
+        
+        //intersect projected edge with surface
+        ENTITY_LIST *ent_list = new ENTITY_LIST;
+        result = api_edfa_int( projected_EDGE, tmp_FACE, ent_list );
 
-        if ( distance_to_point( point1, point_on_curve ) < 0.0005 )
+        if( !result.ok() || ent_list->count() == 0 )
         {
-          embed_FACE = tmp_FACE;
-          break;
+          delete ent_list;
+          continue;
         }
+        
+        //we only want edges
+        DLIList<EDGE*> edges_to_embed;
+        ENTITY *tmp_ent;
+        ent_list->init();
+        while( (tmp_ent=ent_list->next()) != NULL )
+        {
+          if( is_EDGE( tmp_ent ) )
+          {
+            EDGE *EDGE_ptr = static_cast<EDGE*>(tmp_ent);
+            edges_to_embed.append( EDGE_ptr );
+          }
+          else
+            api_delent( tmp_ent );
+        }
+        delete ent_list;
+
+        if( edges_to_embed.size() == 0 )
+          continue;
+        
+        EDGE *EDGEs[1];
+        EDGEs[0] = edges_to_embed.get_and_step();
+        BODY *wire_to_embed = NULL;
+        result = api_make_ewire( 1, EDGEs, wire_to_embed );
+        ENTITY_LIST *face_list = new ENTITY_LIST;
+        face_list->add( tmp_FACE );
+  
+        //now do the embedding
+        API_BEGIN
+          result = api_embed_wire_in_faces( wire_to_embed, copied_BODY, face_list, tolerance );
+        API_END
+
+        if(result.ok())
+        {
+          tmp_edges.clear();
+          api_get_edges((ENTITY*)wire_to_embed, tmp_edges);
+          tmp_edges.init();
+          while((tmp_ent = tmp_edges.next()))
+          {
+            Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges((EDGE*)tmp_ent);
+            if(new_curve)
+              temporary_bridges.append(new_curve);
+          }
+        }
+        
+        //for any additional intersection curves...add them to the list to embed
+        int kk;
+        for(kk=1; kk<edges_to_embed.size(); kk++ )
+        {
+          EDGEs[0] = edges_to_embed.get_and_step();
+          BODY *wire_to_embed = NULL;
+          result = api_make_ewire( 1, EDGEs, wire_to_embed );
+          if( result.ok() )
+            wire_BODYs.append( wire_to_embed );
+        }
+
+        delete face_list;
+
       }
     }
-    if( embed_FACE )
-    {
-      face_list->clear();
-      face_list->add( (ENTITY*)embed_FACE );
-      result = api_embed_wire_in_faces( wire_BODY_ptr, copied_BODY, face_list, tolerance );
-    }
   }
   
   AcisModifyEngine::instance()->cleanup_slivers( copied_BODY );
@@ -15736,16 +18028,348 @@
       num_vertex_bef == num_vertex_aft)
   {
     AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY, CUBIT_TRUE);
-    return CUBIT_SUCCESS;
+    return CUBIT_FAILURE;
   }
 
+  // Get the new entities (just edges for now)
+  // created by the imprint operation.
+  DLIList<ENTITY*> new_ENTITIES, att_ENTITIES;
+  if(copied_BODY && new_tbs)
+    get_new_ENTITIES(copied_BODY, new_ENTITIES);
+
   BodySM* new_body_ptr = get_new_Body( old_body_sm, BODY_ptr, copied_BODY,
                                        false, CUBIT_TRUE );
 
+  if (new_body_ptr)
+  {
+    // Get entities with composite attributes.
+    if(copied_BODY && att_tbs)
+      get_att_ENTITIES(copied_BODY, att_ENTITIES, "COMPOSITE_GEOM");
+  }
+  else
+  {
+    // Get entities with composite attributes.
+    if(att_tbs)
+      get_att_ENTITIES(BODY_ptr, att_ENTITIES, "COMPOSITE_GEOM");
+  }
+  // Convert the new_ENTITIES/att_ENTITIES lists into
+  // topology bridge lists.
+  if(new_tbs)
+  {
+    for(i=new_ENTITIES.size(); i--;)
+    {
+      ENTITY *cur_ENT = new_ENTITIES.get_and_step();
+      AcisBridge *acis_bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_ENT);
+      if(dynamic_cast<TopologyBridge*>(acis_bridge))
+        new_tbs->append_unique(dynamic_cast<TopologyBridge*>(acis_bridge));
+    }
+  }
+  if(att_tbs)
+  {
+    for(i=att_ENTITIES.size(); i--;)
+    {
+      ENTITY *cur_ENT = att_ENTITIES.get_and_step();
+      AcisBridge *acis_bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_ENT);
+      if(dynamic_cast<TopologyBridge*>(acis_bridge))
+        att_tbs->append_unique(dynamic_cast<TopologyBridge*>(acis_bridge));
+    }
+  }
+
   new_body = new_body_ptr;
   return CUBIT_SUCCESS;
 }
 
+
+//WARNING!!! Only use this function if you KNOW that the curves you want
+//to imprint line on the surface.....otherwise you'll get problems.
+//api_embed_wire_in_faces returns unexpected results if the curve
+//does not lie on the surface.
+CubitStatus AcisModifyEngine::embed_curves_into_surface( Surface *surface,
+                                                         DLIList<Curve*> &curves_to_imprint,
+                                                         DLIList<TopologyBridge*> &temporary_bridges,
+                                                         BodySM *&new_body,
+                                                         DLIList<TopologyBridge*> *new_tbs,
+                                                         DLIList<TopologyBridge*> *att_tbs ) const
+{
+  if( curves_to_imprint.size() == 0 )
+    return CUBIT_FAILURE;
+
+  BODY *copied_BODY = NULL;
+  DLIList<FACE*> imprint_FACE_list;
+  DLIList<SurfaceACIS*> acis_surfs;
+  SurfaceACIS *tmp_acis_surf = CAST_TO( surface, SurfaceACIS );
+
+  if( tmp_acis_surf == NULL )
+    return CUBIT_FAILURE;
+
+  FACE *FACE_ptr = tmp_acis_surf->get_FACE_ptr();
+  BODY *BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY( FACE_ptr );
+  BodySM *old_body_sm = AcisQueryEngine::instance()->get_body_sm_of_ENTITY( FACE_ptr );
+
+  acis_surfs.append( tmp_acis_surf );
+  if( get_copied_FACES_of_body( acis_surfs, imprint_FACE_list, copied_BODY ) == CUBIT_FAILURE )
+    return CUBIT_FAILURE;
+
+  if( imprint_FACE_list.size() == 0 )
+    return CUBIT_FAILURE;
+
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  int i;
+  EDGE *EDGEs[ 1 ];
+  ENTITY_LIST wire_BODYs;
+  for( i=0; i<curves_to_imprint.size(); i++ )
+  {
+    //copy
+    EDGE *EDGE_ptr = AcisQueryEngine::get_EDGE( curves_to_imprint.get_and_step() );
+
+    EDGE *copied_EDGE_ptr = NULL;
+    outcome tmp_result = api_edge( EDGE_ptr, copied_EDGE_ptr );
+    ATTRIB_CUBIT_OWNER::remove_cubit_owner( (ENTITY *)copied_EDGE_ptr,
+                                              CUBIT_TRUE );
+    EDGEs[0] = copied_EDGE_ptr;
+    BODY *tmp_BODY = NULL;
+    tmp_result = api_make_ewire( 1, EDGEs, tmp_BODY );
+    wire_BODYs.add( (ENTITY*)tmp_BODY );
+  }
+
+  int number_wire_bodies = wire_BODYs.count();
+
+  if( number_wire_bodies == 0 )
+    return CUBIT_FAILURE;
+
+  ENTITY_LIST temp_face_list;
+  api_get_faces( copied_BODY, temp_face_list );
+
+  ENTITY_LIST *face_list = new ENTITY_LIST;
+  FACE* imprint_FACE = imprint_FACE_list.get();
+  face_list->add( (ENTITY*)imprint_FACE );
+
+  double dist, dist2;
+  SPAposition wire_pos, edge_pos, pos1, pos2;
+
+  outcome result;
+  ENTITY *tmp_ent, *tmp_face_edge;
+  ENTITY_LIST tmp_edges, face_edges;
+  for(i=0; i<number_wire_bodies; i++ )
+  {
+    BODY *wire_BODY_ptr = (BODY*)wire_BODYs[i];
+
+    ENTITY_LIST FACEs;
+    api_get_faces( copied_BODY, FACEs );
+    if(imprint_FACE == NULL)
+    {
+      // Need to see if we can find a face to imprint into.  This face will 
+      // also help us know which curves to search for proximity with 
+      // the curve we are embedding.
+
+      //get midpoint of curve to embed
+      ENTITY_LIST wire_edge_list;
+      api_get_edges( wire_BODY_ptr, wire_edge_list );
+      EDGE *wire_edge = (EDGE*)wire_edge_list[0];
+      SPAposition mid_point = wire_edge->mid_pos();
+
+      //get position at fraction 0.79 along curve
+      SPAparameter s_param = wire_edge->start_param();
+      SPAparameter e_param = wire_edge->end_param();
+
+      //SPAinterval param_interval = wire_edge->param_range();
+      SPAparameter new_parameter = s_param + ((e_param - s_param ) * 0.79);
+
+      if (wire_edge->sense() == REVERSED )
+        new_parameter = -(new_parameter);
+
+      SPAposition point_on_curve;
+      wire_edge->geometry()->equation().eval(new_parameter, point_on_curve );
+
+      //find surface which contains point at parameter 0.79 and midpoint
+      //loop to find appropriate face
+      ENTITY *temp_ENT;
+      FACEs.init();
+      while( (temp_ENT = FACEs.next()) != NULL )
+      {
+        FACE *tmp_FACE = (FACE*)temp_ENT;
+        SPAposition point1;
+        api_find_cls_ptto_face(mid_point, tmp_FACE, point1 );
+        if ( distance_to_point( point1, mid_point ) < tolerance ) 
+        {
+          api_find_cls_ptto_face(point_on_curve, tmp_FACE, point1 );
+
+          if ( distance_to_point( point1, point_on_curve ) < tolerance ) 
+          {
+            imprint_FACE = tmp_FACE;
+            break;
+          }
+        }
+      }
+    }
+    ENTITY_LIST search_edges;
+    if(imprint_FACE == NULL)
+    {
+      // Couldn't find a face so search all curves in body.
+      api_get_edges((ENTITY*)copied_BODY, search_edges);
+    }
+    else
+    {
+      // Found a face so search the curves in the face.
+      api_get_edges((ENTITY*)imprint_FACE, search_edges);
+    }
+    bool found_entities_within_tolerance = false;
+    double largest_distance_within_tolerance = 0.0;
+    search_edges.init();
+    while((tmp_face_edge = search_edges.next()))
+    {
+      dist = 0.0;
+      api_entity_entity_distance(wire_BODY_ptr, tmp_face_edge, wire_pos, edge_pos, dist);
+      if(dist <= tolerance)
+      {
+        found_entities_within_tolerance = true;
+        ENTITY_LIST verts1, verts2;
+        api_get_vertices(wire_BODY_ptr, verts1);
+        api_get_vertices(tmp_face_edge, verts2);
+        ENTITY *vert1, *vert2;
+        verts1.init();
+        while((vert1 = verts1.next()))
+        {
+          verts2.init();
+          while((vert2 = verts2.next()))
+          {
+            dist2 = 0.0;
+            api_entity_entity_distance(vert1, vert2, pos1, pos2, dist2);
+            if(dist2 > dist && dist2 < tolerance)
+              dist = dist2;
+          }
+        }
+        if(dist > largest_distance_within_tolerance)
+          largest_distance_within_tolerance = dist;
+      }
+    }
+    int num_faces_before = FACEs.count();
+    if(found_entities_within_tolerance && largest_distance_within_tolerance > GEOMETRY_RESABS)
+    {
+      // If the biggest distance between entities is less than 1e-6 (ACIS resabs)
+      // we can use regular imprinting.  Otherwise we have to use tolerant embedding.
+      largest_distance_within_tolerance *= 1.1;
+      if(largest_distance_within_tolerance > tolerance)
+        largest_distance_within_tolerance = tolerance;
+
+      if(imprint_FACE)
+      {
+        face_list->clear();
+        face_list->add( (ENTITY*)imprint_FACE );
+        result = api_embed_wire_in_faces(wire_BODY_ptr, copied_BODY, face_list, largest_distance_within_tolerance);
+      }
+      else
+      {
+        result = api_embed_wire_in_faces(wire_BODY_ptr, copied_BODY, NULL, largest_distance_within_tolerance);
+      }
+    }
+    else
+    {
+      // Just do a regular imprint becuase the curve already lies in the face
+      // but doesn't come close to other entities.
+      result = api_imprint(wire_BODY_ptr, copied_BODY);
+    }
+    if(result.ok())
+    {
+      tmp_edges.clear();
+      api_get_edges((ENTITY*)wire_BODY_ptr, tmp_edges);
+      tmp_edges.init();
+      while((tmp_ent = tmp_edges.next()))
+      {
+        Curve *new_curve = AcisQueryEngine::instance()->populate_topology_bridges((EDGE*)tmp_ent);
+        if(new_curve)
+          temporary_bridges.append(new_curve);
+      }
+    }
+    //if normal imprint didn't succeed, try embedding
+    else
+      api_embed_wire_in_faces(wire_BODY_ptr, copied_BODY, NULL, largest_distance_within_tolerance);
+
+    FACEs.clear();
+    api_get_faces( copied_BODY, FACEs );
+    if(FACEs.count() != num_faces_before)
+      imprint_FACE = NULL;
+  }
+ 
+  delete face_list;
+
+  //AcisModifyEngine::instance()->cleanup_slivers( copied_BODY );
+
+  //check to see if anything actually happened
+  int num_vol_bef, num_face_bef, num_edge_bef, num_vertex_bef;
+  CubitStatus status1 = AcisQueryEngine::instance()->number_ENTITIES( BODY_ptr, num_vol_bef,
+                                           num_face_bef, num_edge_bef,
+                                           num_vertex_bef );
+
+  int num_vol_aft, num_face_aft, num_edge_aft, num_vertex_aft;
+  CubitStatus status2 = AcisQueryEngine::instance()->number_ENTITIES( copied_BODY, num_vol_aft,
+                                           num_face_aft, num_edge_aft,
+                                           num_vertex_aft );
+
+  if( status1 == CUBIT_FAILURE  ||
+      status2 == CUBIT_FAILURE )
+  {
+    return CUBIT_FAILURE;
+  }
+
+  if( num_vol_bef == num_vol_aft &&
+      num_face_bef == num_face_aft &&
+      num_edge_bef == num_edge_aft &&
+      num_vertex_bef == num_vertex_aft)
+  {
+    AcisQueryEngine::instance()->delete_ACIS_BODY(copied_BODY, CUBIT_TRUE);
+    return CUBIT_FAILURE;
+  }
+
+  // Get the new entities (just edges for now)
+  // created by the imprint operation.
+  DLIList<ENTITY*> new_ENTITIES, att_ENTITIES;
+  if(copied_BODY && new_tbs)
+    get_new_ENTITIES(copied_BODY, new_ENTITIES);
+
+  BodySM* new_body_ptr = get_new_Body( old_body_sm, BODY_ptr, copied_BODY,
+                                       false, CUBIT_TRUE );
+  if (new_body_ptr)
+  {
+    // Get entities with composite attributes.
+    if(copied_BODY && att_tbs)
+      get_att_ENTITIES(copied_BODY, att_ENTITIES, "COMPOSITE_GEOM");
+  }
+  else
+  {
+    // Get entities with composite attributes.
+    if(att_tbs)
+      get_att_ENTITIES(BODY_ptr, att_ENTITIES, "COMPOSITE_GEOM");
+  }
+
+  // Convert the new_ENTITIES/att_ENTITIES lists into
+  // topology bridge lists.
+  if(new_tbs)
+  {
+    for(i=new_ENTITIES.size(); i--;)
+    {
+      ENTITY *cur_ENT = new_ENTITIES.get_and_step();
+      AcisBridge *acis_bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_ENT);
+      if(dynamic_cast<TopologyBridge*>(acis_bridge))
+        new_tbs->append_unique(dynamic_cast<TopologyBridge*>(acis_bridge));
+    }
+  }
+  if(att_tbs)
+  {
+    for(i=att_ENTITIES.size(); i--;)
+    {
+      ENTITY *cur_ENT = att_ENTITIES.get_and_step();
+      AcisBridge *acis_bridge = ATTRIB_CUBIT_OWNER::cubit_owner(cur_ENT);
+      if(dynamic_cast<TopologyBridge*>(acis_bridge))
+        att_tbs->append_unique(dynamic_cast<TopologyBridge*>(acis_bridge));
+    }
+  }
+
+  new_body = new_body_ptr;
+  return CUBIT_SUCCESS;
+}
+
 CubitStatus AcisModifyEngine::curve_surface_intersection( Surface *surface,
                                             Curve* curve,
                                             DLIList<Curve*> &new_curves ) const
@@ -15753,13 +18377,12 @@
   FACE *FACE_ptr = AcisQueryEngine::get_FACE( surface );
   EDGE *EDGE_ptr = AcisQueryEngine::get_EDGE( curve );
 
-  ENTITY_LIST *ent_list = new ENTITY_LIST;
+  ENTITY_LIST *ent_list = new ENTITY_LIST; 
 
   outcome result = api_edfa_int( EDGE_ptr, FACE_ptr, ent_list );
 
   if( !result.ok() || ent_list->count() == 0 )
   {
-    delete ent_list;
     return CUBIT_FAILURE;
   }
 
@@ -15774,55 +18397,88 @@
       new_curves.append( curve_ptr );
     }
   }
-  delete ent_list;
-
-  if( new_curves.size() == 0 )
-    return CUBIT_FAILURE;
-
+  
+  if( ent_list )
+    ACIS_DELETE ent_list;
+  
   return CUBIT_SUCCESS;
 }
 
-void AcisModifyEngine::get_new_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &new_ENTITIES) const
+void AcisModifyEngine::get_new_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &new_ENTITIES,
+                                        DLIList<DLIList<EDGE*>*> *lists_of_EDGES_on_original_FACES,
+                                        DLIList<DLIList<EDGE*>*> *imprint_EDGE_lists) const
 {
   ENTITY_LIST ENTITIES;
-  int i;
+  int i, j, k;
   
   // vertices
   api_get_vertices( top_ENTITY, ENTITIES);
   for (i = 0; i < ENTITIES.count(); i++)
   {
     if (!ATTRIB_CUBIT_OWNER::cubit_owner(ENTITIES[i]))
-    {
       new_ENTITIES.append_unique(ENTITIES[i]);
-    }
   }
   ENTITIES.clear();
 
   // edges
-  api_get_edges( top_ENTITY, ENTITIES);
+  api_get_edges(top_ENTITY, ENTITIES);
   for (i = 0; i < ENTITIES.count(); i++)
   {
     if (!ATTRIB_CUBIT_OWNER::cubit_owner(ENTITIES[i]))
     {
       new_ENTITIES.append_unique(ENTITIES[i]);
+
+      // Now that we have determined this entity is new remove it
+      // form this lists we will use below in further checks.
+      if(lists_of_EDGES_on_original_FACES)
+      {
+        for(j=lists_of_EDGES_on_original_FACES->size(); j--;)
+        {
+          DLIList<EDGE*> *cur_list = lists_of_EDGES_on_original_FACES->get_and_step();
+          if(cur_list->move_to((EDGE*)ENTITIES[i]))
+            cur_list->extract();
+        }
+      }
     }
   }
   ENTITIES.clear();
-/*
+  if(lists_of_EDGES_on_original_FACES &&
+    lists_of_EDGES_on_original_FACES->size() &&
+    lists_of_EDGES_on_original_FACES->size() == imprint_EDGE_lists->size())
+  {
+    for(j=imprint_EDGE_lists->size(); j--;)
+    {
+      DLIList<EDGE*> *cur_original_EDGE_list = lists_of_EDGES_on_original_FACES->get_and_step();
+      DLIList<EDGE*> *cur_imprint_EDGE_list = imprint_EDGE_lists->get_and_step();
+      for(i=cur_imprint_EDGE_list->size(); i--;)
+      {
+        EDGE *cur_imprint_EDGE = cur_imprint_EDGE_list->get_and_step();
+        for(k=cur_original_EDGE_list->size(); k--;)
+        {
+          EDGE *cur_orig_EDGE = cur_original_EDGE_list->get_and_step();
+          if(AcisQueryEngine::instance()->about_spatially_equal(cur_imprint_EDGE,
+            cur_orig_EDGE))
+          {
+            new_ENTITIES.append_unique((ENTITY*)cur_orig_EDGE);
+            new_ENTITIES.append_unique((ENTITY*)cur_orig_EDGE->start());
+            new_ENTITIES.append_unique((ENTITY*)cur_orig_EDGE->end());
+          }
+        }
+      }
+    }
+  }
+
   // faces
   api_get_faces( top_ENTITY, ENTITIES);
   for (i = 0; i < ENTITIES.count(); i++)
   {
     if (!ATTRIB_CUBIT_OWNER::cubit_owner(ENTITIES[i]))
-    {
       new_ENTITIES.append_unique(ENTITIES[i]);
-    }
   }
   ENTITIES.clear();
-  */
 }
 
-void AcisModifyEngine::get_att_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &att_ENTITIES, char *att_name) const
+void AcisModifyEngine::get_att_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &att_ENTITIES, const char *att_name) const
 {
   ENTITY_LIST ENTITIES;
   int i;
@@ -15890,10 +18546,21 @@
    double sliver_curve_tol = GeometryQueryTool::get_sliver_curve_cleanup_tolerance();
    double sliver_surface_tol = GeometryQueryTool::get_sliver_surface_cleanup_tolerance();
 
-   ENTITY_LIST dummy_list;
-   api_detect_short_edges( body_to_cleanup, dummy_list, sliver_curve_tol, true );
-   api_detect_sliver_faces( body_to_cleanup, dummy_list, sliver_surface_tol, true );
+   ENTITY_LIST ents_to_remove; 
+   api_detect_short_edges( body_to_cleanup, ents_to_remove, sliver_curve_tol, true );
 
+   //put no-merge attributes on all vertices so that irrelevant vertices do not
+   //get inadvertantly removed (regularized out)
+   ENTITY_LIST body_verts;
+   api_get_vertices( body_to_cleanup, body_verts );
+   api_set_no_merge_attrib( body_verts );
+
+   api_detect_sliver_faces( body_to_cleanup, ents_to_remove, sliver_surface_tol, true );
+
+   body_verts.clear(); 
+   api_get_vertices( body_to_cleanup, body_verts );
+   api_remove_no_merge_attrib( body_verts );
+    
    return CUBIT_SUCCESS;
 }
 
@@ -15927,7 +18594,7 @@
   if( removed_curves.count() == 0 )
   {
     api_delent( (ENTITY*)copy_BODY );
-    return CUBIT_SUCCESS;
+    return CUBIT_FAILURE;
   }
   
   get_new_Body(body_sm, tmp_BODY, copy_BODY, CUBIT_FALSE);
@@ -15935,6 +18602,7 @@
   return CUBIT_SUCCESS;
 }
 
+
   CubitStatus AcisModifyEngine::stitch_surfs(
 					     DLIList<BodySM*>& surf_bodies,
 					     BodySM*& stitched_body)const
@@ -15986,24 +18654,1749 @@
       return CUBIT_SUCCESS;
     }
 
-  CubitStatus AcisModifyEngine::trim_up_to_next_surface(BodySM*& tool_body,
-							DLIList<BodySM*> bodies,
-							GeometryEntity * surf_vert)
+CubitStatus AcisModifyEngine::remove_topology(DLIList<Curve*> &curves_to_remove,
+                                       DLIList<Surface*> &surfs_to_remove,
+                                       double backoff_distance,
+                                       double small_edge_size,
+                                       DLIList<BodySM*> &new_bodysm_list,
+                                       CubitBoolean preview) const
+{
+   return AcisTweakTool::instance()->remove_topology( curves_to_remove, surfs_to_remove, 
+                 backoff_distance, small_edge_size, new_bodysm_list, preview);
+
+}
+
+
+
+
+CubitStatus AcisModifyEngine::imprint_overlapping_curves( DLIList<BodySM*> &body_sms,
+                                                          DLIList<BodySM*> &new_body_sms,
+                                                          ProgressTool *progress_tool,
+                                                          DLIList<TopologyBridge*> *new_tbs,
+                                                          DLIList<TopologyBridge*> *att_tbs ) const
+{
+  //find all mergeable curves between the bodies
+#ifdef BOYD16
+  DLIList<RefEntity*> entities;
+#endif
+  DLIList< DLIList<Curve*>* > lists_of_mergeable_curves;
+
+  MergeTool::instance()->find_only_mergeable_curves( body_sms, lists_of_mergeable_curves );
+  
+  int i;
+  //increment 4%
+  if( progress_tool )
+  {
+    for( i=4; i--; )
+      progress_tool->step();
+  }
+
+  //find all overlapping curves between the bodies
+  std::map<Curve*, DLIList<Curve*>* > curve_to_list_map;
+  DLIList< DLIList<Curve*>* > lists_of_overlapping_curves;
+  std::multimap<BodySM*, CubitVector> body_vertex_imprint_map; 
+  //for each list, curves 2-n overlap the first curve
+  
+  SurfaceOverlapTool::instance()->find_overlapping_curves( body_sms, lists_of_overlapping_curves,
+                                                           curve_to_list_map,
+                                                           body_vertex_imprint_map);
+
+  //increment 8%
+  if( progress_tool )
+  {
+    for( i=9; i--; )
+      progress_tool->step();
+  }
+
+  return imprint_overlapping_curves(lists_of_mergeable_curves,
+                                    lists_of_overlapping_curves,
+                                    curve_to_list_map,
+                                    body_vertex_imprint_map,
+                                    new_body_sms,
+                                    progress_tool,
+                                    new_tbs,
+                                    att_tbs );
+
+}
+
+CubitStatus AcisModifyEngine::tolerant_imprint(DLIList<Surface*> &surfs_in,
+                                               DLIList<BodySM*> &new_bodysm_list) const
+{
+  DLIList<Surface*> new_surface_list;
+
+  CubitStatus status = imprint_overlapping_curves(surfs_in, new_bodysm_list);
+
+  status = imprint_overlapping_surfaces(surfs_in, new_bodysm_list, &new_surface_list);
+
+  // The surface may have been blown away by this point so don't do this last one.
+  // I may need to change things so that I pass in the body so I can get the new
+  // surf and still call this but for now I just won't call it.
+//  status = imprint_overlapping_curves(surfs_in, new_bodysm_list);
+  status = imprint_overlapping_curves(new_surface_list, new_bodysm_list);
+
+  return CUBIT_SUCCESS;
+}
+
+
+CubitStatus AcisModifyEngine::imprint_overlapping_curves(DLIList<Surface*> &surfs,
+                                                         DLIList<BodySM*> &new_body_sms) const
+{
+  //find all mergeable curves between the bodies
+  DLIList< DLIList<Curve*>* > lists_of_mergeable_curves;
+
+  MergeTool::instance()->find_only_mergeable_curves(surfs, lists_of_mergeable_curves);
+
+  //find all overlapping curves between the bodies
+  std::map<Curve*, DLIList<Curve*>* > curve_to_list_map;
+  DLIList< DLIList<Curve*>* > lists_of_overlapping_curves;
+  std::multimap<BodySM*, CubitVector> body_vertex_imprint_map; 
+  //for each list, curves 2-n overlap the first curve
+  
+  SurfaceOverlapTool::instance()->find_overlapping_curves(surfs, lists_of_overlapping_curves,
+                                                           curve_to_list_map, body_vertex_imprint_map );
+
+  return imprint_overlapping_curves(lists_of_mergeable_curves,
+                                    lists_of_overlapping_curves,
+                                    curve_to_list_map,
+                                    body_vertex_imprint_map,
+                                    new_body_sms,
+                                    NULL,
+                                    NULL,
+                                    NULL );
+}
+CubitStatus AcisModifyEngine::imprint_overlapping_surfaces( DLIList<Surface*> &surfs,
+                                                           DLIList<BodySM*> &new_bodysm_list,
+                                                           DLIList<Surface*> *new_surface_list) const
+{
+  //Find all overlapping surfaces between the bodies
+  DLIList<Surface*> overlapping_surfaces1;
+  DLIList<Surface*> overlapping_surfaces2;
+
+  overlapping_surfaces1.append(surfs.get_and_step());
+  overlapping_surfaces2.append(surfs.get());
+
+  return imprint_overlapping_surfaces(overlapping_surfaces1, overlapping_surfaces2, new_bodysm_list,
+    NULL, new_surface_list);
+}
+
+CubitStatus AcisModifyEngine::imprint_overlapping_surfaces( DLIList<BodySM*> &body_sms,
+                                                            DLIList<BodySM*> &new_body_sms,
+                                                            ProgressTool *progress_tool) const
+{
+  //Find all mergeable surfaces between the bodies
+  DLIList< DLIList<Surface*>* > lists_of_mergeable_surfaces;
+  /*CubitStatus status =*/ MergeTool::instance()->
+      find_only_mergeable_surfaces( body_sms, lists_of_mergeable_surfaces );
+
+  if( progress_tool )
+    progress_tool->percent( 0.24 );
+
+  //Find all overlapping surfaces between the bodies
+  DLIList<Surface*> overlapping_surfaces1;
+  DLIList<Surface*> overlapping_surfaces2;
+  SurfaceOverlapTool::instance()->
+    find_overlapping_surfaces( body_sms, overlapping_surfaces1, overlapping_surfaces2 );
+
+  if( progress_tool )
+    progress_tool->percent( 0.57 );
+
+  //We only want the non-mergeable overlapping surfaces.
+  //Remove mergable surfaces from overlapping pairs.
+  int i, j;
+  for( i=lists_of_mergeable_surfaces.size(); i--; )
+  {
+    DLIList<Surface*> *tmp_surface_list = lists_of_mergeable_surfaces.get_and_step();
+    for( j=tmp_surface_list->size(); j--; )
     {
-      assert(tool_body);
-      assert(surf_vert);
-      BODY* tool_BODY = AcisQueryEngine::get_BODY( tool_body );
-      if (tool_BODY == NULL)
-	return CUBIT_FAILURE;
+      Surface *tmp_surface = tmp_surface_list->get_and_step();
+      while( overlapping_surfaces1.move_to( tmp_surface ) )
+        overlapping_surfaces1.change_to(NULL);
+      while( overlapping_surfaces2.move_to( tmp_surface ) )
+        overlapping_surfaces2.change_to(NULL);
+    }
+    delete tmp_surface_list;
+  }
 
-      Point * vertex = CAST_TO(surf_vert, Point);
-      if (!vertex)
-	return CUBIT_FAILURE;
-      VERTEX * VERTEX_ptr = AcisQueryEngine::get_VERTEX(vertex);
+  if( progress_tool )
+    progress_tool->percent( 0.59 );
 
-      CubitStatus stat= trim_up_to_next_surface(tool_BODY, bodies, VERTEX_ptr); 
-      if (stat)
-	tool_body =  AcisQueryEngine::instance()->populate_topology_bridges(tool_BODY);
+  return imprint_overlapping_surfaces(overlapping_surfaces1, overlapping_surfaces2,
+                                      new_body_sms, progress_tool);
+}
 
-      return stat;
+CubitStatus
+AcisModifyEngine::remove_FACEs_from_BODY( BODY *BODY_ptr,
+                                          DLIList<FACE*> &remove_FACE_list,
+                                          CubitBoolean silent )
+{
+  if( remove_FACE_list.size() == 0 )
+    return CUBIT_SUCCESS;
+
+  // Need special handling if BODY is solid
+  bool is_closed = false;
+  if( is_closed_solid_body( BODY_ptr ) )
+    is_closed = true;
+
+  int i;
+  outcome result;
+  bool old_flg = ATTRIB_CUBIT_OWNER::set_split_copy( true );
+  //ENTITY_LIST faces_to_remove;
+  FACE *FACE_ptr;
+  for( i=remove_FACE_list.size(); i--; )
+  {
+    FACE_ptr = remove_FACE_list.get_and_step();
+    if( !FACE_ptr )
+      continue;
+    //faces_to_remove.add( FACE_ptr );
+    result = api_remove_face( FACE_ptr );
+    if( !result.ok() )
+    {
+      ATTRIB_CUBIT_OWNER::set_split_copy( old_flg );
+      if( !silent) AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
     }
+  }
+  ATTRIB_CUBIT_OWNER::set_split_copy( old_flg );
+
+  // This doesn't work, because all attributes are removed from the input body,
+  // even if we copy attributes during a split (set_split_copy).  I think this
+  // would be faster than the method we are using.  This could be an acis bug..
+  //ENTITY_LIST unhooked_bodies;
+  //result = api_unhook_faces( faces_to_remove, false, unhooked_bodies );
+  //unhooked_bodies.init();
+  //ENTITY *ENTITY_ptr = NULL;
+  //while( ENTITY_ptr = unhooked_bodies.next() )
+  //  api_delent( ENTITY_ptr );
+  //if( !result.ok() )
+  //{
+  //  AQE->ACIS_API_error(result);
+  //  return CUBIT_FAILURE;
+  //}
+
+  // If we removed a FACE from a solid BODY, we need to make the remaining
+  // FACEs 2D
+  if( is_closed == true )
+  {
+    result = api_body_to_2d( BODY_ptr );
+    if( !result.ok() )
+    {
+      if( !silent) AcisQueryEngine::instance()->ACIS_API_error(result);
+      return CUBIT_FAILURE;
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus
+AcisModifyEngine::remove_FACEs_from_BODY_except( BODY *BODY_ptr,
+                                                 DLIList<FACE*> &keep_FACE_list,
+                                                 CubitBoolean silent )
+{
+  DLIList<FACE*> FACE_list;
+  AcisQueryEngine::instance()->get_FACEs( BODY_ptr, FACE_list );
+
+  DLIList<FACE*> remove_FACE_list;
+  int i;
+  FACE *FACE_ptr;
+  for( i=FACE_list.size(); i--; )
+  {
+    FACE_ptr = FACE_list.get_and_step();
+    if( !FACE_ptr )
+      continue;
+    if( !keep_FACE_list.is_in_list( FACE_ptr ) )
+      remove_FACE_list.append( FACE_ptr );
+  }
+
+  return remove_FACEs_from_BODY( BODY_ptr, remove_FACE_list, silent );
+}
+
+CubitStatus
+AcisModifyEngine::remove_dup_owners( BODY *ref_BODY_ptr, BODY *BODY_ptr )
+{
+  // Check BODIEs, LUMPs, SHELLs, FACEs, LOOPs, COEDGEs, EDGEs, VERTICEs
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, BODY_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, LUMP_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, SHELL_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, FACE_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, LOOP_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, COEDGE_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, EDGE_TYPE );
+  remove_dup_owners( ref_BODY_ptr, BODY_ptr, VERTEX_TYPE );
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus
+AcisModifyEngine::remove_dup_owners( BODY *ref_BODY_ptr, BODY *BODY_ptr,
+                                     const int type )
+{
+  if( type == BODY_TYPE )
+  {
+    if( ATTRIB_CUBIT_OWNER::cubit_owner(ref_BODY_ptr) == 
+      ATTRIB_CUBIT_OWNER::cubit_owner(BODY_ptr))
+      ATTRIB_CUBIT_OWNER::remove_cubit_owner(BODY_ptr);
+    return CUBIT_SUCCESS;
+  }
+
+  outcome result;
+  ENTITY *ENTITY_ptr;
+  AcisBridge* ab_ptr;
+
+  // Use a map
+  std::map<AcisBridge*, ENTITY*>::iterator iter;
+  std::map<AcisBridge*, ENTITY*> ref_map;  // <map key, type>
+  ENTITY_LIST ENTs;
+
+  // Get the entities of the reference BODY into the map
+
+  // More elegant would be to use a function pointer, if I could get it to work
+  if( type==LUMP_TYPE )
+    result = api_get_lumps( ref_BODY_ptr, ENTs );
+  else if( type==SHELL_TYPE )
+    result = api_get_shells( ref_BODY_ptr, ENTs );
+  else if( type==FACE_TYPE )
+    result = api_get_faces( ref_BODY_ptr, ENTs );
+  else if( type==LOOP_TYPE )
+    result = api_get_loops( ref_BODY_ptr, ENTs );
+  else if( type==COEDGE_TYPE )
+    result = api_get_coedges( ref_BODY_ptr, ENTs );
+  else if( type==EDGE_TYPE )
+    result = api_get_edges( ref_BODY_ptr, ENTs );
+  else if( type==VERTEX_TYPE )
+    result = api_get_vertices( ref_BODY_ptr, ENTs );
+  else
+  {
+    PRINT_ERROR( "Invalid entity type encountered\n" );
+    return CUBIT_FAILURE;
+  }
+  if( !result.ok() )
+    return CUBIT_FAILURE;
+
+  // Populate the reference BODY map
+  ENTs.init();
+  while( (ENTITY_ptr = ENTs.next() ) != NULL )
+  {
+    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITY_ptr);
+    if( ab_ptr )
+      ref_map.insert(std::map<AcisBridge*, ENTITY*>::value_type( 
+      ab_ptr, ENTITY_ptr ) );
+  }
+
+  // Loop through the entities of the other BODY, looking for duplicate cubit
+  // owners.
+  ENTs.clear();
+  if( type==LUMP_TYPE )
+    result = api_get_lumps( BODY_ptr, ENTs );
+  else if( type==SHELL_TYPE )
+    result = api_get_shells( BODY_ptr, ENTs );
+  else if( type==FACE_TYPE )
+    result = api_get_faces( BODY_ptr, ENTs );
+  else if( type==LOOP_TYPE )
+    result = api_get_loops( BODY_ptr, ENTs );
+  else if( type==COEDGE_TYPE )
+    result = api_get_coedges( BODY_ptr, ENTs );
+  else if( type==EDGE_TYPE )
+    result = api_get_edges( BODY_ptr, ENTs );
+  else if( type==VERTEX_TYPE )
+    result = api_get_vertices( BODY_ptr, ENTs );
+  else
+  {
+    PRINT_ERROR( "Invalid entity type encountered\n" );
+    return CUBIT_FAILURE;
+  }
+  if( !result.ok() )
+    return CUBIT_FAILURE;
+  ENTs.init();
+  while( (ENTITY_ptr = ENTs.next() ) != NULL )
+  {
+    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITY_ptr);
+    if( ab_ptr )
+    {
+      iter = ref_map.find( ab_ptr );
+      if( iter != ref_map.end() )
+        ATTRIB_CUBIT_OWNER::remove_cubit_owner(ENTITY_ptr);
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+// Function   : trim_BODY_to_box
+// Member Type: PRIVATE
+// Description: Trim the given BODY to fit within the given CubitBox.
+// Author     : Steve Storm
+// Date       : 2/15/07
+//=============================================================================
+CubitStatus
+AcisModifyEngine::trim_BODY_to_box( BODY *&BODY_ptr, CubitBox &box ) const
+{
+  // Work on a copy of the box
+  CubitBox box_copy = box;
+
+  // Special case for planar situation.  Technically, this is not correct but
+  // we can't create a brick with a zero dimension.  Usually, if we have a zero
+  // dimension, we are dealing with a planar model, so it is valid to expand
+  // out like this... in that case we get the correct end result.
+  double box_tol = 1e-6;
+  if( (fabs(box.x_range())<box_tol) || 
+      (fabs(box.y_range())<box_tol) ||
+      (fabs(box.z_range())<box_tol) )
+  {
+    // Arbitrarily make the zero length side 1/10th the shortest side
+    double x = box.x_range();
+    double y = box.y_range();
+    double z = box.z_range();
+    double range;
+
+    if( fabs(x)<box_tol )
+    {
+      if( y<=z )
+        range = y/10.0;
+      else
+        range = z/10.0;
+    }
+    else if( fabs(y)<box_tol )
+    {
+      if( x<=z )
+        range = x/10.0;
+      else
+        range = z/10.0;
+    }
+    else // fabs(z)<box_tol
+    {
+      if( x<=y )
+        range = x/10.0;
+      else
+        range = y/10.0;
+    }
+
+    CubitVector box_center = box.center();
+    if( fabs(x)<box_tol )
+    {
+      box_copy |= (box_center + CubitVector(range, 0.0, 0.0));
+      box_copy |= (box_center - CubitVector(range, 0.0, 0.0));
+    }
+    else if( fabs(y)<box_tol )
+    {
+      box_copy |= (box_center + CubitVector(0.0, range, 0.0));
+      box_copy |= (box_center - CubitVector(0.0, range, 0.0));
+    }
+    else // fabs(z)<box_tol
+    {
+      box_copy |= (box_center + CubitVector(0.0, 0.0, range));
+      box_copy |= (box_center - CubitVector(0.0, 0.0, range));
+    }
+  }
+
+  // Setup a brick
+  CubitVector axes[3];
+  CubitVector extension;
+  axes[0].set( 1.0, 0.0, 0.0 );
+  axes[1].set( 0.0, 1.0, 0.0 );
+  axes[2].set( 0.0, 0.0, 1.0 );
+  extension.set( box_copy.x_range()/2.0, box_copy.y_range()/2.0, 
+                 box_copy.z_range()/2.0 );
+
+  // Create a brick
+  BODY *brick_ptr = make_brick_BODY( box_copy.center(), axes, extension );
+  if( !brick_ptr )
+    return CUBIT_FAILURE;
+
+  // Intersect the brick and BODY (note this will destroy the brick)
+  outcome result = api_boolean( brick_ptr, BODY_ptr, INTERSECTION );
+  if( !result.ok() )
+  {
+    api_delent( brick_ptr );
+    return CUBIT_FAILURE;
+  }
+
+  // Make sure there is something left
+  if( BODY_ptr == NULL || 
+      BODY_ptr->lump() == NULL ||
+      BODY_ptr->lump()->shell() == NULL ||
+      BODY_ptr->lump()->shell()->first_face() == NULL ||
+      BODY_ptr->lump()->shell()->first_face()->geometry() == NULL )
+  {
+    if( BODY_ptr )
+      api_delent( BODY_ptr );
+    BODY_ptr = NULL;
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+int stitch_process_callback( stitch_progress_info *progress_info )
+{
+  double progress = progress_info->percentage()/100.0;
+  AppUtil::instance()->progress_tool()->percent( progress ); 
+  return 0;
+}
+
+CubitStatus AcisModifyEngine::stitch( DLIList<BodySM*> &bodies_to_stitch,
+                                      DLIList<BodySM*> &new_bodies,
+                                      bool tighten_gaps,
+                                      double tolerance ) const
+{
+  ENTITY_LIST bodies_in;
+  DLIList<BODY*> original_BODYs;
+  //get all the underlying ACIS bodies from bodies_to_stitch
+  int i;
+  for( i=bodies_to_stitch.size(); i--; )
+  {
+    BodySM *tmp_body = bodies_to_stitch.get_and_step();
+    BodyACIS* body_acis = CAST_TO(tmp_body, BodyACIS );
+
+    BODY *original_BODY = body_acis->get_BODY_ptr();
+    original_BODYs.append( original_BODY );
+
+    BODY *copied_BODY = this->copy_BODY( original_BODY ); 
+    bodies_in.add( copied_BODY );
+  }
+
+  ENTITY_LIST new_body_list;
+  CubitStatus stat = stitch_simplify_and_tighten_gaps( bodies_in, new_body_list, tighten_gaps, tolerance );
+
+  if( stat == CUBIT_FAILURE )
+    return stat;
+
+  ENTITY *tmp_ent=NULL;
+  DLIList<BODY*>new_BODYs;
+  new_body_list.init();
+  while( NULL != (tmp_ent = new_body_list.next()))
+    new_BODYs.append( (BODY*)tmp_ent );
+
+  get_new_Body( bodies_to_stitch, original_BODYs, new_BODYs, new_bodies, false, true );  
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisModifyEngine::stitch_simplify_and_tighten_gaps(
+                              ENTITY_LIST& bodies_imported_into_ACIS,
+                              ENTITY_LIST& output_bodies,
+                              bool tighten_gaps,
+                              double tolerance )const
+{
+  // **************************************************************
+  // Step 1 : Tolerant Stitching
+  // (call api_stitch with tolerant_stitch_options)
+  // **************************************************************
+  
+  if( tolerance == -1 )
+    tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  bool stitch = true;
+  if(stitch)
+  {
+    // Create a default tolerant_stitch_options object.
+    tolerant_stitch_options sopts;
+
+    // Set the stitcher coincident face identification routine
+    // to SPASTITCH_COIN_SKIP to skip stitching coincident faces.
+    STITCH_COIN_MODES mode = SPASTITCH_COIN_SKIP;
+    sopts.set_stch_coincident_face_handling_mode(mode);
+
+    // Determine and set max-stitch-tol for stitching.
+    sopts.set_max_stitch_tol( tolerance );
+
+    // Call User's function to stitch list of entities
+    if( stitch_entities(bodies_imported_into_ACIS, output_bodies, sopts) == CUBIT_FAILURE )
+    {
+      output_bodies.clear();
+      return CUBIT_FAILURE;
+    }
+  }
+  else
+  {
+    output_bodies = bodies_imported_into_ACIS;
+  }
+
+  // **************************************************************
+  // Step 2 : Simplification
+  // (call api_simplify_entity)
+  // **************************************************************
+
+  // Determine the desired gap tightness ("desired_gap_tightness")
+  // of the user's downstream application (like manufacturing).
+  bool simplification = true;
+  if(simplification)
+  {
+    // A user may want to simplify each stitched BODY in the "output_bodies" list.
+    // Create default simplify_options object. A default simplify_options object
+    // will do both curve and surface simplification based on the default value of
+    // simplification tolerance(SPAresabs).
+    simplify_options simp_opts;
+
+    // Choose a simplification tolerance. If the user desires the gaps in the model
+    // to be within a certain value, then that value could be the best value
+    // to use as simplification tolerance. So user may want to use the desired
+    // gap tightness as simplification tolerance. Set the simplification tolerance
+    // equal to the desired_gap_tightness value of the downstream application.
+    simp_opts.set_simplification_tol( tolerance );
+
+    // Call User's function to simplify each stitched body
+    ENTITY* entity_to_simplify = NULL;
+    output_bodies.init();
+    while (NULL != (entity_to_simplify = output_bodies.next()))
+    {
+      if( CUBIT_FAILURE == simplify_entity(entity_to_simplify, simp_opts) )
+      {
+        PRINT_ERROR("Tightening gaps failed, try healing beforehand.\n");
+        output_bodies.clear();
+        return CUBIT_FAILURE;
+      }
+    }
+  }
+
+  // **************************************************************
+  // Step 3 : Tighten Gaps to desired tightness
+  // (call api_tighten_gaps)
+  // **************************************************************
+  if(tighten_gaps)
+  {
+    // A user may want to tighten gaps in each of the stitched and simplified
+    // BODY so that the gaps in TEDGEs and TVERTEXs in
+    // the BODYs are within a "desired_gap_tightness" of the user's downstream
+    // application (like manufacturing).
+    BODY* body = NULL;
+    output_bodies.init();
+    while (NULL != (body = (BODY *)output_bodies.next()))
+    {
+      if( CUBIT_FAILURE == tighten_gaps_in_body(body, tolerance ) )
+      {
+        PRINT_ERROR("Tightening gaps failed, try healing beforehand.\n");
+        output_bodies.clear();
+        return CUBIT_FAILURE;
+      }
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+// ************************************************************
+// User function to stitch a list of entities
+// ************************************************************
+CubitStatus AcisModifyEngine::stitch_entities(ENTITY_LIST& to_be_stitched,
+                                       ENTITY_LIST& output_bodies,
+                                       tolerant_stitch_options& sopts)const
+{
+  // ENTITY_LIST& new_bodies will contain all the new bodies resulting
+  // from the API api_stitch. This list will be a subset of
+  // ENTITY_LIST& output_bodies. This list is provided so that it is
+  // convenient to the caller to find out the new bodies that the caller
+  // will have to take ownership of (for example, the users may have to register
+  // new bodies in their application and/or do memory management for those bodies).
+  ENTITY_LIST new_bodies;
+
+  // Make the careful option OFF to enable failsafe behavior.
+  // Note:  By default the "careful" option is already OFF
+  option_header *careful_opt = find_option("careful");
+  if (NULL != careful_opt)
+    careful_opt->push(FALSE);
+  // Note: To disable the failsafe behavior, set the "careful" option ON (push TRUE)
+
+  set_stitch_progress_callback( *stitch_process_callback );
+
+  AppUtil::instance()->progress_tool()->start(0, 100, "Stitching Progress:" );
+  // Make a call to api_stitch to stitch the entities in "to be stitched" list
+  outcome result_stch = api_stitch(to_be_stitched,
+    output_bodies,
+    new_bodies,
+    &sopts);
+
+  AppUtil::instance()->progress_tool()->end();
+
+  // Restore the original value of careful_opt
+  if (NULL != careful_opt)
+    careful_opt->pop();    
+
+  // Check and handle fatal problems reported by api_stitch
+  // User code to handle failure and exit.
+  if ( TRUE == handle_fatal_problem_reported_by_outcome(result_stch) )    
+  {
+    PRINT_ERROR("Stitching failed, try healing beforehand.\n");
+    return CUBIT_FAILURE;
+  }
+
+  /*
+  // User may want to know of the non fatal problems the API encoutered,
+  // and take corrective actions if any, before before proceeding to the next step.
+  //handle_problems_reported_by_outcome(result_stch);
+
+  // Pointer to an array of ENTITY_LIST pointers to store the coincident face
+  // cluster lists to allow list processing.
+  ENTITY_LIST* coin_face_list = NULL;
+
+  // Get the number of coincident faces clusters
+  int num_clusters = sopts.get_number_of_coincident_face_clusters();
+
+  // Check if coincident faces were detected
+  if ( num_clusters > 0 )
+  {
+    // Allocate memory based on the size of coincident face cluster list
+    coin_face_list = ACIS_NEW ENTITY_LIST[num_clusters];
+
+    // Now to go in a loop to collect each coincident face cluster
+    ENTITY_LIST* cluster = NULL;
+    int cluster_index = 0;
+    sopts.init_coincident_face_cluster_list();
+
+    while (NULL != (cluster = sopts.get_next_coincident_face_cluster()))
+    {
+      // deep copy list
+      coin_face_list[cluster_index] = *cluster;
+      cluster_index ++;
+    }
+
+    // Process each cluster (as an example, just print the size of each cluster).
+    // In practice, customers will probably want to exit to a handling routine
+    // which deletes items from the to_be_stitched list and recall api_stitch  
+    // again. The user may need to keep retrying this step until no coincident
+    // faces are detected anymore.
+    int i=0;
+    for (i = 0; i < num_clusters; i++)
+    {
+      int num_faces = coin_face_list[i].count();
+      PRINT_INFO("Number of faces in cluster %d = %d", i, num_faces);
+    }
+
+    // Delete the coincident faces cluster list.
+    if ( coin_face_list != NULL )
+    {
+      ACIS_DELETE [] coin_face_list;
+      coin_face_list = NULL;
+    }
+  } // end braces for "num_clusters > 0"
+  */
+
+  return CUBIT_SUCCESS;
+}
+
+// ************************************************************
+// User function to simplify an ENTITY
+// ************************************************************
+CubitStatus AcisModifyEngine::simplify_entity(ENTITY*& entity_to_simplify,
+                                      simplify_options& simp_opts)const
+{
+    // Make the careful option OFF to enable failsafe behavior.
+    // Note:  By default the "careful" option is already OFF
+    option_header *careful_opt = find_option("careful");
+    if (NULL != careful_opt)
+      careful_opt->push(FALSE);
+
+    // Call api_simplify_entity to simplify body.
+    outcome result_of_simplify = api_simplify_entity(entity_to_simplify, &simp_opts);
+
+    // Restore the original value of careful_opt
+    if (NULL != careful_opt)
+      careful_opt->pop();
+
+    // Check and handle fatal problems reported by api_simplify_entity
+    // User code to handle failure and exit.
+    if ( TRUE == handle_fatal_problem_reported_by_outcome(result_of_simplify) )
+      return CUBIT_FAILURE;
+
+    // User may want to know of the non fatal problems the
+    // api encoutered, and take corrective actions if any,
+    // before before proceeding to the next step.
+  //  handle_problems_reported_by_outcome(result_of_simplify);
+ 
+    return CUBIT_SUCCESS;
+}
+
+// ************************************************************
+// User function to tighten gaps in BODY
+// ************************************************************
+CubitStatus AcisModifyEngine::tighten_gaps_in_body(BODY*& body,
+                             const double& desired_gap_tightness)const
+{
+  // Make the careful option OFF to enable failsafe behavior.
+  // Note:  By default the "careful" option is already OFF
+  option_header *careful_opt = find_option("careful");
+  if (NULL != careful_opt)
+    careful_opt->push(FALSE);
+
+  // Call api_tighten_gaps on body with desired_gap_tightness.
+  outcome result_of_gap_tightening = api_tighten_gaps(body,
+    desired_gap_tightness);
+
+  // Restore the original value of careful_opt
+  if (NULL != careful_opt)
+    careful_opt->pop();
+
+  // Check and handle fatal problems reported by api_tighten_gaps
+  // User code to handle failure and exit.
+  if ( TRUE == handle_fatal_problem_reported_by_outcome(result_of_gap_tightening) )
+    return CUBIT_FAILURE;
+
+  // User may want to know of the non fatal problems the
+  // api encoutered, and take corrective actions if any,
+  // before before proceeding to the next step.
+  //handle_problems_reported_by_outcome(result_of_gap_tightening);
+
+  return CUBIT_SUCCESS;
+}
+
+bool AcisModifyEngine::handle_fatal_problem_reported_by_outcome(const outcome& api_outcome)const
+{
+  logical fatal = FALSE;
+
+  // Handle fatal errors of api
+  if ( !api_outcome.ok() )
+  {
+    AcisQueryEngine::instance()->ACIS_API_error ( api_outcome ); 
+    // User may want to know about the fatal error due to
+    // which the API failed
+    error_info* einf = api_outcome.get_error_info();
+
+    // User code to report information on errors. A sample
+    // function "display_problems_encountered" for such
+    // reporting is given at the bottom of the code
+    // snippet
+    display_problems_encountered(einf);
+
+    // Reasons for error
+    if (einf->has_reasons())
+    {
+      // User code to mention that the following are
+      // reasons for the error, the user may print it as
+      // printf("Following are the reasons for the error:\n");
+
+      // error_info_list owns all the error_info
+      // objects inside it and cleans them up on
+      // destruction. User need not worry about memory
+      // cleanup of the error_info objects.
+      error_info_list reasons_eil;
+      einf->reasons(reasons_eil);
+      const error_info* reason_einf = NULL;
+      for (reasons_eil.init(); NULL != (reason_einf =
+        reasons_eil.next());)
+      {
+        display_problems_encountered(reason_einf);
+      }
+    }
+
+    fatal = TRUE;
+  }  
+   return fatal;
+}
+
+void AcisModifyEngine::handle_problems_reported_by_outcome(const outcome& api_outcome) const
+{
+   if ( api_outcome.ok() )
+   {
+      // Problem reporting by API.
+      // API succeeded (either partially or fully) if this point
+      // is reached
+      error_info_list eil;
+      api_outcome.get_error_info_list(eil);
+      const error_info* einf = NULL;
+      for (eil.init(); NULL != (einf = eil.next());)
+      {
+           // User code to report information on problems. A
+           // sample function "display_problems_encountered" for
+           // such reporting is given at the bottom of the code
+           // snippet.
+           display_problems_encountered(einf);
+
+           // Reasons for the problem
+           if (einf->has_reasons())
+           {
+                // User code to mention that the following are
+                // reasons for the problem, the user may print it as
+                printf("Following are the reasons for the error:\n");
+
+                // error_info_list owns all the error_info
+                // objects inside it and cleans them up on
+                // destruction. User need not worry about memory
+                // cleanup of the error_info objects.
+                error_info_list reasons_eil;
+                einf->reasons(reasons_eil);
+                const error_info* reason_einf = NULL;
+                for (reasons_eil.init(); NULL != (reason_einf =
+                                                 reasons_eil.next());)
+                {
+                display_problems_encountered(reason_einf);
+               }
+            }
+         }
+      }
+}
+
+// ************************************************************
+// User function to report information on problems
+// ************************************************************
+void AcisModifyEngine::display_problems_encountered(const error_info *einf) const
+{
+  if ( NULL == einf )
+  { return; }
+  char const *err_message = einf->error_message();
+  spa_outcome_severity_type err_severity = einf->severity();
+
+  // User code to display message and severity
+  // for example, the user might do the following
+
+  PRINT_INFO("Problem encountered: %s\n", err_message);
+  if (SPA_OUTCOME_FATAL == err_severity)
+
+    // Represents a fatal error
+
+  { PRINT_INFO("Severity: FATAL \n"); }
+  else if (SPA_OUTCOME_ERROR == err_severity)
+
+    // Represents an error encountered by a failsafe routine
+    // during an atomic operation
+
+  { PRINT_INFO("Severity: ERROR \n"); }
+  else if (SPA_OUTCOME_PROBLEM == err_severity)
+
+    // Represents a problem encountered during an operation
+
+  { PRINT_INFO("Severity: PROBLEM \n"); }
+  else if (SPA_OUTCOME_INSANITY == err_severity)
+
+    // Represents an insanity in the model
+
+  { PRINT_INFO("Severity: INSANITY \n"); }
+  int ent_id_cnt = get_error_info_entity_id_count(einf);
+
+  // If ent_id_cnt returns positive count,
+  // then einf has atleast one entity, dead or live
+
+  if ( 0 < ent_id_cnt && einf->type() == entity_error_info::id() )
+  {
+    const entity_error_info* ent_einf = (const entity_error_info *)einf;
+    if ( 0 ) /* the user wants to report problems on dead entities too ) */
+      // LIVE and DEAD entities
+    {
+      for (int i = 0; i < ent_id_cnt; i++)
+      {
+        tag_id_type ent_id = ent_einf->get_entity_id(i);
+        ENTITY *err_entity = NULL;
+        outcome res_get_ent = api_get_entity_from_id(ent_id, err_entity);
+        if ( !res_get_ent.ok() )
+        {
+          // Handle API failure and continue or exit as caller thinks suitable       
+        }
+        if (NULL != err_entity) // err_entity is LIVE
+        {
+          // User code to report a live entity associated with a problem,
+          // for example the user may want to highlight the entity
+        }
+        else
+        {
+          // Report problem for a dead entity
+        }
+      }
+    }
+    else // Only LIVE entities
+    {
+      ENTITY_LIST live_entities;
+      ent_einf->get_entities_alive(live_entities);
+      ENTITY *live_err_entity = NULL;
+      for (live_entities.init(); NULL != (live_err_entity = live_entities.next()); )
+      {
+        // User code to report a live entity associated with a problem,
+        // for example the user may want to highlight the entity
+      }
+    }
+  }
+}
+
+CubitStatus AcisModifyEngine::finish_webcut( 
+      BODY *tool_BODY,
+      DLIList<BodySM*> &original_bodysm_list, //original BodySMs of successfully webcut bodies
+      DLIList<BODY*> &original_BODY_list, //original ACIS BODYs
+      DLIList<BODY*> &new_webcut_BODY_list, //BODYs resulting from successful webcuts
+      DLIList<BodySM*> &neighbor_imprint_list, //neighbor BodySMs that need to be imprinted
+                                               //with bodies that were successfully webcut
+      ImprintType imprint_type,
+      DLIList<BodySM*> &results_list ) const
+{
+  CubitBoolean delete_bodies = (GeometryModifyTool::instance()->get_new_ids() ?
+                                CUBIT_FALSE : CUBIT_TRUE);
+
+  int i,j;
+  DLIList<BodySM*> imprinted_neighbor_bodysms;
+  DLIList<BODY*> original_imprinted_neighbor_BODYs;
+  DLIList<BODY*> new_imprinted_neighbor_BODYs;
+
+  //normal imprint--w/ neighbors
+  if( imprint_type == ONLY_INVOLVED_BODIES || 
+      imprint_type == INCLUDE_NEIGHBORS  )
+  {
+    BODY* first_BODY_ptr = NULL;
+    BODY* second_BODY_ptr = NULL;
+
+    //imprint only involved bodies first
+    for (i=0; i< (new_webcut_BODY_list.size() - 1); i++)
+    {
+      first_BODY_ptr = new_webcut_BODY_list.get_and_step();
+      
+      for (j=(i + 1); j<new_webcut_BODY_list.size(); j++)
+      {
+        second_BODY_ptr = new_webcut_BODY_list.get_and_step();
+        imprint_BODYs( first_BODY_ptr, second_BODY_ptr );
+      }
+
+      new_webcut_BODY_list.reset() ;
+      new_webcut_BODY_list.step(i+1) ;
+    }
+
+    //now imprint with the neighbors
+    if( imprint_type == INCLUDE_NEIGHBORS  )
+    {
+      // Loop over all the neighboring Bodies
+      for (i=neighbor_imprint_list.size(); i--;)
+      {
+        BODY *neighbor_BODY_copy = NULL;
+
+        // Get this existing Body's parent ACIS BODY
+        BodySM *neighbor_bodysm = neighbor_imprint_list.get_and_step() ;
+        BODY *neighbor_BODY= AcisQueryEngine::get_BODY(neighbor_bodysm) ;
+        if( neighbor_BODY == NULL )
+          continue;
+        
+        //exclude the tool body from the neighbor imprint
+        if ((tool_BODY && neighbor_BODY  == tool_BODY ) || 
+            original_bodysm_list.move_to(neighbor_bodysm))
+        {
+          // Don't do anything
+          continue;
+        }
+        
+        for(j=new_webcut_BODY_list.size(); j--; )
+        {
+          BODY *new_webcut_BODY = new_webcut_BODY_list.get_and_step(); 
+        
+          if ( BODYs_interfering(new_webcut_BODY, neighbor_BODY) == CUBIT_TRUE )
+          {
+            if ( neighbor_BODY_copy == NULL ) //Haven't made a copy yet
+            {
+              neighbor_BODY_copy = this->copy_BODY( neighbor_BODY,
+                                              GeometryModifyTool::instance()->get_new_ids());
+
+              if (neighbor_BODY_copy == NULL)
+              {
+                PRINT_ERROR("Cannot test imprinting for volume.\n" );
+                break;
+              }
+              else
+              {
+                imprinted_neighbor_bodysms.append( neighbor_bodysm );
+                original_imprinted_neighbor_BODYs.append( neighbor_BODY );
+                new_imprinted_neighbor_BODYs.append( neighbor_BODY_copy );
+              }
+            }
+
+            imprint_BODYs(new_webcut_BODY, neighbor_BODY_copy);
+
+          }
+        }
+      }
+    }
+  }
+
+
+  //Now create the new BodySMs 
+  new_webcut_BODY_list.reset();
+  original_bodysm_list.reset();
+  original_BODY_list.reset();
+
+  for ( i=0; i<new_webcut_BODY_list.size(); i+=2 )
+  {
+    //Get the original BodySM and BODY
+    BodySM *old_Body = original_bodysm_list.get_and_step();
+    BODY *old_BODY = original_BODY_list.get_and_step();
+
+    //Get the resulting 2 BODYs
+    DLIList<BODY*> temp_BODY_list;
+    BODY *webcut_BODY_ptr = new_webcut_BODY_list.get_and_step();
+    temp_BODY_list.append(webcut_BODY_ptr);
+    webcut_BODY_ptr = new_webcut_BODY_list.get_and_step();
+    temp_BODY_list.append(webcut_BODY_ptr);
+
+    //Obtain the new BodySMs
+    DLIList<BodySM*> new_bodysm_list;
+    CubitStatus status = get_new_Body( old_Body, old_BODY, 
+                                       temp_BODY_list, new_bodysm_list,
+                                       false, delete_bodies );
+
+    if (status == CUBIT_FAILURE) 
+      PRINT_ERROR("Failed to build new volume in AGE::webcut.\n");
+
+    // if we didn't get any new bodies back from get_new_Body,
+    // that means that an imprinted body wasn't really imprinted
+    if (new_bodysm_list.size() > 0) 
+    {
+      temp_BODY_list.reset();
+      new_bodysm_list.reset();
+      for (int j = 0; j < new_bodysm_list.size(); j++) 
+      {
+        BodySM *new_body_ptr = new_bodysm_list.get_and_step();
+        results_list.append_unique(new_body_ptr);
+      }
+    }
+  }
+
+  //make new BodySMs if you have done normal imprinting w/ neighbors
+  if( imprint_type == INCLUDE_NEIGHBORS  )
+  {
+    imprinted_neighbor_bodysms.reset();
+    original_imprinted_neighbor_BODYs.reset();
+    new_imprinted_neighbor_BODYs.reset();
+    for( i=imprinted_neighbor_bodysms.size(); i--; )
+    {
+      BodySM *original_bodysm = imprinted_neighbor_bodysms.get_and_step();
+      BODY *old_BODY = original_imprinted_neighbor_BODYs.get_and_step();
+      BODY *new_BODY = new_imprinted_neighbor_BODYs.get_and_step();
+
+      BodySM* new_Body = get_new_Body( original_bodysm, old_BODY, new_BODY, 
+                                       false, true, true );
+      if (new_Body)
+        results_list.append(new_Body);
+      else
+        results_list.append(original_bodysm); //because unaltered bodies 
+                                              //may need to be merged
+    }
+  }
+
+
+
+  //Tolerant imprinting
+  if( imprint_type == TOL_IMPRINT ||
+      imprint_type == TOL_IMPRINT_INCLUDE_NEIGHBORS )
+  {
+    //If any virtual geometry got modified, we cannot do 
+    //subsequent tolerant imprinting.  Check the model for any
+    //problems.
+    for( i=results_list.size(); i--; )
+    {
+      DLIList<Surface*> body_surfs;
+      BodySM *tmp_body = results_list.get_and_step();
+
+      tmp_body->surfaces( body_surfs );
+
+      int j;
+      for( j=body_surfs.size(); j--; )
+      {
+        Surface *tmp_surf = body_surfs.get_and_step();
+        DLIList<LoopSM*> tmp_loops;
+        tmp_surf->loopsms( tmp_loops );
+
+        int l;
+        for( l=tmp_loops.size(); l--; )
+        {
+          LoopSM* tmp_loop = tmp_loops.get_and_step();
+          DLIList<CoEdgeSM*> tmp_coedges;
+          tmp_loop->coedgesms( tmp_coedges );
+
+          int m;
+          for( m=tmp_coedges.size(); m--; )
+          {
+            DLIList<Curve*> tmp_curves;
+            CoEdgeSM *coedge = tmp_coedges.get_and_step();
+            coedge->curves( tmp_curves );
+            if( tmp_curves.size() == 0 )
+            {
+              PRINT_WARNING("Virtual geometry modified in webcut.  Cannot do\n"
+                            "         subsequent tolerant imprinting\n" );
+              return CUBIT_SUCCESS;
+            }
+          }
+        } 
+      }
+    } 
+
+    results_list.reset();
+    double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+    //imprint all new BodySMs with each other 
+    for (i=0; i< (results_list.size() - 1); i++)
+    {
+      BodySM *bodysm_1 = results_list.get_and_step();
+      CubitBox bbox1 = bodysm_1->bounding_box();
+      
+      for (j=(i + 1); j<results_list.size(); j++)
+      {
+        BodySM *bodysm_2 = results_list.get_and_step();
+        CubitBox bbox2 = bodysm_2->bounding_box();
+        
+        if( bbox1.overlap( tolerance, bbox2 ) )
+        {
+          DLIList<BodySM*> bodies_in(2), bodies_out;
+          bodies_in.append( bodysm_1 );
+          bodies_in.append( bodysm_2 );
+          tolerant_imprint( bodies_in, bodies_out, NULL, NULL );
+        }
+      }
+      results_list.reset() ;
+      results_list.step(i+1) ;
+    }
+
+    if( imprint_type == TOL_IMPRINT_INCLUDE_NEIGHBORS )
+    {
+      DLIList<BodySM*> imprinted_neighbors;
+
+      for( i=neighbor_imprint_list.size(); i--; )
+      {
+        BodySM *neighbor_body = neighbor_imprint_list.get_and_step();
+        CubitBox neighbor_box = neighbor_body->bounding_box();
+    
+        for( j=results_list.size(); j--; )
+        {
+          BodySM *webcut_body = results_list.get_and_step();
+          CubitBox bbox = webcut_body->bounding_box();
+
+          if( neighbor_box.overlap( tolerance, bbox ) )
+          {
+            DLIList<BodySM*> bodies_in(2), bodies_out;
+            bodies_in.append( neighbor_body );
+            bodies_in.append( webcut_body );
+            tolerant_imprint( bodies_in, bodies_out, NULL, NULL );
+            imprinted_neighbors.append_unique( neighbor_body ); 
+          }
+        }
+      }
+
+      results_list += imprinted_neighbors;
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+             
+void AcisModifyEngine::start_tracking_history( DLIList<TopologyBridge*> &bridges,
+                                               AcisHistory &history_object, 
+                                               bool ignore_parents )
+{
+  GeometryQueryTool::instance()->history().clear();
+
+  //get all RefEntities from the bridges
+  
+  bool debug = false;
+  int i,j;
+  for( i=bridges.size(); i--; )
+  {
+    //lets assume that it's a body we're modifying
+    
+    DLIList<BodySM*> body_tbs;
+    DLIList<Lump*> lump_tbs;
+    DLIList<Surface*> surface_tbs;
+    DLIList<Curve*> curve_tbs;
+    DLIList<Point*> vertex_tbs;
+
+    TopologyBridge *tb = bridges.get_and_step();
+    
+    //don't bother putting attribute on parents
+    if( ignore_parents )
+    {
+      //only the case if you have a surface, curve, or vertex
+      if( CAST_TO(tb, Surface ) )
+      {
+        tb->surfaces( surface_tbs );
+        tb->curves( curve_tbs );
+        tb->points( vertex_tbs );
+      }
+      else if( CAST_TO(tb, Curve) )
+      {
+        tb->curves( curve_tbs );
+        tb->points( vertex_tbs );
+      }
+      else if( CAST_TO(tb, Point ) )
+        tb->points( vertex_tbs );
+
+    }
+    else
+    {
+      tb->bodysms( body_tbs );
+      assert(body_tbs.size() == 1 );
+      body_tbs.get()->lumps( lump_tbs );
+      body_tbs.get()->surfaces( surface_tbs );
+      body_tbs.get()->curves( curve_tbs );
+      body_tbs.get()->points( vertex_tbs );
+    }
+ 
+    //Attach history attributes to all bodies, volumes, surfaces, 
+    //curves and vertices
+
+    //bodies
+    for( j=body_tbs.size(); j--; )
+    {
+      //get the RefEntity
+      BodySM *bodysm = body_tbs.get_and_step();
+      TopologyEntity *te = bodysm->topology_entity();
+      RefEntity *ref_ent = CAST_TO( te, RefEntity );
+
+      if( NULL == ref_ent )
+      {
+        DLIList<TopologyBridge*> tbs;
+        GeometryQueryTool::instance()->get_tbs_with_bridge_manager_as_owner( bodysm, tbs );
+        te = tbs.get()->topology_entity();
+        ref_ent = CAST_TO( te, RefEntity );
+      } 
+
+      //get the Acis ENTITY
+      ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( bodysm );
+
+      //if there's an attribute there already, get rid of it
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+      if( att && att->deletable() )
+      {
+        att->unhook();
+        att->lose();
+      }
+      else if( att )
+      {
+//        att->unhook();
+//        PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+      }
+
+      //create the history attrib on the entity if it doesn't exist already
+      att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+      int tracking_id = history_object.generate_next_tracking_id();
+      att->add_tracking_id( tracking_id );
+      if( debug )
+        PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+        ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+      history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+    }
+
+    //lumps (volumes)
+    for( j=lump_tbs.size(); j--; )
+    {
+      //get the RefEntity
+      Lump *lump = lump_tbs.get_and_step();
+      TopologyEntity *te = lump->topology_entity();
+      RefEntity *ref_ent = CAST_TO( te, RefEntity );
+
+      //get the Acis ENTITY
+      ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( lump );
+      
+      //if there's an attribute there already, get rid of it
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+      if( att && att->deletable() )
+      {
+        att->unhook();
+        att->lose();
+      }
+      else if( att )
+      {
+ //       att->unhook();
+        PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+      }
+
+      //create the history attrib on the entity if it doesn't exist already
+      att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+      int tracking_id = history_object.generate_next_tracking_id();
+      att->add_tracking_id( tracking_id );
+      if( debug )
+        PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+        ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+      history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+      //add ENTITY to list in case of failure
+      history_object.add_ENTITY( entity );
+    }
+
+    //surfaces
+    for( j=surface_tbs.size(); j--; )
+    {
+      //get the RefEntity
+      Surface *surf = surface_tbs.get_and_step();
+      TopologyEntity *te = surf->topology_entity();
+      RefEntity *ref_ent = CAST_TO( te, RefEntity );
+
+      //Check to see that the entity is a SurfaceACIS
+      SurfaceACIS *surf_acis = CAST_TO( surf, SurfaceACIS );
+      if( surf_acis )
+      {
+        //get the Acis ENTITY
+        ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( surf );
+      
+        //if there's an attribute there already, get rid of it
+        ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+        if( att && att->deletable() )
+        {
+          att->unhook();
+          att->lose();
+        }
+        else if( att )
+        {
+  //        att->unhook();
+          PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+        }
+
+        //create the history attrib on the entity if it doesn't exist already
+        att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+        int tracking_id = history_object.generate_next_tracking_id();
+        att->add_tracking_id( tracking_id );
+        if( debug )
+          PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+          ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+        history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+        //add ENTITY to list in case of failure
+        history_object.add_ENTITY( entity );
+      }
+      else
+      {
+        DLIList<TopologyBridge*> hidden_surfaces;
+        GeometryQueryEngine *gqe = surf->get_geometry_query_engine();
+        gqe->get_underlying_surfaces( surf, hidden_surfaces );
+        
+        int k;
+        for(k=hidden_surfaces.size(); k--; )
+        {
+          //get the Acis ENTITY
+          ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( hidden_surfaces.get_and_step() );
+        
+          //if there's an attribute there already, get rid of it
+          ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+          if( att && att->deletable() )
+          {
+            att->unhook();
+            att->lose();
+          }
+          else if( att )
+          {
+   //         att->unhook();
+            PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+          }
+
+          //create the history attrib on the entity if it doesn't exist already
+          att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+          int tracking_id = history_object.generate_next_tracking_id();
+          att->add_tracking_id( tracking_id );
+          if( debug )
+            PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+            ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+          history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+          //add ENTITY to list in case of failure
+          history_object.add_ENTITY( entity );
+        }
+      }
+    }
+
+    //curves
+    for( j=curve_tbs.size(); j--; )
+    {
+      //get the RefEntity
+      Curve *curve = curve_tbs.get_and_step();
+      TopologyEntity *te = curve->topology_entity();
+      RefEntity *ref_ent = CAST_TO( te, RefEntity );
+
+      //Check to see that the entity is a SurfaceACIS
+      CurveACIS *curve_acis = CAST_TO( curve, CurveACIS );
+      if( curve_acis )
+      {
+        //get the Acis ENTITY
+        ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( curve );
+        
+        //if there's an attribute there already, get rid of it
+        ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+        if( att && att->deletable() )
+        {
+          att->unhook();
+          att->lose();
+        }
+        else if( att )
+        {
+    //      att->unhook();
+          PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+        }
+
+        //create the history attrib on the entity if it doesn't exist already
+        att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+        int tracking_id = history_object.generate_next_tracking_id();
+        att->add_tracking_id( tracking_id );
+        if( debug )
+          PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+          ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+        history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+        //add ENTITY to list in case of failure
+        history_object.add_ENTITY( entity );
+      }
+      else
+      {
+        DLIList<TopologyBridge*> hidden_curves;
+        GeometryQueryEngine *gqe = curve->get_geometry_query_engine();
+        gqe->get_underlying_curves( curve, hidden_curves );
+        
+        int k;
+        for(k=hidden_curves.size(); k--; )
+        {
+          ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( hidden_curves.get_and_step() );
+        
+          //if there's an attribute there already, get rid of it
+          ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+          if( att && att->deletable() )
+          {
+            att->unhook();
+            att->lose();
+          }
+          else if( att )
+          {
+     //       att->unhook();
+            PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+          }
+
+          //create the history attrib on the entity if it doesn't exist already
+          att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+          int tracking_id = history_object.generate_next_tracking_id();
+          att->add_tracking_id( tracking_id );
+          if( debug )
+            PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+            ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+          history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+          //add ENTITY to list in case of failure
+          history_object.add_ENTITY( entity );
+        }
+      }
+    }
+
+    //vertices
+    for( j=vertex_tbs.size(); j--; )
+    {
+      //get the RefEntity
+      Point *point = vertex_tbs.get_and_step();
+      TopologyEntity *te = point->topology_entity();
+      RefEntity *ref_ent = CAST_TO( te, RefEntity );
+
+      PointACIS *point_acis = CAST_TO( point, PointACIS );
+      if( point_acis )
+      {
+        //get the Acis ENTITY
+        ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( point );
+        
+        //if there's an attribute there already, get rid of it
+        ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+        if( att && att->deletable() )
+        {
+          att->unhook();
+          att->lose();
+        }
+        else if( att )
+        {
+      //    att->unhook();
+          PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+        }
+
+        //create the history attrib on the entity if it doesn't exist already
+        att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+        int tracking_id = history_object.generate_next_tracking_id();
+        att->add_tracking_id( tracking_id );
+        if( debug )
+          PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+          ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+        history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+        //add ENTITY to list in case of failure
+        history_object.add_ENTITY( entity );
+      }
+      else
+      {
+        DLIList<TopologyBridge*> hidden_vertex;
+        GeometryQueryEngine *gqe = point->get_geometry_query_engine();
+        gqe->get_underlying_bridges( point, hidden_vertex );
+        
+        if( hidden_vertex.size() )
+        {
+          PointACIS *point_acis = CAST_TO( hidden_vertex.get(), PointACIS );
+          //may have to go a level deeper -- compositing a partitioned curve
+          if( NULL == point_acis )
+          {
+            Point *tmp_point = CAST_TO( hidden_vertex.get(), Point );
+            hidden_vertex.clean_out();
+            gqe->get_underlying_bridges( tmp_point , hidden_vertex );
+          }
+        }
+        else //could be just a partition point..so no real underlying point
+          continue;
+
+        if( hidden_vertex.size() == 0 )
+          continue;
+        
+        ENTITY *entity = AcisQueryEngine::instance()->get_ENTITY_of_entity( hidden_vertex.get() );
+        
+        //if there's an attribute there already, get rid of it
+        ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( entity  );
+        if( att && att->deletable() )
+        {
+       //   att->unhook();
+          att->lose();
+        }
+        else if( att )
+        {
+          att->unhook();
+          PRINT_INFO("---------------------Still have attrib around but can't delete it!\n");
+        }
+
+        //create the history attrib on the entity if it doesn't exist already
+        att = ATTRIB_HISTORY::get_history_attrib( entity, true, &history_object );
+        int tracking_id = history_object.generate_next_tracking_id();
+        att->add_tracking_id( tracking_id );
+        if( debug )
+          PRINT_INFO("RefEntity %s %d ---> ENTITY = %d w/ attrib %p\n", 
+          ref_ent->class_name(), ref_ent->id(), tracking_id, att ); 
+        history_object.add_refentity_tracking_id_pair( ref_ent, tracking_id );
+
+        //add ENTITY to list in case of failure
+        history_object.add_ENTITY( entity );
+      }
+    } 
+  }
+}
+
+void AcisModifyEngine::stop_tracking_history( DLIList<BodySM*> &new_bodies,
+                                              AcisHistory &history_object )
+{
+  DLIList<TopologyBridge*> tbs;
+  CAST_LIST( new_bodies, tbs, TopologyBridge );
+  
+  stop_tracking_history( tbs, history_object );
+}
+
+
+void AcisModifyEngine::stop_tracking_history( DLIList<TopologyBridge*> &new_tbs,
+                                              AcisHistory &history_object )
+{
+  DLIList<ENTITY*> ents_with_attribs; 
+  DLIList<Point*> tmp_vertex_tbs;
+
+  //map tracking ids to TB
+  int i;
+  for( i=new_tbs.size(); i--; )
+  {
+    //get all the TopologyBridges of Bodies, Lumps, Surfaces, Curves, and Vertices
+    DLIList<Lump*> lump_tbs;
+    DLIList<Surface*> surface_tbs;
+    DLIList<Curve*> curve_tbs;
+    DLIList<Point*> vertex_tbs;
+    DLIList<BodySM*> body_tbs;
+    
+    TopologyBridge *tmp_tb = new_tbs.get_and_step();
+    
+    tmp_tb->bodysms( body_tbs );
+    assert( body_tbs.size() < 2 );
+
+    tmp_tb->lumps( lump_tbs );
+    tmp_tb->surfaces( surface_tbs );
+    tmp_tb->curves( curve_tbs );
+    tmp_tb->points( vertex_tbs );
+  
+    tmp_vertex_tbs += vertex_tbs;
+
+    //collect a list of events leading back to the RefEntity
+    //PRINT_INFO("BODY\n");
+  
+
+    if( body_tbs.size() )
+    {
+      BodySM *bodysm = body_tbs.get();
+      ENTITY *tmp_ent = AcisQueryEngine::instance()->get_ENTITY_of_entity( bodysm ); 
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( tmp_ent, false ); 
+      if( att ) 
+      {
+        std::set<int> tracking_ids = att->get_tracking_ids();
+        history_object.add_to_tracking_ids_tb_map( tracking_ids, bodysm );
+        ents_with_attribs.append( tmp_ent );
+      }
+    }
+  
+    int j;
+    //PRINT_INFO("LUMPS\n");
+    for( j=lump_tbs.size(); j--; )
+    {
+      TopologyBridge *tmp_bridge = lump_tbs.get_and_step();
+      ENTITY *tmp_ent = AcisQueryEngine::instance()->get_ENTITY_of_entity( tmp_bridge ); 
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( tmp_ent, false ); 
+      if( att )
+      {
+        std::set<int> tracking_ids = att->get_tracking_ids();
+        history_object.add_to_tracking_ids_tb_map( tracking_ids, tmp_bridge);
+        ents_with_attribs.append( tmp_ent );
+      }
+    }
+
+    //PRINT_INFO("FACES\n");
+    for( j=surface_tbs.size(); j--; )
+    {
+      TopologyBridge *tmp_bridge = surface_tbs.get_and_step();
+      SurfaceACIS *surf_acis = CAST_TO( tmp_bridge, SurfaceACIS );
+      if( NULL == surf_acis )
+        continue;
+      ENTITY *tmp_ent = AcisQueryEngine::instance()->get_ENTITY_of_entity( tmp_bridge ); 
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( tmp_ent, false ); 
+      if( att )
+      {
+        std::set<int> tracking_ids = att->get_tracking_ids();
+        history_object.add_to_tracking_ids_tb_map( tracking_ids, tmp_bridge );
+        ents_with_attribs.append( tmp_ent );
+      }
+    }
+
+    //PRINT_INFO("EDGES\n");
+    for( j=curve_tbs.size(); j--; )
+    {
+      TopologyBridge *tmp_bridge = curve_tbs.get_and_step();
+      CurveACIS *curve_acis = CAST_TO( tmp_bridge, CurveACIS );
+      if( NULL == curve_acis )
+        continue;
+      ENTITY *tmp_ent = AcisQueryEngine::instance()->get_ENTITY_of_entity( tmp_bridge ); 
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( tmp_ent, false ); 
+      if( att )
+      {
+        std::set<int> tracking_ids = att->get_tracking_ids();
+        history_object.add_to_tracking_ids_tb_map( tracking_ids, tmp_bridge );
+        ents_with_attribs.append( tmp_ent );
+      }
+    }
+
+    //PRINT_INFO("VERTICES\n");
+    for( j=vertex_tbs.size(); j--; )
+    {
+      TopologyBridge *tmp_bridge = vertex_tbs.get_and_step();
+      PointACIS *pt_acis = CAST_TO( tmp_bridge, PointACIS );
+      if( NULL == pt_acis )
+        continue;
+      ENTITY *tmp_ent = AcisQueryEngine::instance()->get_ENTITY_of_entity( tmp_bridge ); 
+      ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( tmp_ent, false ); 
+      if( att )
+      {
+        std::set<int> tracking_ids = att->get_tracking_ids();
+        history_object.add_to_tracking_ids_tb_map( tracking_ids, tmp_bridge );
+        ents_with_attribs.append( tmp_ent );
+      }
+    }
+  }
+
+  //now sort what happened 
+  history_object.create_cgm_history_objects();   
+  //history_object.print();
+  GeometryQueryTool::instance()->history().print_port_events();
+
+/*
+  //strip off attributes -- 
+  for( i=0; i<ents_with_attribs.size(); i++ )
+  {
+    ATTRIB_HISTORY *att = ATTRIB_HISTORY::get_history_attrib( ents_with_attribs.get_and_step(), false ); 
+    if( att )
+    {
+      att->unhook();
+      att->lose();
+    }
+  }
+*/
+  //TODO: get this working. 
+  ATTRIB_HISTORY::remove_all_attribs();
+
+}
+                                             
+

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisModifyEngine.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -19,6 +19,7 @@
 #include "AcisQueryEngine.hpp"
 
 #include <set>
+#include <map>
 
 class ENTITY;
 class ENTITY_LIST;
@@ -55,6 +56,9 @@
 class LoopSM;
 class Curve;
 class Point;
+class tolerant_stitch_options;
+class simplify_options;
+class error_info;
 
 class AcisBridge;
 class BodyACIS;
@@ -66,6 +70,7 @@
 class CurveACIS;
 class PointACIS;
 class BodySM;
+class AcisHistory;
 
 class CubitBox;
 class CubitString;
@@ -87,6 +92,9 @@
   friend class AcisHealerTool;
   friend class AcisSurfaceTool;
   friend class AcisTweakTool;
+#ifdef ACIS_TWEAK
+  friend class AcisTweakToolCAT;
+#endif
   friend class AcisEdgeTool;
   friend class AcisToolUtil;
   friend class AcisBridge;
@@ -121,6 +129,10 @@
   static AcisModifyEngine* instance_;
   
   std::set<AcisBridge*> deactivatedSet;
+
+  virtual bool supports_interoperability() { return true; }
+    //- Returns whether intermixing of real and virtual geometry operations
+    //- is supported for the current geometry kernel.
   
   bool bridge_deactivated(AcisBridge*) const;
   CubitStatus deactivate_bridge(AcisBridge*) const;
@@ -246,6 +258,7 @@
                                BodySM*& newBody1, 
                                BodySM*& newBody2,
                                bool keep_old = false) const ;
+  
   virtual CubitStatus imprint(DLIList<BodySM*> &from_body_list,
                               DLIList<BodySM*> &new_from_body_list,
                                bool keep_old = false,
@@ -258,6 +271,7 @@
   virtual CubitStatus imprint( DLIList<BodySM*> &body_list,
                                DLIList<Curve*> &ref_edge_list,
                                DLIList<BodySM*>& new_body_list,
+                               DLIList<TopologyBridge*> &temporary_bridges,
                                bool keep_old_body,
                                bool show_messages = true) const;
     //- Imprints a list of Bodies with a list of RefEdges.  All entities must
@@ -266,6 +280,7 @@
 
   virtual CubitStatus imprint( DLIList<Surface*> &surface_list,
                                DLIList<Curve*> &curve_list,
+                               DLIList<TopologyBridge*> &temporary_bridges,
                                DLIList<BodySM*>& new_body_list,
                                bool keep_old_body ) const;
     //- Imprints a list of RefFaces with a list of RefEdges.  This is
@@ -276,7 +291,10 @@
   virtual CubitStatus imprint( DLIList<Surface*> &surface_list,
                                DLIList<DLIList<Curve*>*> &curve_lists_list,
                                BodySM*& new_body,
-                               bool keep_old_body ) const;
+                               bool keep_old_body,
+                               bool expand = true,
+                               DLIList<TopologyBridge*> *new_tbs = NULL,
+                               DLIList<TopologyBridge*> *att_tbs = NULL ) const;
     //- Imprints a list of Surfaces with list of Curves, sorted per
     //- Surface (ie., curve_lists_list is same length as surface_list).
     //- This version is more efficient than the general-purpose one
@@ -288,7 +306,9 @@
                                DLIList<BodySM*>& new_body_list,
                                bool keep_old_body,
                                DLIList<TopologyBridge*> *new_tbs = NULL,
-                               DLIList<TopologyBridge*> *att_tbs = NULL ) const;
+                               DLIList<TopologyBridge*> *att_tbs = NULL,
+                               double *tol_in = NULL,
+                               bool clean_up_slivers = true) const;
     //- Imprints a list of bodies with a list of vectors.  Useful for
     //- splitting curves and creating hardpoints on surfaces.
 
@@ -310,18 +330,39 @@
     //- Imprints a list of Bodies with a list of RefEdges which are projected
     //- to a list of RefFaces
 
+  virtual CubitStatus remove_topology(DLIList<Curve*> &curves_to_remove,
+                                       DLIList<Surface*> &surfs_to_remove,
+                                       double backoff_distance,
+                                       double small_edge_size,
+                                       DLIList<BodySM*> &new_bodysm_list,
+                                       CubitBoolean preview) const;
+
+  virtual CubitStatus tolerant_imprint_surface_with_curves(
+                                         Surface *surface_to_imprint,
+                                         DLIList<Curve*> &curves,
+                                         DLIList<TopologyBridge*> &temporary_bridges,
+                                         BodySM *&new_body,
+                                         DLIList<TopologyBridge*> *new_tbs = NULL,
+                                         DLIList<TopologyBridge*> *att_tbs = NULL ) const;
+  //Imprints a surface with passed-in curves.  Can imprint successfully
+  //and expectedly with sloppy/dirty geometry.  
+
   virtual CubitStatus tolerant_imprint( DLIList<BodySM*> &bodies_in,
                                         DLIList<BodySM*> &new_bodies,
                                         DLIList<TopologyBridge*> *new_tbs,
                                         DLIList<TopologyBridge*> *att_tbs ) const;
   //Imprints a list of bodies with each other.  Can imprint successfully
   //and expectedly with sloppy/dirty models.  
+  virtual CubitStatus tolerant_imprint(DLIList<Surface*> &surfs_in,
+                                       DLIList<BodySM*> &new_bodysm_list) const;
 
   virtual CubitStatus project_edges( DLIList<Surface*> &ref_face_list,
                                      DLIList<Curve*> &ref_edge_list_in,
                                      DLIList<Curve*> &ref_edge_list_new,
                                      bool print_error = true ) const;
     //- Projects list RefEdges to a list of RefFaces
+  virtual void get_possible_invalid_tbs(DLIList<TopologyBridge*> &bridges_in,
+                             DLIList<TopologyBridge*> &bridges_out);
 
   virtual CubitStatus intersect( BodySM* tool_body_ptr,
                                  DLIList<BodySM*> &from_bodies,
@@ -452,7 +493,19 @@
 			     Surface *stop_surf = NULL,
                              BodySM*  stop_body = NULL) const;
 
+  virtual CubitStatus sweep_to_body(
+                             DLIList<Curve*> curve_list,
+                             BodySM *target_body,
+                             CubitVector distance,
+                             DLIList<BodySM*> &new_bodies,
+                             bool unite) const;
 
+  virtual CubitStatus sweep_to_body(
+                             Surface *source_surface,
+                             BodySM *target_body,
+                             CubitVector distance,
+                             DLIList<BodySM*> &new_bodies) const;
+
 //HEADER- Functions for webcut operations
 
   virtual CubitStatus webcut( 
@@ -460,8 +513,10 @@
                       const CubitVector &v1,
                       const CubitVector &v2,
                       const CubitVector &v3,
+                      DLIList<BodySM*>& neighbor_imprint_list,
                       DLIList<BodySM*>& results_list,
-                      bool imprint = false ) const;
+                      ImprintType imprint_type = NO_IMPRINT,
+                      bool preview = false) const ;
     //R int
     //R- Number of bodies that were webcut ( >= 0 )
     //I webcut_body_list
@@ -478,11 +533,12 @@
     //- The newly created bodies are merged and imprinted depeding on
     //- the respective flags.
 
-  virtual CubitStatus webcut( 
-            DLIList<BodySM*>& webcut_body_list,
-            BodySM const* tool_body,
-            DLIList<BodySM*>& results_list,
-            bool imprint  = false) const;
+  virtual CubitStatus webcut( DLIList<BodySM*>& webcut_body_list,
+                              BodySM const* tool_body,
+                              DLIList<BodySM*>& neighbor_imprint_list,
+                              DLIList<BodySM*>& results_list,
+                              ImprintType imprint_type = NO_IMPRINT,
+                              bool preview = false) const ;
     //R int
     //R- Number of bodies that were webcut ( >= 0 )
     //I webcut_body_list
@@ -504,8 +560,10 @@
                                     double radius,
                                     const CubitVector &axis,
                                     const CubitVector &center,
+                                    DLIList<BodySM*>& neighbor_imprint_list,
                                     DLIList<BodySM*>& results_list,
-                                    bool imprint = false );
+                                    ImprintType imprint_type = NO_IMPRINT,
+                                    CubitBoolean preview = false);
 */
     //- cores the bodies with a cylinder formed by the given
     //- parameters and the height larger than the model.
@@ -515,8 +573,10 @@
                                  const CubitVector &center,
                                  const CubitVector axes[3], 
                                  const CubitVector &extension,
+                                 DLIList<BodySM*>& neighbor_imprint_list,
                                  DLIList<BodySM*> &results_list,
-                                 bool imprint = false );
+                                 ImprintType imprint_type = NO_IMPRINT,
+                                 CubitBoolean preview = false);
 */
   /**<  Webcuts the bodies in the list with a cutting brick.
     *  The brick is created by the given parameters - center of
@@ -531,8 +591,10 @@
                                         const CubitVector &center,
                                         const CubitVector axes[2],
                                         double width, double height,
+                                        DLIList<BodySM*>& neighbor_imprint_list,
                                         DLIList<BodySM*> &results_list,
-                                        bool imprint = false );
+                                        ImprintType imprint_type = NO_IMPRINT,
+                                        bool preview = false );
 */
   /**<  Webcuts the bodies in the list with a cutting planar sheet.
     *  The sheet is created by the given parameters - center of
@@ -543,8 +605,10 @@
   virtual CubitStatus webcut_with_curve_loop( 
                                       DLIList<BodySM*> &webcut_body_list,
                                       DLIList<Curve*> &ref_edge_list,
+                                      DLIList<BodySM*>& neighbor_imprint_list,
                                       DLIList<BodySM*>& results_list,
-                                      bool imprint = false);
+                                      ImprintType imprint_type = NO_IMPRINT,
+                                      bool preview = false);
   */
     //- creates a sheet body with the given curve loop
     //- uses the new sheet body to cut the body list
@@ -557,8 +621,10 @@
                               double angle, 
                               Surface *stop_surf,
                               bool up_to_next, 
+                              DLIList<BodySM*>& neighbor_imprint_list,
                               DLIList<BodySM*> &results_list,
-                              CubitBoolean imprint = false );
+                              ImprintType imprint_type = NO_IMPRINT,
+                              CubitBoolean preview = false);
   */
   /*
   virtual CubitStatus webcut_with_sweep_curves_rotated(
@@ -568,8 +634,10 @@
                               const CubitVector& sweep_vector,
                               double angle, 
                               Surface *stop_surf,
+                              DLIList<BodySM*>& neighbor_imprint_list,
                               DLIList<BodySM*> &results_list,
-                              CubitBoolean imprint = false );
+                              ImprintType imprint_type = NO_IMPRINT,
+                              CubitBoolean preview = false);
   */
   //-these 2 functions sweep a surface or curve about an axis, creating a swept
   //volume or surface respectively, which is in turn used to webcut the blank_bodies.
@@ -587,8 +655,10 @@
                               bool up_to_next, 
                               Surface *stop_surf, 
                               Curve *curve_to_sweep_along, 
+                              DLIList<BodySM*>& neighbor_imprint_list,
                               DLIList<BodySM*> &results_list,
-                              CubitBoolean imprint = false );
+                              ImprintType imprint_type = NO_IMPRINT,
+                              CubitBoolean preview = false);
   */
   //-sweeps a surface(s) along a vector, curve or perpendicular to the surface 
   //(last case implied when sweep_vector's length is zero) producing a swept body.
@@ -608,8 +678,10 @@
                               bool through_all, 
                               Surface *stop_surf, 
                               Curve *curve_to_sweep_along, 
+                              DLIList<BodySM*>& neighbor_imprint_list,
                               DLIList<BodySM*> &results_list,
-                              CubitBoolean imprint = false );
+                              ImprintType imprint_type = NO_IMPRINT,
+                              CubitBoolean preview = false);
   */
   //-sweeps a curve(s) along a vector, curve. Swept surface(s)are stitched 
   //together and used as cutting tool to webcut blank_bodies. If surface(s) 
@@ -634,7 +706,7 @@
 
 //HEADER- Functions that create GeometryEntities
 
-  virtual BodySM* copy_body ( BodySM* bodyPtr) const ;
+  virtual BodySM* copy_body( BodySM* body_sm ) const ;
     //R Body*
     //R- A pointer to the newly created body
     //I bodyPtr
@@ -670,6 +742,9 @@
     //- The third point is optional so it can be NULL.  It is
     //- or can be used for periodic curves that result.
 
+  virtual Curve* make_Curve( DLIList<CubitVector*>& point_list,
+                             DLIList<CubitVector*>& point_tangents) const;
+
   virtual Curve* make_Curve( GeometryType curve_type,
                              Point const* point1_ptr,
                              Point const* point2_ptr,
@@ -738,6 +813,21 @@
     //- The new surface is attached to ACIS geometry.  The acis
     //- goemetry is attached to a full data structure, loop, lump, bodies..
 
+  virtual BodySM* make_extended_sheet( DLIList<Surface*> &surface_list,
+                                       CubitBox *clip_box = NULL,
+                                       bool preview = false) const;
+    //R BodySM*
+    //R- Pointer to a newly created BodySM object.
+    //I surface_list
+    //I- The surface_list from which we want to create an extended sheet.
+    //I clip_box
+    //I- An optional bounding box to clip the resultant sheet body by.
+    //I preview
+    //I- If true just draw the sheet instead of creating it
+    //- This function creates a sheet body by extending the input surfaces.
+    //- The result can be optionally clipped to fit inside of the given
+    //- bounding box.
+
   virtual Surface* make_Surface( GeometryType surface_type,
                                  DLIList<Curve*>& curve_list,
                                  Surface *old_surface_ptr = NULL,
@@ -810,8 +900,10 @@
 /*
   virtual CubitStatus webcut_with_sheet(DLIList<BodySM*>& webcut_body_list,
                                         BodySM *sheet_body,
+                                        DLIList<BodySM*>& neighbor_imprint_list,
                                         DLIList<BodySM*> &new_bodies,
-                                        bool imprint = false);
+                                        ImprintType imprint_type = NO_IMPRINT,
+                                        bool preview = false);
 */
     //- webcuts a body using a sheet body.
     //- It splits the sheet into two single sided bodies.
@@ -824,25 +916,38 @@
                                         BODY *sheet_body,
                                         BODY *&webcut_body_1,
                                         BODY *&webcut_body_2,
-                                        CubitBoolean imprint  = CUBIT_FALSE);
+                                        ImprintType imprint_type = NO_IMPRINT,
+                                        bool preview = false);
   */
     //- webcuts a body using a sheet body.
     //- It splits the sheet into two single sided bodies.
   /*
-  virtual CubitStatus webcut_with_extended_surf(DLIList<BodySM*> &webcut_body,
-                                                Surface *extend_from,
+  virtual CubitStatus webcut_with_extended_sheet(DLIList<BodySM*> &webcut_body,
+                                                DLIList<Surface*> &surface_list,
+                                                DLIList<BodySM*>& neighbor_imprint_list,
                                                 DLIList<BodySM*> &new_bodies,
                                                 int &num_cut,
-                                                bool imprint = false);
+                                                ImprintType imprint_type = NO_IMPRINT,
+                                                bool preview = false);
   */
-    //- creates a surface by extending one from the given surface then
-    //- webcuts using the this sheet.(see webcut_with_sheet.
+    //- creates a sheet by extending the given surfaces then webcuts using
+    //- this sheet.(see webcut_with_sheet)
 
+  virtual CubitStatus split_free_curve( Curve *curve,
+                                        CubitVector &split_location,
+                                        DLIList<Curve*> &new_curves );
+    //- split a free curve a given location
+
   virtual CubitStatus split_body( BodySM *body_ptr,
                                   DLIList<BodySM*> &new_bodies );
     //- splits a body into several bodies (multiple volumes in
     //- a single body go to multiple bodies.
 
+  virtual CubitStatus separate_surfaces( DLIList<Surface*> &surf_list,
+                                         DLIList<BodySM*> &new_bodies );
+      //- Separates surfaces from sheet bodies into separate bodies.  Connected
+      //- surfaces will remain connected but be placed in a new body.
+
   virtual CubitStatus split_periodic( BodySM *body_ptr,
                                       BodySM *&new_body);
     //- splits the periodic bodies
@@ -857,7 +962,8 @@
                                     DLIList<Surface*> &ref_face_list,
                                     DLIList<BodySM*> &new_bodies,
                                     bool keep_old = false,
-                                    bool heal = true) const;
+                                    bool heal = true,
+                                    bool sheet = false) const;
   //- This function assumes that the reffaces sent into
   //- this function are either sheet bodies, or free surfaces.  This
   //- Will have been taken care of in the calling function.  GT?
@@ -878,8 +984,10 @@
   virtual CubitStatus webcut_across_translate( DLIList<BodySM*>& body_list,
                                                Surface* plane_surf1,
                                                Surface* plane_surf2,
+                                               DLIList<BodySM*>& neighbor_imprint_list,
                                                DLIList<BodySM*>& results_list,
-                                               bool imprint = false) const;
+                                               ImprintType imprint_type = NO_IMPRINT,
+                                               bool preview = false) const;
   // In-process function to webcut a flat plate suitable for singe-single sweeping.
 
   CubitStatus offset_curves( DLIList<Curve*>& ref_edge_list, 
@@ -892,6 +1000,14 @@
   //- is calculated by ACIS (the cross product of the wires tangent and the
   //- planar normal).  The gap type is 0 - rounded, 1 - extended, 2 - natural.
 
+  CubitStatus
+  split_curve( Curve* curve_to_split,
+			   const CubitVector& split_location,
+			   DLIList<Curve*>& created_curves );
+  //- Splits a curve at the specified location.
+  //- the single passed in curve is split into two curves at the split location
+  //- the two resulting curves are added to the passed in list
+  
   Curve* trim_curve( Curve* trim_curve, 
                      const CubitVector& trim_vector,
                      const CubitVector& keep_vector,
@@ -993,16 +1109,32 @@
 				  BodySM *body_to_trim_to,
 				  BodySM *&midsurface_body ) const;
 
+  CubitStatus tweak_bend( DLIList<BodySM*> &bend_bodies,
+	                      DLIList<BodySM*> &new_bodysm_list,
+	                      CubitVector& neutral_root,
+	                      CubitVector& bend_axis,
+	                      CubitVector& bend_direction,
+                          double radius,
+                          double angle,
+                          DLIList<CubitVector*> bend_regions,
+                          double width = -1,
+                          CubitBoolean center_bend = CUBIT_FALSE,
+                          int num_points = 0,
+                          CubitBoolean keep_old_body = CUBIT_FALSE,
+                          CubitBoolean preview = CUBIT_FALSE ) const;
+  /**<  Bend solid bodies based on a bend radius and angle.
+    */
+
   virtual CubitStatus tweak_chamfer( DLIList<Curve*> &curve_list, 
                                      double left_offset,
                                      DLIList<BodySM*> &new_bodysm_list,
                                      double right_offset = -1.0,
                                      CubitBoolean keep_old_body = CUBIT_FALSE,
                                      CubitBoolean preview = CUBIT_FALSE ) ;
-  /**<  Chamfer curves on solid bodies.  The left and right offsets are with 
-    *   respect to the curve direction.  If the given right offset is negative,
-    *   the left offset is used.  Users can preview to clarify the meaning of
-    *   left and right.
+  /**<  Chamfer curves on solid or sheet bodies.  The left and right offsets
+    *   are with respect to the curve direction.  If the given right offset is
+    *   negative, the left offset is used.  Users can preview to clarify the
+    *   meaning of left and right.
     */
 
   virtual CubitStatus tweak_chamfer( DLIList<Point*> &point_list, 
@@ -1026,7 +1158,8 @@
                                     DLIList<BodySM*> &new_bodysm_list,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
                                     CubitBoolean preview = CUBIT_FALSE ) ;
-  /**<  Create a round fillet (or blend) at the given curves on solid bodies.
+  /**<  Create a round fillet (or blend) at the given curves on solid or sheet
+    *   bodies.
     */
 
   virtual CubitStatus tweak_fillet( Curve *curve_ptr, 
@@ -1035,8 +1168,9 @@
                                     BodySM *&new_body_ptr,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
                                     CubitBoolean preview = CUBIT_FALSE ) ;
-  /**<  Create a round fillet (or blend) at the given curve on a solid body.
-    *   The fillet has a variable radius from the start to the end of the curve.
+  /**<  Create a round fillet (or blend) at the given curve on a solid or sheet
+    *   body. The fillet has a variable radius from the start to the end of the
+    *   curve.
     */
 
   virtual CubitStatus tweak_fillet( DLIList<Point*> &point_list, 
@@ -1065,26 +1199,29 @@
 
   virtual CubitStatus tweak_offset( DLIList<Surface*> &surface_list,
                                     double offset_distance,
+                                    DLIList<Surface*> *add_surface_list_ptr, 
+                                    DLIList<double> *add_offset_list_ptr,
                                     DLIList<BodySM*> &new_bodysm_list,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
                                     CubitBoolean preview = CUBIT_FALSE ) const;
   /**<  Tweak specified faces of a volume or volumes by offsetting those faces
-    *   by the offset distance.
+    *   by the offset distance(s).
     */
 
   virtual CubitStatus tweak_offset( DLIList<Curve*> &curve_list,
                                     double offset_distance,
+                                    DLIList<Curve*> *add_curve_list_ptr, 
+                                    DLIList<double> *add_offset_list_ptr,
                                     DLIList<BodySM*> &new_bodysm_list,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
                                     CubitBoolean preview = CUBIT_FALSE ) const;
   /**<  Tweak specified curves of a sheet body or bodies by offsetting those
-    *   curves by the offset distance.
+    *   curves by the offset distance(s).
     */
 
   virtual CubitStatus tweak_remove( DLIList<Surface*> &surface_list,
                                     DLIList<BodySM*> &new_bodysm_list,
                                     CubitBoolean extend_adjoining = CUBIT_TRUE,
-                                    CubitBoolean keep_surface = CUBIT_FALSE,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
                                     CubitBoolean preview = CUBIT_FALSE ) const;
   /**<  Remove surfaces from a body or bodies and then extend the adjoining
@@ -1103,34 +1240,80 @@
   virtual CubitStatus tweak_target( DLIList<Surface*> &surface_list,
                                     DLIList<Surface*> &target_surf_list,
                                     DLIList<BodySM*> &new_bodysm_list,
+                                    CubitBoolean extend_flg = CUBIT_TRUE,
+                                    CubitPlane *limit_plane = NULL,
                                     CubitBoolean reverse_flg = CUBIT_FALSE,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
                                     CubitBoolean preview = CUBIT_FALSE ) const;
   /**<  Tweak specified faces of a volume or volumes up to target surfaces.
+    *   If extend flag is true, extend out the targets before tweaking to them 
+    *   (only used for multiple targets; single targets are always extended).  
+    *   The optional limit plane is only valid if extend_flg is TRUE; it will
+    *   limit the tweak to not go past this plane in the case where the tweaked
+    *   body would only partially intersect the extended targets.  The reverse
+    *   flag should never be needed - if it is, there may be a bug or a bad
+    *   normal on a body (i.e., negative volume body), and is only retained for
+    *   debugging.
     */
 
   virtual CubitStatus tweak_target( DLIList<Curve*> &curve_list,
                                     DLIList<Surface*> &target_surf_list, 
                                     DLIList<BodySM*> &new_bodysm_list,
+                                    CubitBoolean extend_flg = CUBIT_TRUE,
+                                    CubitPlane *limit_plane = NULL,
                                     CubitBoolean reverse_flg = CUBIT_FALSE,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE ) const;
+                                    CubitBoolean preview = CUBIT_FALSE ,
+                                    double max_area_increase = 0) const;
   /**<  Tweak specified edges of a surface or set of surfaces (in sheet
     *   bodies) up to a set of target surfaces.  This essentially extends or
-    *   trims the attached surfaces of the sheet body.
+    *   trims the attached surfaces of the sheet body.  If extend flag
+    *   is true, extend out the targets before tweaking to them (only used for
+    *   multiple targets; single targets are always extended).  The optional
+    *   limit plane is only valid if extend_flg is TRUE; it will limit the
+    *   tweak to not go past this plane in the case where the tweaked body
+    *   would only partially intersect the extended targets.  The reverse flag
+    *   should never be needed - if it is, there may be a bug or a bad normal
+    *   on a body (i.e., negative volume body), and is only retained for
+    *   debugging.
     */
 
   virtual CubitStatus tweak_target( DLIList<Curve*> &curve_list,
                                     DLIList<Curve*> &target_curve_list, 
                                     DLIList<BodySM*> &new_bodysm_list,
+                                    CubitBoolean extend_flg = CUBIT_TRUE,
+                                    CubitPlane *limit_plane = NULL,
                                     CubitBoolean reverse_flg = CUBIT_FALSE,
                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE ) const;
+                                    CubitBoolean preview = CUBIT_FALSE,
+                                    double max_area_increase = 0 ) const;
   /**<  Tweak specified edges of a sheet body or bodies up to a list of target
-    *   curves that are part of a sheet body.  The target is a surface created by
-    *   thickening the owning surfaces of the target curves.
+    *   curves that are part of a sheet body.  The target is a surface created 
+    *   by thickening the owning surfaces of the target curves. If extend flag
+    *   is true, extend out the targets before tweaking to them (only used for
+    *   multiple targets; single targets are always extended).  The optional
+    *   limit plane is only valid if extend_flg is TRUE; it will limit the
+    *   tweak to not go past this plane in the case where the tweaked body
+    *   would only partially intersect the extended targets.  The reverse flag
+    *   should never be needed - if it is, there may be a bug or a bad normal
+    *   on a body (i.e., negative volume body), and is only retained for
+    *   debugging.
     */
 
+  virtual CubitStatus tweak_target( Point *point_ptr,
+                                    DLIList<Surface*> &modify_surface_list,
+                                    CubitVector &target_loc,
+                                    BodySM *&new_bodysm_ptr,
+                                    CubitBoolean keep_old_body = CUBIT_FALSE,
+                                    CubitBoolean preview = CUBIT_FALSE ) const;
+  /**<  Tweak specified vertex of a sheet body to a given location.  The
+    *   given vertex must be part of a planar surface or surfaces attached to
+    *   linear curves only.  The user specified which of those surfaces to
+    *   actually modify.  The given location will be projected to be on the
+    *   given planar surface(s) before being used - this projected location
+    *   must be the same on all surfaces.
+    */
+
   virtual CubitStatus remove_curve_slivers( BodySM *body_sm, double lengthlimit ) const;
   
   virtual CubitStatus create_net_surface( DLIList<Surface*>& ref_face_list, BodySM *& new_body,
@@ -1146,9 +1329,24 @@
 
   virtual CubitStatus create_offset_surface( Surface* ref_face_ptr, BodySM*& new_body, double offset_distance ) const;
 
+  virtual CubitStatus create_offset_sheet( DLIList<Surface*> &surface_list,
+                                           double offset_distance,
+                                           DLIList<Surface*> *add_surface_list_ptr,
+                                           DLIList<double> *add_offset_list_ptr,
+                                           DLIList<BodySM*> &new_body_list,
+                                           CubitBoolean preview = CUBIT_FALSE ) const;
+  /**< Create a sheet body (or bodies) by offsetting the given faces. The
+    *  optional additional face list and double list (must be same length)
+    *  allow different offset distances for different faces. Adjoining faces
+    *  are extended or trimmed to remain joined in the new sheet body.  Radial
+    *  faces that cannot be so offset are removed and the resulting wound
+    *  healed by the surrounding faces.
+    */
+
   virtual CubitStatus create_offset_body( BodySM* body_ptr, BodySM*& new_body, double offset_distance ) const;
 
-  virtual CubitStatus create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body ) const;
+  virtual CubitStatus create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body,
+                                           DLIList<Curve*>& guides) const;
 
   virtual CubitStatus loft_surfaces( Surface *face1, const double &takeoff1,
                                      Surface *face2, const double &takeoff2,
@@ -1160,25 +1358,90 @@
                                      CubitBoolean simplify_option = CUBIT_FALSE) const;
 
   virtual CubitStatus loft_surfaces_to_body( Surface *face1, const double &takeoff1,
-         									         Surface *face2, const double &takeoff2,
-			                  						BodySM*& new_body,
-									                  CubitBoolean arc_length_option,
-									                  CubitBoolean twist_option,
-									                  CubitBoolean align_direction,
-									                  CubitBoolean perpendicular,
-									                  CubitBoolean simplify_option) const;
+         				     Surface *face2, const double &takeoff2,
+			                     BodySM*& new_body,
+                                             CubitBoolean arc_length_option,
+                                             CubitBoolean twist_option,
+					     CubitBoolean align_direction,
+					     CubitBoolean perpendicular,
+					     CubitBoolean simplify_option) const;
     
   virtual CubitStatus create_surface( DLIList<CubitVector*>& vec_list,
                                       BodySM *&new_body,
                                       Surface *ref_face_ptr, 
-			                             CubitBoolean project_points ) const;
+			              CubitBoolean project_points ) const;
 
+  virtual CubitStatus create_surface( DLIList<Point*>& vec_list,
+                                      BodySM *&new_body ) const;
+
   virtual CubitStatus create_weld_surface( CubitVector &root,
-                                           Surface *ref_face1, double leg1, Surface *ref_face2, double leg2,
+                                           Surface *ref_face1, double leg1, 
+                                           Surface *ref_face2, double leg2,
                                            BodySM *&new_body ) const;
 
   CubitStatus scale( BodySM *&body, const CubitVector& f );
 
+  virtual CubitStatus curve_surface_intersection( Surface *surface, 
+                                                  Curve* curve,
+                                                  DLIList<Curve*> &new_curves ) const;
+  //Intersects input surface with input curve to produce intersection curve(s).
+  //If intersection results is nothing or a point, CUBIT_FAILURE is returned.
+  EDGE* project_EDGE( EDGE* EDGE_in_ptr, FACE* FACE_ptr, bool print_error = true ) const;
+    //- Projects a EDGE to a FACE returning the newly created EDGE
+  EDGE* make_surface_EDGE( VERTEX* from,
+                           VERTEX* to,
+                           FACE *FACE_ptr,
+                           const CubitVector &plane_normal,
+                           const CubitVector *third_point = NULL) const;
+  FACE* make_FACE( GeometryType FACE_type,
+                   DLIList<EDGE*>& EDGE_list,
+                   Surface *old_surface_ptr = NULL) const;
+    //R FACE*
+    //R- Returned FACE pointer
+    //I FACE_type
+    //I- The type of geometry entity to be associated with the FACE
+    //I- that is created
+    //I EDGE_list
+    //I- Input list of EDGEs that bound the FACE to be made.
+    //- This function creates an ACIS FACE using the EDGEs in EDGE_list.
+    //- The type of the underlying geometry is determined by the
+    //- FACE_type argument.
+    //- All other associated ACIS entities are also created.
+  BODY* make_extended_sheet( DLIList<FACE*> &FACE_list,
+                             CubitBox *clip_box = NULL,
+                             bool suppress_errors = false) const;
+    //R BODY*
+    //R- Pointer to a newly created BODY object.
+    //I FACE_list
+    //I- The FACE_list from which we want to create an extended sheet.
+    //I clip_box
+    //I- An optional bounding box to clip the resultant sheet body by.
+    //- This function creates a sheet body by extending the input FACEs.
+    //- The result can be optionally clipped to fit inside of the given
+    //- bounding box.
+  CubitStatus imprint( BODY *BODY_ptr, 
+                       FACE *FACE_ptr, 
+                       EDGE *EDGE_ptr, 
+                       DLIList<TopologyBridge*> &temporary_bridges,
+                       bool expand = false) const;
+    //- Imprint given FACE with given EDGE.  BODY_ptr is BODY that FACE_ptr is on.
+  
+  BODY* copy_BODY (BODY* body_ptr,
+                   bool remove_attribs = true ) const;
+    //- Make a copy of the input BODY, body_ptr, and return a pointer
+    //- to the new BODY. If the operation fails, a NULL pointer is returned.
+    //- If remove_attribs is set to CUBIT_TRUE, then the attributes from the
+    //- original BODY will be stripped off the new BODY (these are automatically
+    //- copied to the new BODY, by ACIS.
+    
+  CubitBoolean bodies_interfering( BodySM *body1, BodySM *body2 ) const;
+
+  CubitStatus stitch( DLIList<BodySM*> &bodies_to_stitch,
+                      DLIList<BodySM*> &new_bodies,
+                      bool tighten_gaps,
+                      double tolerance )const;
+
+
 protected:
 
 private:
@@ -1381,12 +1644,6 @@
                           SPAposition* ctr_ptr,
                           bool sense) const;
 
-  EDGE* make_surface_EDGE( VERTEX* from,
-                           VERTEX* to,
-                           FACE *FACE_ptr,
-                           const CubitVector &plane_normal,
-                           const CubitVector *third_point = NULL) const;
-
   EDGE* make_spline_EDGE( VERTEX* from,
                           VERTEX* to,
                           SPAposition* pos_array,
@@ -1410,13 +1667,21 @@
     //- Create a spline curve from the input locations. Returns NULL if
     //- unable to create a spline.  Uses api_curve_spline
 
-  FACE* make_type_FACE( CONE *CONE_ptr ) const;
+  EDGE* make_spline_EDGE( DLIList<CubitVector*> &vec_list, 
+                          CubitVector* start_direction,
+                          CubitVector* end_direction );
+
+  FACE* make_type_FACE( CONE *CONE_ptr, FACE *FACE_ptr, 
+                        CubitBox *limit_box = 0 ) const;
     //R FACE*
     //R- face pointer connected to sheet body.
     //I- Cone geometry where info is to be gleaned.
+    //I- Optional bounding box for determing size of FACE.  If not supplied, 
+    //   uses the super bounding box of the model.
     //-  This function takes the input cone geometry and creates
     //-  another face using this to create a larger face that
-    //-  has a height fitting a factor larger than the model.
+    //-  has a height fitting a factor larger than the model, or the supplied
+    //-  limit_box.
 
   FACE* make_type_FACE( SPHERE *SPHERE_ptr ) const;
     //R FACE*
@@ -1434,46 +1699,42 @@
     //-  another face using this to create a full torus face.
     //-  it is just the shell of the torus.
 
-  FACE* make_type_FACE( SPLINE *SPLINE_ptr ) const;
+#if CUBIT_ACIS_VERSION < 1900
+  FACE* make_type_FACE( SPLINE *SPLINE_ptr, CubitBox *limit_box_ptr = NULL ) const;
+#endif
+
+  FACE* make_type_FACE( FACE *FACE_ptr, CubitBox *limit_box_ptr = NULL ) const;
     //R FACE*
     //R- face pointer connected to sheet body.
-    //I- Spline geometry where info is to be gleaned.
-    //-  This function takes the input spline geometry and creates
+    //WARNING: Input FACE's geometry must be of type spline!!!!!
+    //-  This function takes the FACE and creates
     //-  another face using this to create a full spline face.
-    //-  it is just the shell of the spline.
+    //-  It attempts to expand out 10% greater than the overall 
+    //-  cubit bounding box or to the given limit_box.
 
-  FACE* make_type_FACE( PLANE *PLANE_ptr ) const;
+
+
+  FACE* make_type_FACE( PLANE *PLANE_ptr, CubitBox *limit_box = 0 ) const;
     //R FACE*
     //R- face pointer connected to sheet body.
     //I- Plane geometry where info is to be gleaned.
-    //- The super bounding box of the model is used to creat the limits of the
-    //- new plane.
+    //I- Optional bounding box for determing size of FACE.  If not supplied, 
+    //   uses the super bounding box of the model.
 
   FACE* make_FACE( FACE* FACE_ptr, 
-                   CubitBoolean extended_from = CUBIT_FALSE
+                   CubitBoolean extended_from = CUBIT_FALSE,
+                   CubitBox *limit_box = 0
                  ) const;
     //R FACE*
-    //R- REturned FACE pointer
+    //R- Returned FACE pointer
     //I- Existing FACE to make a copy from.
-    //I- flag to tell whether to extend the face to its full geometric form or not.
+    //I- Flag to tell whether to extend the face to its full geometric form or not.
+    //I- Optional bounding box for determing size of FACE if extended_from is TRUE
+    //   (used for planes, cones and cylinders).  If not supplied, uses the overall
+    //   Cubit model bounding box.
     //- This function accepts apointer to a face and makes an api
     //- call to copy this face and construct a sheet body from it.
 
-  FACE* make_FACE( GeometryType FACE_type,
-                   DLIList<EDGE*>& EDGE_list,
-                   Surface *old_surface_ptr = NULL) const;
-    //R FACE*
-    //R- Returned FACE pointer
-    //I FACE_type
-    //I- The type of geometry entity to be associated with the FACE
-    //I- that is created
-    //I EDGE_list
-    //I- Input list of EDGEs that bound the FACE to be made.
-    //- This function creates an ACIS FACE using the EDGEs in EDGE_list.
-    //- The type of the underlying geometry is determined by the
-    //- FACE_type argument.
-    //- All other associated ACIS entities are also created.
-
   BODY* make_planar_quad_BODY ( const CubitVector& Point1,
                                 const CubitVector& Point2,
                                 const CubitVector& Point3,
@@ -1512,9 +1773,10 @@
 
   CubitStatus webcut( DLIList<BodySM*>& webcut_body_list,
                       BODY* tool_BODY,
+                      DLIList<BodySM*>& neighbor_imprint_list,
                       DLIList<BodySM*>& results_list,
-                      bool imprint = false
-                      ) const ;
+                      ImprintType imprint_type = NO_IMPRINT,
+                      bool preview = false) const ;
     //R int
     //R- Number of bodies that were webcut ( >= 0 )
     //I webcut_body_list
@@ -1568,41 +1830,50 @@
     //- Deletes the Bodies in body_list and the Acis BODYs in BODY_list
 
 
-  
+  CubitStatus stitch_FACEs( DLIList<FACE*> &faces,
+                            FACE *&result_FACE,
+                            BODY *&stitched_BODY );
+  //I List of FACEs you want stitched together
+  //IO Pointer to FACE...gets set if all FACEs can be stitched into single FACE 
+  //IO If stitching of FACEs is successful, stitched_BODY is resultant BODY.  
+  //   Means that all faces could be stitched together, forming a single BODY,
+  //   but not a single FACE.
+  //returns CUBIT_SUCCESS if stitching was successful, other return FAILURE
 
-  void webcut_imprint(BODY* cutting_tool_BODY_ptr,
-                      DLIList<BodySM*> &old_body_list,
-                      DLIList<BODY*>& new_webcut_BODY_list,
-                      DLIList<BODY*>& just_webcut_BODY_list,
-                      DLIList<BodySM*>& results_list,
-                      DLIList<BodySM*> &imprinted_model_Body_list,
-                      DLIList<BODY*> &imprinted_model_BODY_list) const ;
-    //I cutting_tool_BODY_ptr
-    //I- Pointer to the Cutting Tool BODY. This is required in the case
-    //I- where an existing Body - is used as the CT. In that case, its BODY
-    //I- is kept out of the imprint operations.
-    //IO new_webcut_BODY_list
-    //IO- List of BODYs created by webcutting the list of RefBodies
-    //IO- specified in the webcut command. New BODYs created as a product
-    //IO- of performing imprints on the existing BODYs in the Model are
-    //IO- appended to this list.
-    //- Performs the required imprint operations to ensure that the topologies
-    //- of the boundaries of the new webcut BODYs "match" those of their
-    //- neighbouring BODYs (for mesh compatibility reasons).
 
+  CubitStatus finish_webcut( BODY *tool_BODY,
+                           DLIList<BodySM*> &original_bodysm_list, //original BodySMs of successfully webcut bodies
+                           DLIList<BODY*> &original_BODY_list, //original ACIS BODYs
+                           DLIList<BODY*> &new_webcut_BODY_list, //BODYs resulting from successful webcuts
+                           DLIList<BodySM*> &neighbor_imprint_list, //
+                                                                    //with bodies that were webcut
+                           ImprintType imprint_type,
+                           DLIList<BodySM*> &results_list ) const;
+    //tool_BODY -- tool body...just to make sure a neighbor isn't the tool body
+    //             so the tool doesn't get imprinted
+    //original_bodysm_list -- original BodySMs that were successfully webcut
+    //original_BODY_list -- original ACIS BODYs that whose copy was successfully webcut
+    //new_webcut_BODY_list -- copied ACIS BODYs that were successfully
+    //neighbor_imprint_list -- neighbor BodySMs that need to be imprinted with bodies
+    //                         that were webcut
+    //imprint_type -- type of imprint
+    //results_list -- BodySMs resulting from the webcut and all neighbors
+
+  CubitStatus webcut_bodies_with_sheet_body( BODY *sheet_BODY,
+                                             DLIList<BodySM*> &blank_bodysms,
+                                             DLIList<BodySM*> &neighbor_imprint_list,
+                                             DLIList<BodySM*> &result_bodysms,
+                                             ImprintType imprint_type,
+                                             int &num_cut,
+                                             CubitBoolean preview );
+
+
   BODY* create_infinite_plane_cutting_tool( const CubitVector &vecVertex1,
                                             const CubitVector &vecVertex2,
                                             const CubitVector &vecVertex3,
                                             const SPAbox& super_box,
                                             bool just_face = false ) const;
 
-  BODY* copy_BODY (BODY* body_ptr,
-                   bool remove_attribs = true ) const;
-    //- Make a copy of the input BODY, body_ptr, and return a pointer
-    //- to the new BODY. If the operation fails, a NULL pointer is returned.
-    //- If remove_attribs is set to CUBIT_TRUE, then the attributes from the
-    //- original BODY will be stripped off the new BODY (these are automatically
-    //- copied to the new BODY, by ACIS.
 
 //HEADER- Functions related to geometric sweep operations
 
@@ -1756,13 +2027,13 @@
     //- to be done first using the GeometryTool::is_interfering procedure.
 
   CubitStatus imprint( BODY *BODY_ptr, DLIList<FACE*> &FACE_list,
-                       DLIList<EDGE*> &EDGE_list ) const;
+                       DLIList<EDGE*> &EDGE_list, DLIList<TopologyBridge*> &temporary_bridges ) const;
     //- Imprints a list of FACEs with a list of EDGEs.  The FACEs must
     //- be from the same BODY that is passed in.  FACEs are modified but
     //- EDGEs are not.
 
   CubitStatus imprint( BODY *BODY_ptr, DLIList<FACE*> &FACE_list,
-                       DLIList<DLIList<EDGE*>*> &EDGE_lists_list ) const;
+                       DLIList<DLIList<EDGE*>*> &EDGE_lists_list, bool expand = false ) const;
     //- Same as above function, except more efficient if it is known exactly 
     //- which EDGEs need to be imprinted with which FACEs.  Note as input 
     //- there is a corresponding EDGE_list for each input FACE.  The function
@@ -1793,13 +2064,21 @@
     //- This function removes topology that is not essential
     //- to the existance of the body.
   CubitStatus regularize_entity( GeometryEntity *old_refentity_ptr,
-                                 BodySM *&new_body_ptr );
+                                 BodySM *&new_body_ptr);
    //- clean RefEntity
+  CubitStatus test_regularize_entity( GeometryEntity *old_refentity_ptr);
+  CubitStatus get_copied_FACES_and_EDGES_of_body( DLIList<SurfaceACIS*>& ref_face_list,
+                                                      DLIList<CurveACIS*>& ref_edge_list,
+                                                      DLIList<FACE*>& FACE_list,
+                                                      DLIList<EDGE*>& EDGE_list,
+                                                      DLIList<SurfaceACIS*>& removed_ref_faces,
+                                                      DLIList<CurveACIS*>& removed_ref_edges,
+                                                      BODY*& copied_BODY_ptr ) const;
 
   CubitStatus get_copied_FACES_of_body( DLIList<SurfaceACIS*>& ref_face_list,
                                         DLIList<FACE*>& FACE_list,
                                         BODY*& copied_BODY_ptr ) const;
-  //- Given a list of RefFaces, this function returns a list of Acis FACE's
+  //- Given a list of Surfaces, this function returns a list of Acis FACE's
   //- from a BODY that it copies from the parent BODY of the first RefFace in
   //- the incoming list.  This body is also returned, and still contains
   //- all the CUBIT attributes that the original BODIES had. The referenced
@@ -1862,7 +2141,10 @@
 
   CubitStatus embed_curves_into_surface( Surface *surface, 
                                          DLIList<Curve*> &curves_to_imprint,
-                                         BodySM *&new_body ) const;
+                                         DLIList<TopologyBridge*> &temporary_bridges,
+                                         BodySM *&new_body,
+                                         DLIList<TopologyBridge*> *new_tbs = NULL,
+                                         DLIList<TopologyBridge*> *att_tbs = NULL ) const;
   //Embeds the given curves into the surface.  Equaivalent to imprinting, but 
   //works well for curves that have tolerance problems, (i.e. might not reach
   //the bounding curves of the surface, or might be almost coincident with a
@@ -1872,7 +2154,16 @@
   //api_embed_wire_in_faces returns unexpected results if the curve
   //does not lie on the surface.
 
-
+  CubitStatus imprint_overlapping_curves( DLIList<Surface*> &surfs,
+                                          DLIList<BodySM*> &new_body_sms) const;
+  CubitStatus imprint_overlapping_curves( DLIList< DLIList<Curve*>* > &lists_of_mergeable_curves,
+                                            DLIList< DLIList<Curve*>* > &lists_of_overlapping_curves,
+                                            std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                            std::multimap<BodySM*, CubitVector> &body_vertex_imprint_map,
+                                            DLIList<BodySM*> &new_body_sms,
+                                            ProgressTool *progress_tool,
+                                            DLIList<TopologyBridge*> *new_tbs,
+                                            DLIList<TopologyBridge*> *att_tbs ) const;
   CubitStatus imprint_overlapping_curves( DLIList<BodySM*> &body_sms,
                                           DLIList<BodySM*> &new_body_sms,
                                           ProgressTool *progress_tool = NULL,
@@ -1882,17 +2173,87 @@
   //After a call to this function, all overlapping curves between the 
   //bodies are also mergeable.
 
+  CubitStatus imprint_overlapping_surfaces( DLIList<Surface*> &surfs,
+                                          DLIList<BodySM*> &new_body_sms,
+                                          DLIList<Surface*> *new_surface_list = NULL) const;
+  CubitStatus imprint_overlapping_surfaces(DLIList<Surface*> &overlapping_surfaces1,
+                                            DLIList<Surface*> &overlapping_surfaces2,
+                                            DLIList<BodySM*> &new_body_sms,
+                                            ProgressTool *progress_tool = NULL,
+                                            DLIList<Surface*> *new_surface_list = NULL) const;
   CubitStatus imprint_overlapping_surfaces( DLIList<BodySM*> &body_sms,
                                             DLIList<BodySM*> &new_body_sms,
                                             ProgressTool *progress_tool = NULL) const;
   //Given a list of bodies, if Surface A overlaps with surface B, imprints 
   //appropriate curves of surface A onto surface B then curves of B onto A.
-void get_new_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &new_ENTITIES) const;
-void get_att_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &att_ENTITIES, char *att_name) const;
+  void get_new_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &new_ENTITIES,
+                                        DLIList<DLIList<EDGE*>*> *list_of_EDGES_on_original_FACES = NULL,
+                                        DLIList<DLIList<EDGE*>*> *imprint_EDGE_lists = NULL) const;
+  void get_att_ENTITIES(ENTITY *top_ENTITY, DLIList<ENTITY*> &att_ENTITIES, const char *att_name) const;
 
   DLIList<EDGE*> find_new_EDGES(BODY *copied_BODY_ptr);
   // Marks all of the edges without Cubit owners as imprint features
 
+  CubitStatus remove_FACEs_from_BODY( BODY *BODY_ptr, 
+                                      DLIList<FACE*> &remove_FACE_list,
+                                      CubitBoolean silent = CUBIT_FALSE );
+  //- Remove the given FACEs from the BODY (modifying the input BODY).  The
+  //- input BODY is assumed to be a sheet body.  All input FACEs must be from
+  //- a single BODY.  Includes option to suppress any error messages.
+
+   CubitStatus remove_FACEs_from_BODY_except( BODY *BODY_ptr, 
+                                              DLIList<FACE*> &keep_FACE_list,
+                                              CubitBoolean silent = CUBIT_FALSE );
+   //- Remove all FACEs from the BODY except those in the keep_FACE_list
+   //- (modifying the input BODY).  The input BODY is assumed to be a sheet
+   //- BODY.  All input FACEs must be from a single BODY.  Includes option
+   //- to suppress any error messages.
+
+   CubitStatus remove_dup_owners( BODY *ref_BODY_ptr, BODY *BODY_ptr );
+   //- Remove duplicate Cubit owners from the BODY_ptr.  The ref_BODY_ptr is
+   //- unchanged - Cubit owner attributes that exist in both BODY_ptr and
+   //- ref_BODY_ptr are removed from BODY_ptr.
+
+   CubitStatus remove_dup_owners( BODY *ref_BODY_ptr, BODY *BODY_ptr, const int type );
+   //- Remove duplicate Cubit owners from the BODY_ptr.  The ref_BODY_ptr is
+   //- unchanged - Cubit owner attributes that exist in both BODY_ptr and
+   //- ref_BODY_ptr are removed from BODY_ptr.  The type of ENTITY to operate
+   //- on is specified by the type: BODY_TYPE, LUMP_TYPE, SHELL_TYPE,
+   //- FACE_TYPE, LOOP_TYPE, COEDGE_TYPE, EDGE_TYPE or VERTEX_TYPE.
+
+   CubitStatus trim_BODY_to_box( BODY *&BODY_ptr, CubitBox &box ) const;
+   //- Trim the given BODY to fit within the given CubitBox.
+   
+   CubitStatus stitch_simplify_and_tighten_gaps(ENTITY_LIST& bodies_imported_into_ACIS,
+                                        ENTITY_LIST& output_bodies,
+                                        bool tighten_gaps,
+                                        double tolerance )const;
+
+   CubitStatus stitch_entities( ENTITY_LIST& to_be_stitched,
+                                ENTITY_LIST& output_bodies,
+                                tolerant_stitch_options& sopts)const;
+
+   CubitStatus tighten_gaps_in_body(BODY*& body,
+                                   const double& desired_gap_tightness)const;
+
+   CubitStatus simplify_entity(ENTITY*& entity_to_simplify,
+                                       simplify_options& simp_opts)const;
+
+   bool handle_fatal_problem_reported_by_outcome(const outcome& api_outcome)const;
+
+   void handle_problems_reported_by_outcome(const outcome& api_outcome)const;
+ 
+   void display_problems_encountered(const error_info *einf)const;
+
+   void start_tracking_history( DLIList<TopologyBridge*> &bridges, 
+                                AcisHistory &history_object,
+                                bool ignore_parents = false );
+
+   void stop_tracking_history( DLIList<BodySM*> &new_bodies,
+                               AcisHistory &history_object );
+
+   void stop_tracking_history( DLIList<TopologyBridge*> &new_tbs,
+                               AcisHistory &history_object );
 };
 
 #endif

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -36,6 +36,7 @@
 #include <ctype.h>
 #include <assert.h>
 #include <errno.h>
+#include <map>
 // ********** END STANDARD INCLUDES           **********
 
 // ********** BEGIN ACIS INCLUDES             **********
@@ -44,8 +45,10 @@
 #include "cstrapi.hxx"
 #include "eulerapi.hxx"
 #include "intrapi.hxx"
+#include "raytest.hxx"
 #include "api.hxx"
 #include "kernapi.hxx"
+#include "kernopts.hxx"
 #include "ptentrel.hxx"
 #include "getbox.hxx"
 #include "debug.hxx"
@@ -120,16 +123,28 @@
 #include "module.hxx"
 #include "option.hxx"
 #include "getowner.hxx"
+#include "insanity_list.hxx"
 
-#if CUBIT_ACIS_VERSION >= 1600
-#include "clash_bodies.hxx"
+#if defined(WIN32)
+#if CUBIT_ACIS_VERSION >= 1700
+
+#ifdef CAT
+#include "spa_unlock_2380.cpp"
+#else
+#include "spa_unlock_2312.cpp"
 #endif
 
+#endif
+#endif
+ 
 #ifdef ACIS_IGES_TRANSLATOR
 #include "errorcode.err"
-#include "acisiges_api.hxx"
-#include "SPAXUnit.h"
-#include "acis_unit_api.h"
+//#include "acisiges_api.hxx"
+//#include "SPAXUnit.h"
+//#include "acis_unit_api.h"
+#include "heal_api.hxx"
+
+#include "SPAIUnit.h"
 #endif
 
 #ifdef ACIS_PROE_TRANSLATOR
@@ -141,16 +156,30 @@
    #include "cathusk/chl_api/apiwrite.hxx" 
 #endif
 #ifdef ACIS_STEP_TRANSLATOR
-#include "acisstep_api.hxx"
+//#include "acisstep_api.hxx"
 #endif
 
 #if defined( ACIS_IGES_TRANSLATOR) || defined( ACIS_STEP_TRANSLATOR )
-  #include "SPAXBase.h"
-  #include "SPAXBoolean.h"
-  #include "SPAXProgressReportCB.h"
+  #include "SPAIConverter.h"
+  #include "SPAIDocument.h"
+  #include "SPAIAcisDocument.h"
+  #include "SPAIProgressCallback.h"
+  #include "SPAIOptions.h"
+  #include "SPAIOptionName.h"
+  #include "SPAIValue.h"
 #endif
 
+#ifdef IGTO
+// For iGTO, these includes need to happen
+#include "lop_api.hxx"
+#include "warp_api.hxx"
+#include "part_api.hxx"
+#include "skinapi.hxx"
 
+#endif
+#include "blendapi.hxx"
+
+
 // ********** END ACIS INCLUDES               **********
 
 // ********** BEGIN CUBIT INCLUDES            **********
@@ -200,6 +229,11 @@
 #include "GfxDebug.hpp"
 #include "AcisFeatureEngine.hpp"
 
+#ifdef CUBIT_GUI
+#ifndef NO_USAGE_TRACKING
+#include "GUIInterface.h"
+#endif
+#endif // CUBIT_GUI
 
 const int AcisQueryEngine::MAX_NUM_CURVE_POINTS  = 750;
 const int AcisQueryEngine::AQE_SUBMINOR_VERSION = 0;
@@ -211,15 +245,19 @@
    api_terminate_generic_attributes();
    api_terminate_spline();
    api_terminate_kernel();
+   api_terminate_blending();
    api_terminate_intersectors();
    api_terminate_constructors();
    api_terminate_euler_ops();
+
+/*
 #ifdef ACIS_IGES_TRANSLATOR
    api_terminate_xiges();
 #endif
 #ifdef ACIS_STEP_TRANSLATOR
    api_terminate_xstep();
 #endif
+    */
 #ifdef ACIS_PROE_TRANSLATOR
    api_terminate_proe();
 #endif
@@ -397,11 +435,19 @@
            handled = CUBIT_FALSE;
          else
          {
-            // Since the user is requesting this EDGE be exported freely,
-            // copy it to a new entity (in case it's not really a free edge)
-            copy_single_entity((ENTITY*)EDGE_ptr, copied_entity_ptr);
-            entity_list.add(copied_entity_ptr);
-            copied_entity_list.add(copied_entity_ptr);
+            ENTITY_LIST ent_list;
+            api_get_faces( (ENTITY*)EDGE_ptr, ent_list );
+            
+            if( ent_list.count() )
+            {
+              // Since the user is requesting this EDGE be exported freely,
+              // copy it to a new entity (since it is not a free edge)
+              copy_single_entity((ENTITY*)EDGE_ptr, copied_entity_ptr);
+              entity_list.add(copied_entity_ptr);
+              copied_entity_list.add(copied_entity_ptr);
+            }
+            else
+              entity_list.add( EDGE_ptr );
             edge_count++;
          }
       }
@@ -415,11 +461,18 @@
            handled = CUBIT_FALSE;
          else
          {
-            // Since the user is requesting this VERTEX be exported freely,
-            // copy it to a new entity (in case it's not really a free vertex)
-            copy_single_entity((ENTITY*)VERTEX_ptr, copied_entity_ptr);
-            entity_list.add(copied_entity_ptr);
-            copied_entity_list.add(copied_entity_ptr);
+            ENTITY_LIST ent_list;
+            api_get_edges( (ENTITY*)VERTEX_ptr, ent_list );
+            if( ent_list.count() )
+            {
+              // Since the user is requesting this VERTEX be exported freely,
+              // copy it to a new entity (since it is not a free vertex)
+              copy_single_entity((ENTITY*)VERTEX_ptr, copied_entity_ptr);
+              entity_list.add(copied_entity_ptr);
+              copied_entity_list.add(copied_entity_ptr);
+            }
+            else
+              entity_list.add( VERTEX_ptr );
             vertex_count++;
          }
       }
@@ -539,36 +592,55 @@
       PRINT_ERROR( "The IGES translator is not licensed for this installation\n" );
       return CUBIT_FAILURE;
 #else
-      CubitString version = "Cubit ";
-      version += cubit_version;
 
-      // Author, organization, sending system, receiving system
-      result = api_xiges_set_header( getenv("USERNAME"), getenv("USERDOMAIN"),
-                                       version.c_str(), NULL, 1, 1.0 );
-      if( !result.ok() )
-      {
-         ACIS_API_error(result);
-         PRINT_WARNING("unable to define IGES header information for '%s'\n", filename);
-      }
+     CubitString version = "Cubit ";
+     version += cubit_version;
 
-      char* logfilename = NULL;
-      if( !logfile_name || !strcmp( logfile_name, "" ) )
-         strcpy(logfilename, "iges_export.log");
-      else
-         logfilename = (char *)logfile_name;
-   
-      result = api_xiges_write( entity_list, (char *)filename, logfilename );
+     char *username; 
+   #if defined(WIN32) 
+     username = getenv("USERNAME");
+   #else
+     username = getenv("USER");
+   #endif
 
-      if( !result.ok() )
-      {
-         PRINT_ERROR("Acis could not export to the IGES file: '%s'\n", filename);
-         ACIS_API_error(result);
-         entity_list.clear();
-         copied_entity_list.init();
-         while ( (entity_ptr=copied_entity_list.next()) )
-            api_delent( entity_ptr );
-         return CUBIT_FAILURE;
-      }
+     char *system_name;
+   #if defined(WIN32) 
+     system_name = "Windows"; 
+   #endif 
+
+   #if defined(CUBIT_LINUX) 
+     system_name = "Linux";
+   #endif
+
+   #if defined(MACOSX) 
+     system_name = "Apple"; 
+   #endif
+
+     SPAIOptions options;
+     options.Add( SPAIOptionName::AuthorName, username );
+     options.Add( SPAIOptionName::OrganizationName, version.c_str() ); 
+//     options.Add( SPAIOptionName::SendingSystemName, system_name );
+     options.Add( SPAIOptionName::TranslateFreeCurves, true );
+
+     //create the destination document
+     SPAIAcisDocument src(&entity_list);
+     SPAIDocument dst( filename );
+     SPAIUnit spai_unit(SPAIUnitUnknown);
+     dst.SetUnit( spai_unit );
+
+     SPAIConverter converter;
+     converter.SetOptions( options );
+     SPAIFile log_file(logfile_name);
+     converter.StartLog(log_file);
+     SPAIResult tmp_result = converter.Convert(src, dst);
+     converter.StopLog(log_file);
+
+     if( tmp_result.IsFailure() )
+     {
+       PRINT_ERROR("%s\n", tmp_result.GetMessage() );
+       return CUBIT_FAILURE;
+     }
+
 #endif //ACIS_IGES_TRANSLATOR
    }
 #ifdef ACIS_CATIA_TRANSLATOR
@@ -612,49 +684,29 @@
       copied_entity_list.init();
       while ( (entity_ptr=copied_entity_list.next()) )
          api_delent( entity_ptr );
-#if defined(SGI)
-      PRINT_ERROR("The STEP translator is not available for the 64-bit SGI platform\n");
-#else 
       PRINT_ERROR( "The STEP translator is not licensed for this installation\n" );
-#endif
       return CUBIT_FAILURE;
-#else     
-      if ( !stepInitialized ) {
-        PRINT_ERROR("The STEP translater has not been properly initialized.\n");
-        entity_list.clear();
-        copied_entity_list.init();
-        while ( (entity_ptr = copied_entity_list.next()) )
-          api_delent( entity_ptr );
-      
-        return CUBIT_FAILURE;
-      }
-      
-      char* logfilename = NULL;
-      if( !logfile_name || !strcmp( logfile_name, "" ) )
-         strcpy(logfilename, "step_export.log");
-      else
-         logfilename = (char *)logfile_name;
+#else
+     char* logfilename = NULL;
+     if( !logfile_name || !strcmp( logfile_name, "" ) )
+        strcpy(logfilename, "step_export.log");
+     else
+        logfilename = (char *)logfile_name;
 
-      result = api_xstep_write( entity_list, (char *)filename, logfilename ); 
+     SPAIAcisDocument src(&entity_list);
+     SPAIDocument dst( filename );
+     SPAIConverter converter;
+     SPAIFile log_file(logfile_name);
+     converter.StartLog(log_file);
+     SPAIResult tmp_result = converter.Convert(src, dst);
+     converter.StopLog(log_file);
 
-//    BODY* block;
-//    result = api_make_cuboid(10.0, 10.0, 10.0, block);
-//    ENTITY_LIST elist;
-//    elist.init();
-//    elist.add(block);
-//    result = api_step_convert_acisentlist_to_step(elist, "block.step", "block_step_write.log", NULL);
-//    api_delent(block);
-	
-      if( !result.ok() )
-      {
-         PRINT_ERROR("ACIS could not export to the STEP file: '%s'\n", filename);
-         ACIS_API_error(result);
-         entity_list.clear();
-         copied_entity_list.init();
-         while ( (entity_ptr=copied_entity_list.next()) )
-            api_delent( entity_ptr );
-         return CUBIT_FAILURE;
-      }
+     if( tmp_result.IsFailure() )
+     {
+       PRINT_ERROR("%s\n", tmp_result.GetMessage() );
+       return CUBIT_FAILURE;
+     }
+     
 #endif
    }
    
@@ -832,12 +884,10 @@
   CubitBoolean import_vertices,
   CubitBoolean free_surfaces) 
 {
-  int i;
   CpuTimer import_solid_model_timer;
   CubitBoolean step_import = CUBIT_FALSE;
   CubitBoolean iges_import = CUBIT_FALSE;
 
-
     // Check to make sure the requested type is supported
   if (strcmp(file_type, "ACIS_SAT") != 0 &&
       strcmp(file_type, "ACIS_SAB") != 0 &&
@@ -998,8 +1048,6 @@
   Surface* surface_ptr;
   Curve*   curve_ptr;
   Point*   point_ptr;
-  int percent_after = 0,
-     number_splines_simplified = 0;
   CubitStatus status = CUBIT_SUCCESS;
   outcome result;
 
@@ -1552,6 +1600,79 @@
   return about_spatially_equal(pos1, pos2, tolerance_factor);
 }
 
+CubitBoolean AcisQueryEngine::about_spatially_equal (EDGE* E1, EDGE* E2) const
+{
+  CubitBoolean ret = CUBIT_TRUE;
+
+  if( E1 == E2 )
+    return CUBIT_TRUE;
+
+  SPAinterval e1_range = E1->param_range();
+  SPAinterval c1_range = e1_range;
+  if(E1->sense() == REVERSED)
+    c1_range.negate();
+  double c1_param = c1_range.start_pt() + (c1_range.end_pt() - c1_range.start_pt())/3.0;
+  const curve &c1 = E1->geometry()->equation();
+  SPAposition test_point_1, test_point_2;
+  // Find the point 1/3 along curve_1 
+  c1.eval(c1_param, test_point_1);
+
+  // See if the 1/3 point on curve_1 lies on curve_2
+  const curve &c2 = E2->geometry()->equation();
+  c2.point_perp(test_point_1, test_point_2);
+
+  if (!about_spatially_equal(test_point_1, test_point_2 ))
+    ret = CUBIT_FALSE;
+
+  if(ret == CUBIT_TRUE)
+  {
+    /*
+    c2.eval(c2_param, test_point_2, c2_deriv);
+
+    //If one of the curves is zero-length, it will have a zero
+    //tangent vector.
+    double len_product = c1_deriv.len() * c2_deriv.len();
+    if( len_product > CUBIT_DBL_MIN )
+    {
+      double dot_product = c1_deriv % c2_deriv;
+      if (dot_product < 0)
+        relative_sense = CUBIT_REVERSED;
+    }
+    else
+    {
+      //If one of the tangents is zero-length, one of the curves had
+      //better be as well.
+      assert( (c1.length() * c2.length()) < CUBIT_RESABS );
+    }
+    */
+
+    VERTEX *E1V1 = E1->start();
+    VERTEX *E1V2 = E1->end();
+    VERTEX *E2V1 = E2->start();
+    VERTEX *E2V2 = E2->end();
+    if(about_spatially_equal(E1V1, E2V1))
+    {
+      if(!about_spatially_equal(E1V2, E2V2))
+        ret = CUBIT_FALSE;
+    }
+    else if(about_spatially_equal(E1V1, E2V2))
+    {
+      if(!about_spatially_equal(E1V2, E2V1))
+        ret = CUBIT_FALSE;
+    }
+    else
+      ret = CUBIT_FALSE;
+  }
+
+  if(ret == CUBIT_TRUE)
+  {
+    if(fabs(E1->length() - E2->length()) > GEOMETRY_RESABS)
+      ret = CUBIT_FALSE;
+  }
+
+  return ret;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Unhook the ENTITY's references in VGI. Call the next 
 //                 level of the series of functions to allow other 
@@ -1921,7 +2042,49 @@
       return CUBIT_TRUE;
    }
 }
+//-------------------------------------------------------------------------
+// Purpose       : Save the input ENTITYs to a SAT file
+//
+// Special Notes :
+//
+// Creator       : Corey Ernst  
+//
+// Creation Date : 2/13/2008 
+//-------------------------------------------------------------------------
+int AcisQueryEngine::save_ENTITYs_as_sat_file ( ENTITY_LIST *entity_list, 
+                                               const char* filename,
+                                               const char* update_mode ) const
+{
+   FILE* ENTITY_file_ptr = fopen(filename, update_mode);
+   if (ENTITY_file_ptr == NULL)
+   {
+      PRINT_ERROR ("Cannot open file. ENTITY not saved.\n");
+      return CUBIT_FALSE;
+   }
+   else
+   {
+      CubitString version = "Cubit ";
+      CubitString cubit_version("12.0b");
+      version += cubit_version;
+      FileInfo info;
+      info.set_product_id(version.c_str());
 
+      info.set_units(1.0);
+      api_set_file_info((FileId | FileUnits), info);
+     
+      outcome result = api_save_entity_list(ENTITY_file_ptr,
+                                    CUBIT_TRUE, *entity_list);
+      fclose(ENTITY_file_ptr);
+      if (!result.ok())
+      {
+         ACIS_API_error(result);
+         PRINT_ERROR ("Problem saving ENTITY to sat file.\n");
+         return CUBIT_FALSE;
+      }
+      return CUBIT_TRUE;
+   }
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Return a bounding box that encompasses all the
 //                 ENTITYs in the input ENTITY_LIST.
@@ -2210,14 +2373,10 @@
                                                          SPAposition &box_min,
                                                          SPAposition &box_max ) const
 {
-   int number_triangles, number_points, number_facets;
    GMem gMem;
 
-   CubitStatus status = 
-      get_graphics(face_ptr, number_triangles, number_points,
-                          number_facets, &gMem, 
-                          15, 0);
-   if (status != CUBIT_SUCCESS || number_facets == 0) {
+   CubitStatus status = get_graphics(face_ptr, &gMem, 15, 0);
+   if (status != CUBIT_SUCCESS || gMem.fListCount == 0) {
       status = CUBIT_FAILURE;
       return status;
    }
@@ -2226,7 +2385,7 @@
    xmin = ymin = zmin = DBL_MAX;
    xmax = ymax = zmax = -DBL_MAX;
    GPoint* plist = gMem.point_list();
-   for (int i = 0; i<number_points; i++) {
+   for (int i = 0; i<gMem.pointListCount; i++) {
       if (plist[i].x > xmax) xmax = plist[i].x; 
       if (plist[i].y > ymax) ymax = plist[i].y; 
       if (plist[i].z > zmax) zmax = plist[i].z; 
@@ -3432,7 +3591,6 @@
 //-------------------------------------------------------------------------
 CubitStatus AcisQueryEngine::get_graphics(
   Surface* surface_ptr,
-  int& number_triangles, int& number_points, int& facet_list_size,
   GMem* g_mem, unsigned short normal_tolerance, double distance_tolerance,
   double max_edge_length ) const
 {
@@ -3440,27 +3598,15 @@
   FACE* face_ptr = get_FACE(surface_ptr);
   if (face_ptr == NULL)
     return CUBIT_FAILURE;
-  return get_graphics ( face_ptr, number_triangles, number_points,
-                               facet_list_size, g_mem, normal_tolerance,
+  return get_graphics ( face_ptr, g_mem, normal_tolerance,
                                distance_tolerance, max_edge_length );
 }
 
 CubitStatus AcisQueryEngine::get_graphics(
   FACE* face_ptr,
-  int& number_triangles, int& number_points, int& facet_list_size,
   GMem* g_mem, unsigned short normal_tolerance, double distance_tolerance, 
   double max_edge_length ) const
 {
-    // Because this may be unnecessarily called twice,
-    // say there is one triangle.
-  if (!g_mem)
-  {
-    number_triangles = 1;
-    number_points = 3;
-    facet_list_size = 4;
-    return CUBIT_SUCCESS;
-  }
-
 #if CUBIT_ACIS_VERSION >= 800
   // distance tolerance ignore value was changed
   // handle it here for everyone in cubit
@@ -3501,13 +3647,6 @@
     return CUBIT_FAILURE;
   }
   
-    // Fill in the return variables and return.
-    // These variables really aren't needed, because they
-    // are returned as part of g_mem.
-  number_points    = g_mem->pointListCount;
-  facet_list_size  = g_mem->fListCount;
-  number_triangles = facetManager->polygon_count();
-  
   return CUBIT_SUCCESS;
 }
 
@@ -3523,11 +3662,9 @@
 // Creation Date : 03/04/97
 //-------------------------------------------------------------------------
 CubitStatus AcisQueryEngine::get_graphics( Curve* curve_ptr,
-                                           int& num_points,
                                            GMem* g_mem,
                                            double tolerance ) const
 {
-   CubitStatus rv;
    EDGE* the_EDGE = get_EDGE(curve_ptr);
      // NULL pointer is OK
 
@@ -3539,10 +3676,34 @@
        tolerance = SPAresfit;
    }
 
-   rv = this->facet_EDGE(the_EDGE, num_points, g_mem, (double)tolerance);
-   if (rv == CUBIT_FAILURE)
-      PRINT_ERROR("Unable to facet curve\n");
-   return rv;
+   SPAposition* io_points=NULL;
+   double* io_params=NULL;
+   int out_count;
+
+   outcome result = api_facet_edge(the_EDGE, tolerance, 0, 15, 0, out_count,
+       &io_points, &io_params);
+   if(!result.ok())
+   {
+     PRINT_ERROR("Unable to facet curve\n");
+     return CUBIT_FAILURE;
+   }
+
+   g_mem->allocate_polylines(out_count - 1);
+   g_mem->fListCount = 0;
+   g_mem->pointListCount = out_count;
+
+   GPoint* pts = g_mem->point_list();
+   for(int i=0; i<out_count; i++)
+   {
+     pts[i].x = io_points[i].x();
+     pts[i].y = io_points[i].y();
+     pts[i].z = io_points[i].z();
+   }
+
+   ACIS_DELETE [] io_points;
+   ACIS_DELETE [] STD_CAST io_params;
+
+   return CUBIT_SUCCESS;
 }
 
 CubitStatus AcisQueryEngine::facet_EDGE(const EDGE* EDGE_ptr, int& num_points,
@@ -3797,7 +3958,6 @@
 }
 
 AcisQueryEngine::AcisQueryEngine()
-  : stepInitialized(false)
 {
   assert( !instance_ );
 
@@ -3814,6 +3974,15 @@
 #endif
    initialize_base(&base_config);
 
+#if defined(WIN32) 
+ #if CUBIT_ACIS_VERSION >= 1700
+  #ifdef CAT
+     unlock_spatial_products_2380();
+  #else
+     unlock_spatial_products_2312();
+  #endif
+ #endif
+#endif
   
    outcome error = api_start_modeller ( CUBIT_FALSE);
    if ( !error.ok() )
@@ -3826,27 +3995,19 @@
    api_initialize_generic_attributes();
    api_initialize_spline();
    api_initialize_kernel();
+   api_initialize_blending();
    api_initialize_intersectors();
    api_initialize_constructors();
    api_initialize_euler_ops();
 
-#ifdef ACIS_IGES_TRANSLATOR
-     error = api_initialize_xiges();
-#endif //end IGES TRANSLATOR
+#ifdef IGTO
+   // Need the next 4 calls for iGTO
+   api_initialize_local_ops() ;
+   api_initialize_part_manager() ;
+   api_initialize_skinning() ;
+   api_initialize_warp() ;
+#endif
 
-
-#ifdef ACIS_STEP_TRANSLATOR
-     
-   outcome my_result = api_initialize_xstep();
-   ACIS_API_error(my_result);
-   stepInitialized = true;
-
-   // Convert assembly parts to separate bodies, as opposed as 
-   // one body with multiple lumps.
-   api_set_int_option( "stp_assemb_part_as_body", 1 );
-
-#endif /* ACIS_STEP_TRANSLATOR */
-
 #ifdef ACIS_PROE_TRANSLATOR
    api_initialize_proe();
 #endif
@@ -3874,11 +4035,17 @@
    this_option = find_option ( "tight_torus_box" );
    this_option -> set ( TRUE );
 
+#ifdef IGTO
+   // Need the next 2 lines for iGTO
+   this_option = find_option ( "annotation" );
+   this_option->set(FALSE);
+#endif
+
 #ifdef ACIS_IGES_TRANSLATOR
-   api_xiges_Ig2Ac_ConvFreeCurves_Set( TRUE );
+   //api_xiges_Ig2Ac_ConvFreeCurves_Set( TRUE );
 
    //reads in file based on units in file....prevents scaling
-   api_xacis_set_application_unit( spaxUnit_unknown );
+   //api_xacis_set_application_unit( spaxUnit_unknown );
 #endif
 
    this_option = find_option ( "compress_bb" );
@@ -3887,7 +4054,7 @@
 	// We can have a different refinement for each body passed in.  For
 	// example, we may want to adjust the refinement according to the body
 	// size.  But for demonstration, we will just use the same one for all.
-	REFINEMENT *refinement_ptr;
+	REFINEMENT *refinement_ptr = 0;
 	// Create a refinement.
 	outcome result = api_create_refinement(refinement_ptr);
     if (!result.ok())
@@ -4233,242 +4400,70 @@
    return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisQueryEngine::fire_ray( BodySM *body,
-                                       const CubitVector &ray_point,
-                                       const CubitVector &unit,
-                                       DLIList<double>& ray_params,
-                                       DLIList<GeometryEntity*> *entity_list) const
+CubitStatus
+AcisQueryEngine::fire_ray( CubitVector &origin,
+                           CubitVector &direction,
+                           DLIList<TopologyBridge*> &at_entity_list,
+                           DLIList<double> &ray_params,
+                           int max_hits,
+                           double ray_radius,
+                           DLIList<TopologyBridge*> *hit_entity_list ) const
 {
-   ray_params.clean_out();
-     
-     // fire a ray at the specified body, returning the entities hit and
-     // the parameters along the ray; return non-zero if error
-   
-     // since ACIS only returns a given entity once, even if it is hit
-     // twice (goofy, huh?), we need to fire two rays, one from each direction,
-     // and possibly more if the hits don't match
-   const double SCALE_FACTOR = 1.05;
-   
-   SPAposition pos_low(ray_point.x(), ray_point.y(), ray_point.z());
-   SPAunit_vector vector_low(unit.x(), unit.y(), unit.z());
-   
-     // use SPAresabs to get the surface when possible
-   double ray_radius = GEOMETRY_RESABS;
-   int hits_wanted = 0;
-   
-   ENTITY_LIST entities_low;
-   double *params_low = NULL;
-   outcome rc;
-   GeometryEntity *geom_entity;
-   BODY *body_ACIS =  get_BODY( body );
-   
-   
-   rc = api_ray_test_body (pos_low, vector_low, ray_radius, hits_wanted,
-                           body_ACIS, entities_low, params_low);
-   
-   
-   if (!rc.ok()) {
-      PRINT_ERROR("First ray fire failed for body\n");
-      ACIS_API_error(rc, "Ray fire");
-      entities_low.clear();
-      return CUBIT_FAILURE;
-   }
-   else if (!entities_low.count()) 
-   {
-     entities_low.clear();
-     return CUBIT_SUCCESS;
-   }
-     // get new position that's totally outside bounding SPAbox
-   CubitBox box = bounding_box(bounding_box(get_BODY(body)));
-     // use max range of bounding box - seems like it should be easier
-     // than this!
-   CubitVector ray_point2 = ray_point + SCALE_FACTOR * unit * 
-       CUBIT_MAX_4(box.x_range(), box.y_range(), box.z_range(), 0);
-   SPAposition pos_high(ray_point2.x(), ray_point2.y(), ray_point2.z());
-   
-   ENTITY_LIST entities_high;
-   double *params_high = NULL;
-   SPAunit_vector vector_high = -vector_low;
-   hits_wanted = 0;
-   
-   rc = api_ray_test_body (pos_high, vector_high, ray_radius, hits_wanted,
-                           body_ACIS, entities_high, params_high);
-   
-   
-   if (!rc.ok()) {
-      PRINT_ERROR("Second ray fire failed for body\n");
-      ACIS_API_error(rc, "Ray fire");
-      entities_low.clear();
-      entities_high.clear();
-      return CUBIT_FAILURE;
-   }
-     // now compare entities on list, marching backward on one list and
-     // forward on the other; if a mismatch is found, need to fire another ray
-   
-   if (DEBUG_FLAG(1)) {
-      CubitVector dum = ray_point;
-      GfxDebug::draw_vector(dum, ray_point2, CUBIT_YELLOW);
-      GfxDebug::flush();
-   }
-   
-   int ilow = 0;
-   int ihigh = entities_high.count()-1;
-   ENTITY_LIST entities_hit;
+  // Get ACIS entities
+  DLIList<ENTITY*> at_ENTITY_list;
+  TopologyBridge *bridge_ptr;
+  AcisBridge *acis_bridge_ptr;
+  ENTITY *ENTITY_ptr;
+  int i;
+  at_entity_list.reset();
+  for( i=at_entity_list.size(); i--; )
+  {
+    bridge_ptr = at_entity_list.get_and_step();
+    acis_bridge_ptr = CAST_TO( bridge_ptr, AcisBridge );
+    if( !acis_bridge_ptr )
+    {
+      PRINT_WARNING( "non-ACIS entity encountered where ACIS entity expected\n" );
+      continue;
+    }
 
-   double range_orig = (pos_high - pos_low).len();
-   double range = range_orig;
-     //  RefEntity *ref_entity;
-   double res_high = 5.0 * GEOMETRY_RESABS;
-   double offset = 0.0;
-   
-     // step up the low list and down the high list; entity on low list is
-     // always added; if it is the first hit on a repeated entity, it will 
-     // not match the entity on the high list; if this is the case, the low
-     // ray will be fired again and the low list counter reset; continue until
-     // we are at the beginning of the high list
-   TopologyEntity* topo_entity_ptr;
-   
-   while (ihigh >= 0) {
-      ray_params.append(params_low[ilow] + offset);
-      
-        // would have done this later, after while loop, if ACIS lists
-        // were not brain dead (no duplicates allowed!!!)
-      if (entity_list)
-      {
-         topo_entity_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity( entities_low[ilow] );
-         geom_entity = CAST_TO( topo_entity_ptr, GeometryEntity );
-         if (geom_entity) entity_list->append(geom_entity);
-      }
-      
-        // do both an entity check and a SPAposition check, in case a single
-        // entity is repeated (like the side surf of a cylinder)
-      if (entities_low[ilow] == entities_high[ihigh] &&
-          fabs(params_low[ilow] - (range - params_high[ihigh])) < res_high)
-      {
-         ilow++;
-         ihigh--;
-      }
-      
-      else {
-         if (DEBUG_FLAG(55)) {
-              // fire another low ray; add in 0.1% of the distance between high
-              // and low hit parameters to make sure pos_low isn't on the surf
-            double factor = .001 * (range - params_high[ihigh] - params_low[ilow]);
-            offset += params_low[ilow] + factor;
-            pos_low += (params_low[ilow] + factor) * vector_low; 
-            entities_low.clear();
-            hits_wanted = 0;
-            delete [] params_low;
-            rc = api_ray_test_body (pos_low, vector_low, ray_radius, hits_wanted,
-                                    body_ACIS, entities_low, params_low);
-            if (!rc.ok()) {
-               PRINT_ERROR("Supplemental ray fire failed for body\n");
-               ACIS_API_error(rc, "Ray fire");
-               
-                 // finish off params array with last hit on body
-               ray_params.append(range - params_high[0]);
-               if (entity_list) {
-                  topo_entity_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity( entities_low[ilow] );
-                  geom_entity = CAST_TO( topo_entity_ptr, GeometryEntity );
-                  if (geom_entity) entity_list->append(geom_entity);
-               }
-               if (ray_params.size() % 2 == 1) {
-                  ray_params.last();
-                  ray_params.append(ray_params.get());
-                  if (entity_list) {
-                     entity_list->last();
-                     entity_list->append(entity_list->get());
-                  }
-               }
-               return CUBIT_FAILURE;
-            }
-            else if (!entities_low.count()) {
-               PRINT_ERROR("Imbalanced rays in ray_fire!!!\n");
-               entities_low.clear();
-               entities_high.clear();
-               entities_hit.clear();
-               return CUBIT_FAILURE;
-            }
-            
-            ilow = 0;
-            range = range_orig - offset;
-         }
-         else {
-              // try this - don't even bother firing another low ray (it'll
-              // fail anyway) - just put the first high hit on the list and
-              // make sure we have an even number of hits
-            ray_params.append(range - params_high[0]);
-            if (entity_list) {
-               topo_entity_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity( entities_low[ilow] );
-               geom_entity = CAST_TO( topo_entity_ptr, GeometryEntity );
-               if (geom_entity) entity_list->append(geom_entity);
-            }
-            if (ray_params.size() % 2 == 1) {
-               ray_params.last();
-               ray_params.append(ray_params.get());
-               if (entity_list) {
-                  entity_list->last();
-                  entity_list->append(entity_list->get());
-               }
-            }
-            if (entities_low.count() == 1 && entities_high.count() == 1)
-            {
-               entities_low.clear();
-               entities_high.clear();
-               entities_hit.clear();
-               return CUBIT_SUCCESS;
-            }
-            else 
-            {
-               entities_low.clear();
-               entities_high.clear();
-               entities_hit.clear();
-               return CUBIT_FAILURE;
-            }
-         }
-      }
-   }
-   
-   if (ray_params.size()%2) {
-        // number of hits odd - put another hit in list in case it's a
-        // tangency hit; for num_hit > 1, need a point_in_body check
-      SPAposition pos;
-      int index = 0;
-      pos_low -= offset * vector_low; 
-      int i;
-      
-      ray_params.reset();
-      for (i = 1; i < ray_params.size(); i+=2) {
-         point_containment pc;
-         pos = pos_low + 0.5 * (ray_params.next(i-1) + ray_params.next(i)) * vector_low;
-         rc = api_point_in_body (pos, body_ACIS, pc);
-         if (!rc.ok()) {
-            PRINT_ERROR("Point in body during ray fire failed for body \n");
-            ACIS_API_error(rc, "Ray fire point in body");
-            entities_low.clear();
-            entities_high.clear();
-            entities_hit.clear();
-            return CUBIT_FAILURE;
-         }
-         
-         if (pc == point_outside) index = i-1;
-      }
-      
-        // index is the point that needs to be repeated; first bubble
-        // the list, then replace
-      ray_params.reset();
-      ray_params.step(index);
-      ray_params.insert(ray_params.get());
-      if (entity_list) {
-         entity_list->reset();
-         entity_list->step(index);
-         entity_list->insert(entity_list->get());
-      }
-   }
-   entities_low.clear();
-   entities_high.clear();
-   entities_hit.clear();
-   return CUBIT_SUCCESS;
+    ENTITY_ptr = acis_bridge_ptr->ENTITY_ptr();
+
+    at_ENTITY_list.append( ENTITY_ptr );
+  }
+
+  if( at_ENTITY_list.size() == 0 )
+    return CUBIT_FAILURE;
+
+  if( ray_radius == 0.0 )
+    ray_radius = SPAresabs;
+
+  DLIList<double> tmp_ray_params;
+  DLIList<ENTITY*> hit_ENTITY_list;
+
+  // Fire the ray at the ACIS entities
+  if( fire_ray( origin, direction, at_ENTITY_list, tmp_ray_params,
+    &hit_ENTITY_list, ray_radius, max_hits ) == CUBIT_FAILURE )
+    return CUBIT_FAILURE;
+
+  // Populate output
+  tmp_ray_params.reset();
+  hit_ENTITY_list.reset();
+  for( i=tmp_ray_params.size(); i--; )
+  {
+    ray_params.append( tmp_ray_params.get_and_step() );
+    
+    if( hit_entity_list )
+    {
+      // Get TopologyBridge from ENTITY
+      ENTITY_ptr = hit_ENTITY_list.get_and_step();
+
+      AcisBridge *ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ENTITY_ptr);
+      TopologyBridge *tb_ptr = CAST_TO( ab_ptr, TopologyBridge );
+      hit_entity_list->append( tb_ptr );
+    }
+  }
+
+  return CUBIT_SUCCESS;
 }
 
 int AcisQueryEngine::get_major_version() 
@@ -4614,18 +4609,23 @@
     this_minor = 0;
     valid = true;
   }
-  else if (major == 16 && this_minor >= 0 && this_minor <= 3) {
+
+  else if (major == 16 && this_minor >= 0 && this_minor <= 9) {
     this_minor = 0;
     valid = true;
   }
-  else if (major == 16 && this_minor >= 0 && this_minor <= 5) {
+  else if (major == 17 && this_minor >= 0 && this_minor <= 2) {
     this_minor = 0;
     valid = true;
   }
-  else if (major == 16 && this_minor >= 0 && this_minor <= 7) {
+  else if (major == 18 && this_minor >= 0 && this_minor <= 3) {
     this_minor = 0;
     valid = true;
   }
+  else if (major == 19 && this_minor >= 0 && this_minor <= 2) {
+    this_minor = 0;
+    valid = true;
+  }
   else {
     PRINT_ERROR("Unrecognized Acis version number %d.%d.\n", major, this_minor);
     return CUBIT_FAILURE;
@@ -5565,9 +5565,17 @@
     SPAposition pt1=cur->eval_position( new_end );
     
     // create the vertices
-    VERTEX *svert= ACIS_NEW VERTEX( ACIS_NEW APOINT(pt0) );
-    VERTEX *evert= ACIS_NEW VERTEX( ACIS_NEW APOINT(pt1) );	
+    APOINT *apoint_0 = NULL;
+    APOINT *apoint_1 = NULL;
     
+    API_BEGIN;
+    apoint_0 = ACIS_NEW APOINT( pt0 );
+    apoint_1 = ACIS_NEW APOINT( pt1 );
+    API_END;
+
+    VERTEX *svert= ACIS_NEW VERTEX( apoint_0 );
+    VERTEX *evert= ACIS_NEW VERTEX( apoint_1 );
+    
     // create the curve
     CURVE *the_curve=make_curve( *cur );
 #ifdef BOYD16
@@ -5940,7 +5948,7 @@
     ACIS_API_error( result, "transforming BODY" );
     return CUBIT_FAILURE;
   }
-  
+
   TRANSFORM* identity = new TRANSFORM( scale_transf(1.0) );
   result = api_change_body_trans( BODY_ptr, identity, FALSE );
   identity->lose();
@@ -6109,6 +6117,19 @@
   api_terminate_warp();
 #endif
 
+  //scaling will scale up gaps in the model, which can corrupt it.
+  //do a quick check here to warn the user that he might want to heal
+  //the model if it got corrupted due to the scale
+  insanity_list *list_of_problems = NULL;
+  BODY* BODY_ptr = get_BODY( body );
+  api_check_entity( (ENTITY*)BODY_ptr, list_of_problems );
+
+  if ( list_of_problems && list_of_problems->count() )
+  {
+    PRINT_WARNING("Model may be corrupted from the scaling opeartion.\n"); 
+    PRINT_INFO("       Consider healing it.\n"); 
+  }
+
   return result;
 }
 
@@ -6237,10 +6258,7 @@
   remove_cubit_owner_attrib_in_BODY(acis_body_1);
   remove_cubit_owner_attrib_in_BODY(acis_body_2);
 
-  CubitBoolean bodies_overlap = CUBIT_FALSE;
-
-#if CUBIT_ACIS_VERSION < 1600 
-  bodies_overlap = CUBIT_TRUE;
+  CubitBoolean bodies_overlap = CUBIT_TRUE;
   BOOL_TYPE bool_type = INTERSECTION;
   outcome result = api_boolean(acis_body_1, acis_body_2, bool_type );
   if (acis_body_2 == NULL ||
@@ -6249,26 +6267,6 @@
   {
     bodies_overlap = CUBIT_FALSE;
   }
-#else
-  bodies_overlap = CUBIT_FALSE;
-  body_clash_result clash_result;
-  outcome result = api_clash_bodies( acis_body_1, acis_body_2, 
-                                     clash_result, CLASH_CLASSIFY_BODIES );
-  if (!result.ok())
-  {
-    PRINT_ERROR("Intersection operation failed.\n");
-    AcisQueryEngine::instance()->ACIS_API_error(result, "intersect Bodies");
-    return CUBIT_FALSE;
-  }
-
-  if( clash_result.clash_type() == CLASH_CONTAINED ||
-      clash_result.clash_type() == CLASH_CONTAINED_ABUTS ||
-      clash_result.clash_type() == CLASH_COINCIDENT ||
-      clash_result.clash_type() == CLASH_INTERLOCK )
-  {
-    bodies_overlap = CUBIT_TRUE;
-  }
-#endif
   
   if ( acis_body_1 != NULL )
     AcisQueryEngine::instance()->delete_ACIS_BODY(acis_body_1);
@@ -6298,48 +6296,21 @@
   BODY *acis_body_1_orig = AcisQueryEngine::get_BODY(body_ptr_1);
   BODY *acis_body_2_orig = AcisQueryEngine::get_BODY(body_ptr_2);
 
-  CubitBoolean bodies_overlap = CUBIT_FALSE;
+  CubitBoolean bodies_overlap = CUBIT_TRUE;
 
-#if CUBIT_ACIS_VERSION < 1600 
-  BODY *acis_body_1, *acis_body_2; 
-  api_copy_body(acis_body_1_orig, acis_body_1);
-  api_copy_body(acis_body_2_orig, acis_body_2);
+  API_NOP_BEGIN;
+    BOOL_TYPE bool_type = INTERSECTION;
+    remove_cubit_owner_attrib_in_BODY(acis_body_1_orig);
+    remove_cubit_owner_attrib_in_BODY(acis_body_2_orig);
+    outcome result = api_boolean(acis_body_1_orig, acis_body_2_orig, bool_type );
+    if (acis_body_2_orig == NULL ||
+        acis_body_2_orig->lump() == NULL && acis_body_2_orig->wire() == NULL ||
+        !result.ok())
+    {
+      bodies_overlap = CUBIT_FALSE;
+    }
+  API_NOP_END;
 
-  //remove the attributes
-  remove_cubit_owner_attrib_in_BODY(acis_body_1);
-  remove_cubit_owner_attrib_in_BODY(acis_body_2);
-
-  bodies_overlap = CUBIT_TRUE;
-  BOOL_TYPE bool_type = INTERSECTION;
-  outcome result = api_boolean(acis_body_1, acis_body_2, bool_type );
-  if (acis_body_2 == NULL ||
-      acis_body_2->lump() == NULL && acis_body_2->wire() == NULL ||
-      !result.ok())
-  {
-    bodies_overlap = CUBIT_FALSE;
-  }
-  if ( acis_body_2 != NULL )
-    AcisQueryEngine::instance()->delete_ACIS_BODY(acis_body_2);
-#else
-  bodies_overlap = CUBIT_FALSE;
-  body_clash_result clash_result;
-  outcome result = api_clash_bodies( acis_body_1_orig, acis_body_2_orig, 
-                                     clash_result, CLASH_CLASSIFY_BODIES );
-  if (!result.ok())
-  {
-    PRINT_ERROR("Intersection operation failed.\n");
-    AcisQueryEngine::instance()->ACIS_API_error(result, "intersect Bodies");
-    return CUBIT_FALSE;
-  }
-
-  if( clash_result.clash_type() == CLASH_CONTAINED ||
-      clash_result.clash_type() == CLASH_CONTAINED_ABUTS ||
-      clash_result.clash_type() == CLASH_COINCIDENT ||
-      clash_result.clash_type() == CLASH_INTERLOCK )
-  {
-    bodies_overlap = CUBIT_TRUE;
-  }
-#endif
   return bodies_overlap;
 }
 
@@ -6374,6 +6345,9 @@
     listcat( entity_list, tmp_list );
     tmp_list.clear();
     result = api_restore_entity_list( file_ptr, ascii, tmp_list );
+    if (!result.ok())
+      ACIS_API_error(result);
+
   } while (result.ok());
   remove_refinements( entity_list );
 
@@ -6392,17 +6366,31 @@
   
   PRINT_INFO( "Reading IGES file '%s'...\n", file_name );
 
-  FILE *logfile_ptr = fopen( logfilename, "w" );
-  if( logfile_ptr == NULL )
-  {
-    PRINT_ERROR( "unable to open iges logfile '%s'\n", logfilename );
-    return CUBIT_FAILURE;
-  }
+  SPAIFile log_file( logfilename );
 
-  SPAXProgressReport_fct = progress_report_function;
   AppUtil::instance()->progress_tool()->start(0, 100, "Importing IGES File:" );
-  outcome result = api_xiges_read(entity_list, (char *)file_name, (char *)logfilename, heal);
 
+  SPAIOptions options;
+  SPAIValue my_false(FALSE);
+  options.Add( SPAIOptionName::Healing, my_false);
+  SPAIValue my_rep("BRep+Assembly");
+  options.Add( SPAIOptionName::Representation, my_rep);
+  options.Add( SPAIOptionName::TranslateFreeCurves, true);
+
+  SPAIDocument src( file_name );
+  SPAIAcisDocument dst;
+  SPAIConverter converter;
+  converter.SetOptions( options );
+  converter.SetProgressCallback( (SPAIProgressCallback)progress_report_function );
+  converter.StartLog(log_file);
+  SPAIResult result = converter.Convert(src, dst );
+  converter.StopLog(log_file);
+
+  ENTITY_LIST *tmp_entity_list = NULL;
+  dst.GetEntities( tmp_entity_list );
+  dst.DetachEntities();
+  entity_list.add( *tmp_entity_list ); 
+
   //convert all bodies to 2d sheet bodies
   ENTITY *tmp_ent;
   entity_list.init();
@@ -6411,23 +6399,71 @@
     if (is_BODY( tmp_ent ) )
       api_body_to_2d( (BODY*)tmp_ent );
   }
-
-  fclose( logfile_ptr );
   
   PRINT_INFO( "Done\n" );
 
-  if( !result.ok() )
+  if( result.IsFailure() )
   {
-    ACIS_API_error( result );
-    PRINT_ERROR( "problem reading from IGES file '%s'\n", file_name );
-    return CUBIT_FAILURE;
+    //spatial categorized these TOO_BIG/SMALL errors as fatal.  We're
+    //going ahead anyhow, simply telling the user to scale down the model
+    if( result.GetNumber() & SPAX_ACIS_E_BOX_TOO_BIG )
+    {
+      PRINT_WARNING("'%s'", result.GetMessage() );
+      PRINT_INFO("Your model is very large. Operations on your model could be \n" 
+                 "numerically unstable.  Consider scaling your model down.\n" );
+    }
+    else if( result.GetNumber() & SPAX_ACIS_E_BOX_TOO_SMALL )
+    {
+      PRINT_WARNING("'%s'", result.GetMessage() );
+      PRINT_INFO("Your model is very small. Operations on your model could be \n" 
+                 "numerically unstable.  Consider scaling your model up.\n");
+    }
+    else
+    {
+      PRINT_ERROR( "problem reading from IGES file '%s'\n", file_name );
+      PRINT_ERROR("'%s'", result.GetMessage() );
+      return CUBIT_FAILURE;
+    }
+  } 
+
+  // fix for MiST - healer may not have worked if 
+  //midsurfaces were not sheet bodies during IGES import
+  if (heal)
+  {
+    entity_list.init();
+    AppUtil::instance()->progress_tool()->start(0, entity_list.count(), "Healing Model:" );
+
+    while( (tmp_ent = entity_list.next()) != NULL) 
+    {
+      if(is_BODY( tmp_ent ) )
+      {
+        outcome result;
+        result = api_hh_init_body_for_healing( (BODY*)tmp_ent );	
+        if( !result.ok() )
+        {
+          ACIS_API_error( result );       
+          //Don't bail out if you have trouble healing a body
+        }
+        result = api_hh_auto_heal( (BODY*)tmp_ent );
+        if( !result.ok() )
+        {
+          ACIS_API_error( result );          
+          //Don't bail out if you have trouble healing a body
+        }
+        api_hh_end_body_for_healing( (BODY*)tmp_ent );
+      }
+      AppUtil::instance()->progress_tool()->step();
+    }
   }
+
   return CUBIT_SUCCESS;
 }
 #endif
 
 #ifdef ACIS_CATIA_TRANSLATOR
-CubitStatus AcisQueryEngine::read_catia_file(const char* file_name, const char* logfile_name, ENTITY_LIST &entity_list)
+CubitStatus AcisQueryEngine::read_catia_file(const char* file_name, 
+                                             const char* logfile_name, 
+                                             ENTITY_LIST &entity_list)
 {
   char* logfilename = NULL;
   if( !logfile_name || !strcmp( logfile_name, "" ) )
@@ -6467,11 +6503,6 @@
 CubitStatus AcisQueryEngine::read_step_file(const char* file_name, const char* logfile_name, 
                                             ENTITY_LIST &entity_list, bool heal )
 {
-  if ( !stepInitialized ) {
-    PRINT_ERROR("The STEP translater has not been properly initialized.\n");
-    return CUBIT_FAILURE;
-  }
-
   char* logfilename = NULL;
   if( !logfile_name || !strcmp( logfile_name, "" ) )
       strcpy(logfilename, "step_import.log");
@@ -6479,38 +6510,85 @@
       logfilename = (char *)logfile_name;
 
   PRINT_INFO( "Reading STEP file '%s'...\n", file_name );
-  
-  SPAXProgressReport_fct = progress_report_function;
 
-  api_xstep_set_option("step_to_acis_attrib_transf", TRUE);
+  SPAIFile logFile( logfilename );
+
   AppUtil::instance()->progress_tool()->start(0, 100, "Importing STEP File:" );
-  outcome result = api_xstep_read( entity_list, (char *)file_name, (char *)logfilename, heal ); 
 
-  if( !result.ok() )
+  SPAIOptions options;
+  SPAIValue my_true(TRUE);
+  options.Add( SPAIOptionName::TranslateAttributes, my_true);  
+  
+  SPAIConverter converter;
+  converter.SetOptions( options );
+  converter.SetProgressCallback( (SPAIProgressCallback)progress_report_function );
+  converter.StartLog(logFile);
+
+  SPAIAcisDocument dst;
+  SPAIDocument src( file_name );
+  SPAIResult import_result = converter.Convert(src, dst );
+  converter.StopLog(logFile);
+
+  ENTITY_LIST *tmp_entity_list = NULL;
+  dst.GetEntities( tmp_entity_list );
+  dst.DetachEntities();
+  entity_list.add( *tmp_entity_list ); 
+
+  AppUtil::instance()->progress_tool()->end();
+
+  if( !import_result.IsSuccess() )
   {
-    if( result.error_number() == SPAX_ACIS_E_BOX_TOO_BIG )
+    //spatial categorized these TOO_BIG/SMALL errors as fatal.  We're
+    //going ahead anyhow, simply telling the user to scale down the model
+    if( import_result.GetNumber() & SPAX_ACIS_E_BOX_TOO_BIG )
     {
-      const char* warning = find_err_ident(result.error_number());
-      PRINT_WARNING("%s\n", find_err_mess( result.error_number() ) );
+      PRINT_WARNING("'%s'", import_result.GetMessage() );
       PRINT_INFO("Your model is very large. Operations on your model could be \n" 
-                 "numerically unstable.  Consider scaling your model down.\n", warning);
+                 "numerically unstable.  Consider scaling your model down.\n" );
     }
-    else if( result.error_number() == SPAX_ACIS_E_BOX_TOO_SMALL )
+    else if( import_result.GetNumber() & SPAX_ACIS_E_BOX_TOO_SMALL )
     {
-      const char* warning = find_err_ident(result.error_number());
-      PRINT_WARNING("%s\n", find_err_mess( result.error_number() ) );
+      PRINT_WARNING("'%s'", import_result.GetMessage() );
       PRINT_INFO("Your model is very small. Operations on your model could be \n" 
-                 "numerically unstable.  Consider scaling your model up.\n", warning);
+                 "numerically unstable.  Consider scaling your model up.\n");
     }
     else
     {
-      ACIS_API_error( result );
       PRINT_ERROR( "problem reading from STEP file '%s'\n", file_name );
-      AppUtil::instance()->progress_tool()->end();
+      PRINT_ERROR("'%s'", import_result.GetMessage() );
       return CUBIT_FAILURE;
     }
+  } 
+
+  ENTITY *tmp_ent;
+  if (heal)
+  {
+    entity_list.init();
+    AppUtil::instance()->progress_tool()->start(0, entity_list.count(), "Healing Model:" );
+
+    while( (tmp_ent = entity_list.next()) != NULL) 
+    {
+      if(is_BODY( tmp_ent ) )
+      {
+        outcome result;
+        result = api_hh_init_body_for_healing( (BODY*)tmp_ent );	
+        if( !result.ok() )
+        {
+          ACIS_API_error( result );       
+          //Don't bail out if you have trouble healing a body
+        }
+        result = api_hh_auto_heal( (BODY*)tmp_ent );
+        if( !result.ok() )
+        {
+          ACIS_API_error( result );          
+          //Don't bail out if you have trouble healing a body
+        }
+        api_hh_end_body_for_healing( (BODY*)tmp_ent );
+      }
+      AppUtil::instance()->progress_tool()->step();
+    }
   }
-  AppUtil::instance()->progress_tool()->end();
+
   return CUBIT_SUCCESS;
 }
 
@@ -6532,6 +6610,20 @@
       new ATTRIB_SNL_SIMPLE( currItem, tmp_attrib );
       delete tmp_attrib;
     }          
+    //read in other names
+    label_attrib = NULL;
+    api_find_named_attribute( currItem, "ATTRIB_XACIS_NAME",(ATTRIB_GEN_NAME*&)(label_attrib) );
+    if (label_attrib != NULL)
+    {
+      const char *part_name = label_attrib->value();	
+      CubitString tmp_string( part_name );
+      if( tmp_string.find( "Next assembly relationship" ) != MAX_POS ) 
+        continue;	
+	
+      CubitSimpleAttrib *tmp_attrib = new CubitSimpleAttrib( "ENTITY_NAME", part_name );
+      new ATTRIB_SNL_SIMPLE( currItem, tmp_attrib );
+      delete tmp_attrib;
+    }
   }
 }
 
@@ -6599,3 +6691,103 @@
 }
 #endif
 
+CubitStatus
+AcisQueryEngine::fire_ray( CubitVector &origin,
+                           CubitVector &direction,
+                           DLIList<ENTITY*> &at_ENTITY_list,
+                           DLIList<double> &ray_params,
+                           DLIList<ENTITY*> *hit_ENTITY_list,
+                           double ray_radius,
+                           int hits_wanted ) const
+{
+  int i;
+
+  // Compute the ray parameters
+  SPAposition ray_origin( origin.x(), origin.y(), origin.z() );
+  SPAunit_vector ray_dir( direction.x(), direction.y(), direction.z() );
+
+  // Get targets
+  int num_targets = at_ENTITY_list.size();
+  ENTITY** targets = ACIS_NEW ENTITY*[ num_targets ];
+  at_ENTITY_list.reset();
+  for( i=0; i<num_targets; i++ ) 
+    targets[i] = at_ENTITY_list.get_and_step();
+
+  outcome result;
+  hit *hit_list = NULL;
+
+  //WORKAROUND
+  //ask for all hits b/c ACIS doesn't always return the closest hit if only ask for 1
+  // To remove this workaround, delete the following variable and call the api function
+  // with hits_wanted.  The code at the end of this function which 'minds the number of hits wanted'
+  // can also be deleted.
+  int hits_wanted_bugfix = 0; //return all hits
+
+  result = api_raytest_ents( ray_origin, ray_dir, ray_radius, hits_wanted_bugfix, 
+    num_targets, targets, hit_list );
+
+  ACIS_DELETE [] STD_CAST targets;
+
+  if( hit_list )
+  {
+    // Walk through the list of hits
+    hit *hit_ptr = hit_list;
+
+    ray_params.append( (double)hit_ptr->ray_param );
+    if( hit_ENTITY_list )
+      hit_ENTITY_list->append( hit_ptr->entity_hit );
+
+    while( (hit_ptr = hit_ptr->next) != NULL )
+    {
+      if( hit_ptr->type_of_hit == hit_thru )
+      {
+        ray_params.append( (double)hit_ptr->ray_param );
+        if( hit_ENTITY_list )
+          hit_ENTITY_list->append( hit_ptr->entity_hit );
+      }
+    }
+    //now cleanup
+    hit_ptr = hit_list;
+    while( hit_ptr->next != NULL )
+    {
+      hit *next_ptr = hit_ptr->next;
+      ACIS_DELETE hit_ptr;
+      hit_ptr = next_ptr;
+    }
+
+    //mind the number of hits wanted. Don't return more than that number
+    // Sort ray_params (low to high) and sort hit_ENTITY_list to match
+    //  This will ensure entities are in order of who got hit first
+    //  Do the sort by adding to a map (should auto-sort)
+
+    int hits_returned = 0;
+    std::map<double, ENTITY*> temp_map;
+    ray_params.reset();
+    if( hit_ENTITY_list) hit_ENTITY_list->reset();
+
+    for( i=0; i<ray_params.size(); i++ )
+      temp_map.insert(std::map<double, ENTITY*>::value_type( ray_params.get_and_step(), 
+      hit_ENTITY_list ? hit_ENTITY_list->get_and_step() : 0 ) );
+
+    // The map should be sorted, so iterate through it and add to the official lists
+    ray_params.clean_out();
+    if( hit_ENTITY_list) hit_ENTITY_list->clean_out();
+
+    std::map<double, ENTITY*>::iterator iter;
+    for (iter=temp_map.begin(); iter != temp_map.end(); iter++)
+    {
+      if ( (hits_wanted == 0) || (hits_returned < hits_wanted) )
+      {
+        ray_params.append(iter->first);
+        if( hit_ENTITY_list) hit_ENTITY_list->append(iter->second);
+        hits_returned++;
+      }
+      else
+        break;
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisQueryEngine.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -131,6 +131,9 @@
   friend class AcisModifyEngine;
   friend class AcisHealerTool;
   friend class AcisSurfaceTool;
+#ifdef ACIS_TWEAK
+  friend class AcisTweakToolCAT;
+#endif
   friend class AcisTweakTool;
   friend class AcisEdgeTool;
   friend class AcisToolUtil;
@@ -161,7 +164,6 @@
   const char * modeler_type()
      { return "ACIS"; }
 
-  
 //HEADER- RTTI and safe casting functions.
   
   virtual const type_info& entity_type_info() const ;
@@ -289,17 +291,11 @@
 //HEADER- Functions related to faceting
   
   virtual CubitStatus get_graphics(Surface* surface_ptr,
-                                          int& number_triangles,
-                                          int& number_points,
-                                          int& number_facets,
                                           GMem* gMem,
                                           unsigned short normal_tolerance,
                                           double distance_tolerance,
                                           double max_edge_length ) const;
   CubitStatus get_graphics( FACE* face_ptr,
-                                  int& number_triangles,
-                                  int& number_points,
-                                  int& number_facets,
                                   GMem* gMem,
                                   unsigned short normal_tolerance,
                                   double distance_tolerance,
@@ -326,7 +322,6 @@
     //- CUBIT_FAILURE is returned.
 
   virtual CubitStatus get_graphics( Curve* curve_ptr,
-                                    int& num_points,
                                     GMem* gMem = NULL,
                                     double tolerance = 0.0 ) const;
     //R CubitStatus
@@ -422,13 +417,20 @@
     //- Gets the minimum distance between two entities and the closest positions 
     //- on those entities. Supports vertices, curves, surfaces, volumes and bodies.
 
-  virtual CubitStatus fire_ray( BodySM *body,
-                                const CubitVector &ray_point,
-                                const CubitVector &unit,
-                                DLIList<double>& ray_params,
-                                DLIList<GeometryEntity*> *entity_list) const;
-    //- Fire a ray at the specified body, returning the entities hit and
-    // the parameters along the ray; return non-zero if error
+  virtual CubitStatus fire_ray( CubitVector &origin,
+                                CubitVector &direction,
+                                DLIList<TopologyBridge*> &at_entity_list,
+                                DLIList<double> &ray_params,
+                                int max_hits = 0,
+                                double ray_radius = 0.0,
+                                DLIList<TopologyBridge*> *hit_entity_list=0 ) const;
+    //- Fire a ray at specified entities, returning the parameters (distances)
+    //- along the ray and optionally the entities hit.  Returned lists are
+    //- appended to.  Input entities can be any of bodies, volumes, faces,
+    //- edges or vertices (note TopologyEntity is used because a Body is not a 
+    //- GeometryEntity).  Optionally you can specify the maximum number of hits
+    //- to return (default = 0 = unlimited), and the ray radius to use for
+    //- intersecting the entities (default = 0.0 = use modeller default).
 
   virtual CubitStatus transform_vec_position( 
     CubitVector const& position_vector,
@@ -560,10 +562,18 @@
 #endif
 
 //HEADER- Functions that create TopologyEntities
+  public: // KGM expose this for now
   BodySM *populate_topology_bridges(BODY *body_ptr) const;
   Lump *populate_topology_bridges(LUMP *lump_ptr) const;
   Surface *populate_topology_bridges(FACE *face_ptr) const;
   Curve *populate_topology_bridges(EDGE *edge_ptr) const;
+
+  ENTITY* get_ENTITY_of_entity( TopologyBridge *topobridge_ptr ) const;
+    //- Returns the ENTITY of the given TopologyBridge
+  
+
+
+  private:
   Point *populate_topology_bridges(VERTEX *vertex_ptr) const;
     //- go through the entity passed in, make sure it has TopologyBridge
     //- entities (or create them)
@@ -580,6 +590,9 @@
     //- Given a list of RefEdges, return all the EDGEs
   
 //HEADER- Functions that create ACIS ENTITYs
+  int save_ENTITYs_as_sat_file ( ENTITY_LIST *entity_list, 
+                                 const char* filename,
+                                 const char* update_mode ) const;
   
   int save_ENTITY_as_sat_file (ENTITY* entity_ptr, 
                                const char* filename,
@@ -618,6 +631,7 @@
     //- own unhooking.
   
 //HEADER- Functions related to geometric comparison operations
+  CubitBoolean about_spatially_equal (EDGE* E1, EDGE* E2) const;
   
   CubitBoolean about_spatially_equal ( const SPAposition &pos1, 
                                        const SPAposition &pos2, 
@@ -685,13 +699,10 @@
     //- Return the BODY that "owns" the VERTEX associated with the input 
     //- RefVertex.
 
-  ENTITY* get_ENTITY_of_entity( TopologyBridge *ref_entity_ptr ) const;
-    //- Returns the ENTITY of the given RefEntity
-  
   ENTITY* get_ENTITY_of_entity( BODY* BODY_ptr,
-                                TopologyBridge* topoentity_ptr) const;
+                                TopologyBridge* topobridge_ptr) const;
     //- Returns the ENTITY in the input BODY_ptr whose parent attribute 
-    //- corresponds to the input TopologyEntity pointer
+    //- corresponds to the input TopologyBridge pointer
   
 //HEADER- Bounding box functions.
   
@@ -873,6 +884,26 @@
   CubitStatus remove_refinements( ENTITY_LIST& list );
     //- Clear any refinements set on objects in .SAT file after
     //- import.
+
+  CubitStatus fire_ray( CubitVector &origin,
+                        CubitVector &direction,
+                        DLIList<ENTITY*> &at_ENTITY_list,
+                        DLIList<double> &ray_params,
+                        DLIList<ENTITY*> *hit_ENTITY_list,
+                        double ray_radius,
+                        int hits_wanted) const;
+    //- Fire a ray at specified entities from the given ray origin in the given
+    //- ray direction, returning the parameters (distances) along the ray and
+    //- optionally the entities hit.  Only entities in the forward direction
+    //- along the ray can be hit.  Returned lists are appended to.  The radius
+    //- of the ray can optionally be specified.  The number of hits can be
+    //- limited by supplying hits_wanted (0 means return all hits).  Note the
+    //- returned number of ray_params will always equal the number of returned
+    //- ENTITIES hit.
+    //- NOTE: returned entities hit might be "hidden" beneath virtual entities.
+    //-       To resolve to visible entities, use "get_visible_ents_for_hits"
+    //-       in GeometryQueryTool.
+
   
   static const int MAX_NUM_CURVE_POINTS;
   static const int AQE_SUBMINOR_VERSION;
@@ -880,8 +911,6 @@
   static double   *curveParams;
   AcisFacetManager* facetManager;
   
-  bool stepInitialized;
-
   int exportVersion;
 };
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -6,51 +6,6 @@
 //- Version: $Id:
 
 // ********** BEGIN ACIS INCLUDES             **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/acis.hxx"
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/geom/transfrm.hxx"
-#include "kernel/kerndata/top/edge.hxx"
-#include "kernel/kerndata/top/loop.hxx"
-#include "kernel/kerndata/top/coedge.hxx"
-#include "kernel/kerndata/top/face.hxx"
-#include "kernel/kerndata/top/wire.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "kernel/kernutil/law/law.hxx"
-#include "kernel/spline/api/spl_api.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "constrct/kernapi/api/cstrapi.hxx"
-#include "skin/kernapi/api/skinapi.hxx"
-#include "skin/sg_husk/skin/skin.hxx"
-#include "offset/kernapi/api/ofstapi.hxx"
-#include "cover/kernapi/api/coverapi.hxx"
-#include "kernel/geomhusk/bnd_crv.hxx"
-#include "kernel/geomhusk/getowner.hxx"
-#include "baseutil/vector/interval.hxx"
-#include "intersct/kerngeom/curve/curextnd.hxx"
-#include "kernel/kerngeom/curve/extend.hxx"
-#include "kernel/kerngeom/curve/curdef.hxx"
-#include "kernel/kerndata/geom/curve.hxx"
-#include "kernel/kerndata/geom/point.hxx"
-#include "kernel/kerndata/geom/surface.hxx"
-#include "kernel/kerndata/top/shell.hxx"
-#include "kernel/kerndata/top/lump.hxx"
-#include "kernel/kerndata/top/vertex.hxx"
-#include "kernel/kerndata/geom/cnstruct.hxx"
-
-#include "baseutil/vector/position.hxx"
-#include "baseutil/vector/unitvec.hxx"
-#include "baseutil/logical.h"
-
-#ifdef ACIS_LOCAL_OPS
-#include "lop_husk/api/lop_api.hxx"
-#endif
-#include "boolean/kernapi/api/boolapi.hxx"
-#include "kernel/geomhusk/copyent.hxx" // copy single entity
-
-#else
 #include "acis.hxx" 
 #include "api.hxx" 
 #include "kernapi.hxx" 
@@ -86,15 +41,13 @@
 #include "position.hxx"
 #include "unitvec.hxx" 
 #include "logical.h"
+#include "boolapi.hxx" 
+#include "copyent.hxx" // copy single entity
 
 #ifdef ACIS_LOCAL_OPS
   #include "lop_api.hxx"
 #endif
-#include "boolapi.hxx" 
 
-#include "copyent.hxx" // copy single entity
-#endif
-
 // ********** END ACIS INCLUDES               **********
 
 // ********** BEGIN CUBIT INCLUDES            **********
@@ -108,6 +61,7 @@
 #include "GeometryQueryTool.hpp"
 #include "Body.hpp"
 #include "BodyACIS.hpp"
+#include "PointACIS.hpp"
 #include "CurveACIS.hpp"
 #include "SurfaceACIS.hpp"
 
@@ -121,6 +75,7 @@
 
 // For multiple surfaces
 #include "Loop.hpp"
+#include "Point.hpp"
 #include "RefVertex.hpp"
 #include "CoEdge.hpp"
 
@@ -739,7 +694,8 @@
 
 CubitStatus
 AcisSurfaceTool::create_skin_surface( DLIList<Curve*>& curves,
-                                      BodySM*& new_body )
+                                      BodySM*& new_body,
+                                      DLIList<Curve*>& guides)
 {
   new_body = NULL;
   int i;
@@ -756,6 +712,9 @@
   
   // Create the wires from the edges 
   BODY** wires = new BODY*[curves.size()];
+  EDGE** edge_guides = NULL;
+  if (guides.size())
+      edge_guides = new EDGE*[guides.size()];
   
   Curve* curve_ptr;
   EDGE* EDGE_ptr;
@@ -814,6 +773,31 @@
     num_wires++;
   }
 
+  int num_guides = 0;
+  guides.reset();
+  for (i = 0; i < guides.size(); i++)
+  {
+      curve_ptr = guides.get_and_step();
+      CurveACIS* acis_curve_ptr = dynamic_cast<CurveACIS*>(curve_ptr);
+
+      // Get the EDGE ptr from the RefEdge
+      if( !acis_curve_ptr || !(EDGE_ptr = acis_curve_ptr->get_EDGE_ptr()) )
+      {
+          PRINT_ERROR( "Curve guide is not an ACIS curve\n" );
+          for( i=0; i<num_wires; i++ )
+              api_delent( wires[i] );
+          for( i=0; i<num_guides; i++)
+              api_delent( edge_guides[i] );
+          delete [] wires;
+          delete [] edge_guides;
+          return CUBIT_FAILURE;
+      }
+
+      result = api_edge( EDGE_ptr, copied_EDGE_ptr );
+      edge_guides[i] = copied_EDGE_ptr;
+      num_guides++;
+  }
+
   BODY *skin_body = NULL; 
   
   PRINT_INFO( "Creating skin surface...\n" );
@@ -825,13 +809,19 @@
     tmp_skin_options.set_solid(1);
   }
   
-  result = api_skin_wires( num_wires, wires, skin_body, &tmp_skin_options ); 
+  if (num_guides == 0)
+    result = api_skin_wires( num_wires, wires, skin_body, &tmp_skin_options ); 
+  else
+    result = api_skin_wires( num_wires, wires, num_guides, edge_guides, skin_body, &tmp_skin_options );
 
   // Cleanup memory
   for( i=0; i<num_wires; i++ )
     api_delent( wires[i] );
   delete [] wires;
-  
+  for( i=0; i<num_guides; i++)
+      api_delent( edge_guides[i] );
+  delete [] edge_guides;
+
   if( !result.ok() )
   {
     AcisQueryEngine::instance()->ACIS_API_error(result);
@@ -1311,6 +1301,152 @@
   return CUBIT_SUCCESS;
 }
 
+CubitStatus 
+AcisSurfaceTool::create_surface( DLIList<Point*>& points,
+                                 BodySM *&new_body )
+{
+  int i, j;
+  outcome result;
+
+  // Create curves connecting the points
+  DLIList<EDGE*> EDGE_list;
+  EDGE *EDGE_ptr;
+
+  points.reset();
+  Point *start_point = points.get_and_step();
+  PointACIS* acis_s_point = CAST_TO(const_cast<Point*>(start_point), PointACIS) ; 
+  VERTEX *start_vert = acis_s_point->get_VERTEX_ptr();
+
+  CubitVector coord1 = start_point->coordinates();
+  SPAposition start( coord1.x(), coord1.y(), coord1.z() );
+  SPAposition end;
+  for( i=0; i<points.size(); i++ )
+  {
+    Point *end_point = points.get_and_step();
+    CubitVector coord2 = end_point->coordinates(); 
+    end.set_x( coord2.x() );
+    end.set_y( coord2.y() );
+    end.set_z( coord2.z() );
+
+    if( coord1.within_tolerance( coord2, GEOMETRY_RESABS ) )
+    {
+       PRINT_ERROR( "Attempt to create a line between coincident points at (%f, %f, %f)\n",
+          start.x(), start.y(), start.z() );
+       for( j=0; j<EDGE_list.size(); j++ )
+      {
+        EDGE_ptr = EDGE_list.get_and_step();
+        api_delent( EDGE_ptr );
+      }
+      return CUBIT_FAILURE;
+    }
+
+    PointACIS* acis_e_point = CAST_TO(const_cast<Point*>(end_point), PointACIS) ; 
+    VERTEX *end_vert = acis_e_point->get_VERTEX_ptr();
+    
+    
+    STRAIGHT *tmp_straight; 
+    API_BEGIN;
+    tmp_straight = new STRAIGHT( start, normalise( end - start ) );
+    API_END;
+
+    EDGE *tmp_edge = new EDGE( start_vert, end_vert, tmp_straight, FORWARD );
+
+    EDGE_list.append( tmp_edge );
+    start_vert = end_vert; 
+    start = end;
+    coord1 = coord2;
+  }
+
+  // Make a WIRE from the EDGES
+  int edge_count = points.size();
+  EDGE** EDGEs = new EDGE* [edge_count];
+  EDGE_list.reset();
+  for( i=0; i<edge_count; i++ )
+    EDGEs[i] = EDGE_list.get_and_step();
+
+  BODY* wire_BODY = NULL;
+  result = api_make_ewire(edge_count, EDGEs, wire_BODY) ;
+  delete [] EDGEs;
+  if ( !result.ok() || wire_BODY == NULL )
+  {
+    AcisQueryEngine::instance()->ACIS_API_error( result );
+    if (wire_BODY)
+      api_delent(wire_BODY);
+    else
+    {
+      for( j=0; j<EDGE_list.size(); j++ )
+      {
+        EDGE_ptr = EDGE_list.get_and_step();
+        api_delent( EDGE_ptr );
+      }
+    }
+    return CUBIT_FAILURE;
+  }
+  
+    // Check to make sure the wire is closed
+  result = api_closed_wire( wire_BODY );
+  if( !result.ok() )
+  {
+    AcisQueryEngine::instance()->ACIS_API_error( result );
+    PRINT_ERROR( "ACIS reports that a closed loop was not found\n" );
+    api_delent( wire_BODY ); // This deletes the underlying EDGEs
+    return CUBIT_FAILURE;   
+  }
+  
+    // Use the WIRE to make a FACE.
+    // Note that the call to api_cover_wires creates not
+    // only the FACE but the entire topological data
+    // structure above FACE (till BODY).
+  ENTITY_LIST acis_FACE_list;
+  result = api_cover_wires ( wire_BODY,
+                             *(surface*)NULL_REF,
+                             acis_FACE_list );
+  
+  if ( !result.ok() || acis_FACE_list.count() == 0 )
+  {
+    AcisQueryEngine::instance()->ACIS_API_error( result );
+    wire_BODY->lose();
+    for (int i=0; i<edge_count; i++)
+      EDGE_list.get_and_step()->lose();
+    return CUBIT_FAILURE;
+  }
+
+  if (acis_FACE_list.count() != 1)
+  {
+    PRINT_ERROR("ACIS api_cover_wires function created more than one FACE.\n"
+                "       At this time, we cannot deal with this.\n");
+    wire_BODY->lose();
+    for (int i=0; i<edge_count; i++)
+      EDGE_list.get_and_step()->lose();
+    return CUBIT_FAILURE;
+  }
+  
+    //make this a 2d body.
+  result = api_body_to_2d( wire_BODY );
+  if ( !result.ok() )
+  {
+    AcisQueryEngine::instance()->ACIS_API_error( result );
+    PRINT_ERROR("ACIS api_body_to_2d function failed.\n");
+    wire_BODY->lose();
+    for (int i=0; i<edge_count; i++)
+      EDGE_list.get_and_step()->lose();
+    return CUBIT_FAILURE;
+  }
+  FACE *FACE_ptr = (FACE*) acis_FACE_list.next();
+  if ( FACE_ptr == NULL || FACE_ptr->geometry() == NULL )
+  {
+    PRINT_ERROR("a surface could not be constructed from the resultant polygon.\n");
+    wire_BODY->lose();
+    for (int i=0; i<edge_count; i++)
+      EDGE_list.get_and_step()->lose();
+    return CUBIT_FAILURE;
+  }
+
+  Surface *new_surface_ptr = AcisQueryEngine::instance()->populate_topology_bridges( FACE_ptr );
+  new_body = AcisModifyEngine::instance()->make_BodySM( new_surface_ptr );
+ 
+  return CUBIT_SUCCESS;
+}
 static SPAtransf const &get_edge_trans(EDGE *edge)
 {
 	// Find the body
@@ -1642,6 +1778,12 @@
     PRINT_ERROR("Invalid ACIS Surface -- aborting.\n");
     return CUBIT_FAILURE;
   }
+
+  if(!FACE_ptr1->loop() || !FACE_ptr2->loop())
+  {
+    PRINT_ERROR("Surfaces must have at least one loop for lofting -- aborting.\n");
+    return CUBIT_FAILURE;
+  }
   
   api_copy_entity_contents( (ENTITY *)FACE_ptr1, ENTITY_ptr);
   FACE_ptr1 = (FACE *)ENTITY_ptr;
@@ -1662,15 +1804,15 @@
   //CubitBoolean solid = perpendicular;
   
    result = api_loft_faces(FACE_ptr1, 
-								takeoff1, 
-								FACE_ptr2, 
-								takeoff2, 
-								loft_body, 
-								arc_length_option, 
-								twist_option, 
-								align_direction,  
-								perpendicular,
-								simplify_option);
+                           takeoff1, 
+                           FACE_ptr2, 
+                           takeoff2, 
+                           loft_body, 
+                           arc_length_option, 
+                           twist_option, 
+                           align_direction,  
+                           perpendicular,
+                           simplify_option);
   
   if( !result.ok() )
   {
@@ -1855,14 +1997,17 @@
 
 CubitStatus
 AcisSurfaceTool::create_skin_surface( DLIList<RefEdge*>& ref_edge_list,
-                                     Body*& new_body )
+                                     Body*& new_body,
+                                     DLIList<RefEdge*>& guide_list)
 {
   CubitStatus result;
   BodySM* this_bodysm;
   DLIList<Curve*> curve_list(ref_edge_list.size());
+  DLIList<Curve*> guide_curve_list(guide_list.size());
   
   new_body = 0;
   
+  // get ACIS curves from ref_edge_list
   ref_edge_list.reset();
   for (int i = ref_edge_list.size(); i--; )
   {
@@ -1877,8 +2022,22 @@
   if (curve_list.size() != ref_edge_list.size())
     return CUBIT_FAILURE;
 
+  // get ACIS curves from guide_list
+  guide_list.reset();
+  for (int i = guide_list.size(); i--; )
+  {
+    RefEdge* edge = guide_list.get_and_step();
+    CurveACIS* curve = get_acis_curve(edge);
+    if (!curve)
+      PRINT_ERROR("Curve %d is not an ACIS Curve.\n", edge->id());
+    else
+      guide_curve_list.append(curve);
+  }
+  if (guide_curve_list.size() != guide_list.size())
+    return CUBIT_FAILURE;
 
-  result = create_skin_surface( curve_list, this_bodysm );
+
+  result = create_skin_surface( curve_list, this_bodysm, guide_curve_list );
   if (!result)
     return result;
   

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisSurfaceTool.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -10,6 +10,7 @@
 class EDGE;
 template <class X> class DLIList;
 
+class Point;
 class Curve;
 class Surface;
 class BodySM;
@@ -87,8 +88,10 @@
                                   double offset_distance );
   //- Creates a new body by offsetting from another body
 
-  CubitStatus create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body );
-  CubitStatus create_skin_surface( DLIList<RefEdge*>& curves, Body*& new_body );
+  CubitStatus create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body,
+                                   DLIList<Curve*>& guides);
+  CubitStatus create_skin_surface( DLIList<RefEdge*>& curves, Body*& new_body,
+                                   DLIList<RefEdge*>& guides);
   //- Skinning puts a surface through a set of curves that are somewhat
   //- parallel to each other.
 
@@ -132,11 +135,15 @@
   CubitStatus create_surface( DLIList<CubitVector*>& vec_list,
                               BodySM *&new_body,
                               Surface *surface_ptr, 
-			                        CubitBoolean project_points );
+			      CubitBoolean project_points );
+
+  CubitStatus create_surface( DLIList<Point*> &vec_list,
+                              BodySM *&new_body );
+
   CubitStatus create_surface( DLIList<CubitVector*>& vec_list,
                               Body *&new_body,
                               RefFace *ref_face_ptr, 
-			                        CubitBoolean project_points );
+			      CubitBoolean project_points );
   //- Creates a surface out of a list of points.  The points must form
   //- a polygon (there must be at least 3 points), but do not need to be 
   //- absolutely planar.  The resultant surface will have one loop with

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -14,7 +14,9 @@
 
 #include "DLIList.hpp"
 
+#include "CubitUtil.hpp"
 #include "AcisToolUtil.hpp"
+#include "AcisToolUtil.hpp"
 #include "AcisQueryEngine.hpp"
 #include "AcisModifyEngine.hpp"
 #include "GeometryQueryTool.hpp"
@@ -23,11 +25,17 @@
 #include "Body.hpp"
 #include "RefFace.hpp"
 #include "RefEdge.hpp"
+#include "RefVertex.hpp"
+#include "CoEdge.hpp"
+#include "Loop.hpp"
+#include "Shell.hpp"
 
+
 #include "BodyACIS.hpp"
 #include "SurfaceACIS.hpp"
 #include "CurveACIS.hpp"
 #include "attrib_cubit_owner.hpp"
+#include "err_ent.hxx"
 
 Body* AcisToolUtil::get_new_Body( Body* old_body, BODY* old_BODY,
                                   BODY* new_BODY, bool keep_old,
@@ -197,5 +205,182 @@
   return dynamic_cast<Body*>(ent_ptr);
 }
 
+void AcisToolUtil::convert_entity_list( insanity_list *ent_list,
+                                    DLIList<TopologyEntity*> &topo_entity_list)
+{
+  if( ent_list->count() )
+  {
+    insanity_list *tmp_list = ent_list;
+    for(; tmp_list; tmp_list = tmp_list->next() )
+    {
+      insanity_data *error_data = tmp_list->data();
+      ENTITY *bad_ent = error_data->get_ent();
+      ENTITY_LIST bad_ents;
+      if(bad_ent->identity() == ERROR_ENTITY_TYPE )
+      {
+        ERROR_ENTITY *error_ent = (ERROR_ENTITY*)bad_ent;
+        bad_ents.add( error_ent->get_owner(0) ); 
+        bad_ents.add( error_ent->get_owner(1) ); 
+      }
+      else
+        bad_ents.add( bad_ent );
+      
+      bad_ents.init();
 
+      PRINT_INFO("%s: ", error_data->get_message() );
 
+      while( (bad_ent = bad_ents.next()) != NULL )
+      {
+        TopologyEntity* te_ptr = NULL;
+        te_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity( bad_ent );
+        if( te_ptr )
+        {
+          RefEntity *ref_ent = CAST_TO( te_ptr, RefEntity );
+          topo_entity_list.append_unique(te_ptr);
+          if( ref_ent )
+            PRINT_INFO(" %s %d", ref_ent->class_name(), ref_ent->id() );
+        }
+        else
+          PRINT_INFO("%s",bad_ent->type_name() );
+      }
+      PRINT_INFO("\n");
+    }
+  }
+}
+ 
+CubitStatus AcisToolUtil::show_bad_geom(DLIList <TopologyEntity*> &ent_list,
+                                    const CubitString &user_name)
+{
+  DLIList<RefVertex*> vertex_list;
+  DLIList<RefEdge*> edge_list;
+  DLIList<RefEdge*> curve_coedge_list;
+  DLIList<CoEdge*> coedge_list;
+  DLIList<Loop*> loop_list;
+  DLIList<RefFace*> face_list;
+  DLIList<Shell*> shell_list;
+  DLIList<RefVolume*> volume_list;
+  int i;
+
+  // We need an encapsulated class to handle this sort of thing...
+  for (i=0;i<ent_list.size();i++)
+  {
+    TopologyEntity* TE_ptr = ent_list.get_and_step();
+    RefVertex* ref_vertex;
+    RefEdge* ref_edge;
+    CoEdge* co_edge;
+    Loop* loop;
+    RefFace* face;
+    Shell* shell;
+    RefVolume* volume;
+
+    if( (ref_vertex = CAST_TO( TE_ptr, RefVertex ) ) != NULL )
+      vertex_list.append_unique(ref_vertex);
+    else if( (ref_edge = CAST_TO( TE_ptr, RefEdge ) ) != NULL )
+      edge_list.append_unique(ref_edge);
+    else if( (co_edge = CAST_TO( TE_ptr, CoEdge ) ) != NULL )
+      coedge_list.append_unique(co_edge);
+    else if( (loop = CAST_TO( TE_ptr, Loop ) ) != NULL )
+      loop_list.append_unique(loop);
+    else if( (face = CAST_TO( TE_ptr, RefFace ) ) != NULL )
+      face_list.append_unique(face);
+    else if( (shell = CAST_TO( TE_ptr, Shell ) ) != NULL )
+      shell_list.append_unique(shell);
+    else if( (volume = CAST_TO( TE_ptr, RefVolume ) ) != NULL )
+      volume_list.append_unique(volume);        
+  }
+
+  char *pre = new char[user_name.length()+100];  
+
+  if( vertex_list.size() )
+  {
+    sprintf( pre, "Found %d bad vertices in %s. The vertices: ", vertex_list.size(),
+      user_name.c_str() );
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( vertex_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  if( edge_list.size() )
+  {
+    sprintf( pre, "Found %d bad curves in %s. The curves: ", edge_list.size(), 
+      user_name.c_str() );    
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( edge_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  for( i=0; i<coedge_list.size(); i++ )
+  {
+    RefEdge* ref_edge_ptr = coedge_list.get_and_step()->get_ref_edge_ptr();
+    curve_coedge_list.append_unique( ref_edge_ptr );
+  }
+  if( coedge_list.size() )
+  {
+    sprintf( pre, "Found %d bad coedges in %s. The curves: ", coedge_list.size(), 
+      user_name.c_str() );
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( curve_coedge_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  // LOOPS
+  Loop* loop_ptr;
+  DLIList<RefEdge*> curve_loop_list;
+  for( i=0; i<curve_loop_list.size(); i++ )
+  {
+    loop_ptr = loop_list.get_and_step();
+    DLIList<RefEdge*> tmp_curve_list;
+    loop_ptr->ordered_ref_edges( tmp_curve_list );
+    curve_loop_list.merge_unique( tmp_curve_list );
+  }
+  curve_loop_list.reset();
+  if( curve_loop_list.size() )
+  {
+    sprintf( pre, "Found %d bad loops in %s. The curves: ", loop_list.size(), user_name.c_str() );
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( curve_loop_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  // SURFACES
+  if( face_list.size() )
+  {
+    sprintf( pre, "Found %d bad surfaces in %s. The surfaces: ", face_list.size(), user_name.c_str() );
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( face_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  // SHELLS
+  Shell* shell_ptr;
+  DLIList<RefFace*> face_shell_list;
+  for( i=0; i<shell_list.size(); i++ )
+  {
+    shell_ptr = shell_list.get_and_step();
+    DLIList<RefFace*> tmp_surface_list;
+    shell_ptr->ref_faces( tmp_surface_list );
+    face_shell_list.merge_unique( tmp_surface_list );
+  }
+  if( face_shell_list.size() )
+  {
+    sprintf( pre, "Found %d bad shells in %s. The surfaces: ", shell_list.size(), user_name.c_str() );
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( face_shell_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  // LUMPS  
+  if( volume_list.size() )
+  {    
+    sprintf( pre, "Found %d bad volumes in %s. The volumes: ", volume_list.size(), user_name.c_str() );
+    DLIList<CubitEntity*> cubit_list;
+    CAST_LIST( volume_list, cubit_list, CubitEntity );
+    CubitUtil::list_entity_ids( pre, cubit_list );
+  }
+
+  delete [] pre;
+  
+  return CUBIT_SUCCESS;
+}
+
+

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisToolUtil.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -18,11 +18,14 @@
 
 #include "CubitDefines.h"  /* for CubitStatus */
 
+#include "insanity_list.hxx"
+
 template <class X> class DLIList;
 
 class Body;
 class RefEdge;
 class RefFace;
+class TopologyEntity;
 
 class ENTITY;
 class BODY;
@@ -71,6 +74,15 @@
     
     static Body* get_body_of_ENTITY(ENTITY*);
 
+    static void convert_entity_list( insanity_list *ent_list,
+                              DLIList<TopologyEntity*> &topology_entities);
+      // Given the acis entities, gets the corrisponding topology entities in
+      // cubit by which they are represented.
+
+    static CubitStatus show_bad_geom( DLIList<TopologyEntity*> &ent_list, 
+                                      const CubitString &user_name);
+    // This was put in only to display bad geometry from a validate.  Needs to 
+    // be encapsulated in another class...
 };
 
 #endif

Copied: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.cpp (from rev 3491, cgm/branches/cubit/geom/ACIS_SRC/AcisTopologyTool.cpp)
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.cpp	                        (rev 0)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -0,0 +1,4330 @@
+//- Class: AcisTopologyTool
+//- File: AcisTopologyTool.cpp
+//- Type: class implemention
+//- Owner: Brett Clark
+
+// Include files
+
+#include "AcisTopologyTool.hpp" 
+#include "CubitVector.hpp" 
+#include "CubitPlane.hpp" 
+#include "AcisDrawTool.hpp"
+#include "GeometryDefines.h"
+#include "AcisModifyEngine.hpp"
+#include "AcisHealerTool.hpp"
+#include "GeomMeasureTool.hpp"
+#include "attrib_cubit_owner.hpp"
+#include "attrib_snl_simple.hpp"
+#include "CubitString.hpp"
+#include "CubitSimpleAttrib.hpp"
+#include "TopologyBridge.hpp"
+#include "GfxDebug.hpp"
+
+#include "vertex.hxx"
+#include "point.hxx"
+#include "vector.hxx"
+#include "edge.hxx"
+#include "face.hxx"
+#include "lists.hxx"
+#include "unitvec.hxx"
+#include "surface.hxx"
+#include "surdef.hxx"
+#include "curve.hxx"
+#include "curdef.hxx"
+#include "strdef.hxx"
+#include "straight.hxx"
+#include "param.hxx"
+#include "position.hxx"
+#include "interval.hxx"
+#include "cstrapi.hxx"
+#include "esplit.hxx"
+#include "coedge.hxx"
+#include "intrapi.hxx"
+#include "pladef.hxx"
+#include "acistype.hxx"
+#include "body.hxx"
+#include "lump.hxx"
+#include "shell.hxx"
+#include "eulerapi.hxx"
+#include "stchapi.hxx"
+#include "boolapi.hxx"
+#include "err_ent.hxx"
+
+static double pi_over_two = CUBIT_PI/2.0;
+static double pi_over_four = pi_over_two/2.0;
+static double three_pi_over_two = 3.0*pi_over_two;
+static double three_pi_over_four = three_pi_over_two/2.0;
+static double five_pi_over_four = 5.0*pi_over_four;
+static double seven_pi_over_four = 7.0*pi_over_four;
+
+void f(RefFace* face, int color);
+void e(RefEdge* edge, int color);
+void v(RefVertex* vert, int color);
+void p(CubitVector* v, int color);
+void en(ENTITY* ent, int color);
+void pos(SPAposition* p, int color);
+
+void F(FACE* face, int color)
+{
+  AcisDrawTool::instance()->draw_FACE(face, color, CUBIT_FALSE, CUBIT_TRUE);
+  ENTITY_LIST verts;
+  api_get_vertices((ENTITY*)face, verts);
+  verts.init();
+  ENTITY *tmp_ent;
+  while((tmp_ent = verts.next()))
+    AcisDrawTool::instance()->draw_VERTEX((VERTEX*)tmp_ent, color, CUBIT_TRUE);
+}
+
+void E(EDGE* edge, int color)
+{
+  AcisDrawTool::instance()->draw_EDGE(edge, color, CUBIT_TRUE);
+  ENTITY_LIST verts;
+  api_get_vertices((ENTITY*)edge, verts);
+  verts.init();
+  ENTITY *tmp_ent;
+  while((tmp_ent = verts.next()))
+    AcisDrawTool::instance()->draw_VERTEX((VERTEX*)tmp_ent, color, CUBIT_TRUE);
+}
+
+void V(VERTEX* vert, int color)
+{
+  AcisDrawTool::instance()->draw_VERTEX(vert, color, CUBIT_TRUE);
+}
+
+void En(ENTITY* e, int color)
+{
+  AcisDrawTool::instance()->draw_ENTITY(e, color, CUBIT_FALSE, CUBIT_TRUE);
+  ENTITY_LIST verts;
+  api_get_vertices(e, verts);
+  verts.init();
+  ENTITY *tmp_ent;
+  while((tmp_ent = verts.next()))
+    AcisDrawTool::instance()->draw_VERTEX((VERTEX*)tmp_ent, color, CUBIT_TRUE);
+}
+
+void Clear()
+{
+  GfxDebug::clear();
+  GfxDebug::flush();
+}
+
+CubitStatus AcisTopologyTool::remove_topology(BODY *&body,
+                                              DLIList<EDGE*> &edges_to_remove,
+                                              DLIList<FACE*> &faces_to_remove,
+                                              double backoff_distance,
+                                              double small_edge_size)
+{
+  double tol_sq = GEOMETRY_RESABS*GEOMETRY_RESABS;
+  int i;
+  CubitStatus status = CUBIT_SUCCESS;
+  DLIList<VERTEXClump*> clumps;
+  DLIList<VERTEX*> all_verts_in_clumps;
+  DLIList<FACE*> faces_that_might_move, new_vol_faces, modified_faces;
+  DLIList<SPAposition> clump_positions, split_positions, projected_positions;
+  std::map <VERTEX*, VERTEXClump*, mapltid> old_vertex_to_clump_map;
+  std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> surrounding_faces_map;
+  std::map <FACE*, int, mapltid> face_clump_count_map;
+  std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> faces_that_dont_intersect_map;
+  std::map <EDGE*, EDGE*, mapltid> old_edge_to_new_edge_map;
+
+  // Put an attribute on all of the ACIS curves and verts to
+  // track what has been destroyed during the operation.  Entities
+  // that still have the att after the operation will be considered
+  // unmodified.
+  ENTITY_LIST edges_and_verts, tmp_list;
+  api_get_edges((ENTITY*)body, edges_and_verts);
+  api_get_vertices((ENTITY*)body, tmp_list);
+  edges_and_verts.add(tmp_list);
+  ENTITY *tmp_ent;
+  edges_and_verts.init();
+  while((tmp_ent = edges_and_verts.next()))
+    add_named_att(tmp_ent, "UNMODIFIED");
+
+  // This will group points that are close together into clumps and will
+  // build a map from the points to the clump they are in.
+  if(!setup_clump_map(edges_to_remove, faces_to_remove, small_edge_size,
+        clumps, old_vertex_to_clump_map))
+  {
+    status = CUBIT_FAILURE;
+  }
+  // Create a global list of all of the pts that are in clumps.
+  else if(!get_all_verts_in_clumps(clumps, all_verts_in_clumps))
+  {
+    status = CUBIT_FAILURE;
+  }
+  // Build a map from a clump to the faces surrounding it.
+  else if(!find_faces_surrounding_clumps(clumps, surrounding_faces_map, 
+        all_verts_in_clumps, old_vertex_to_clump_map, faces_to_remove))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!find_face_clump_counts(surrounding_faces_map, face_clump_count_map))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!find_faces_that_dont_intersect(surrounding_faces_map, 
+      faces_that_dont_intersect_map, small_edge_size))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!ensure_possible_solution(faces_that_dont_intersect_map, faces_that_might_move))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!choose_best_face_to_move(faces_that_might_move, 
+    face_clump_count_map, all_verts_in_clumps))
+  {
+    status = CUBIT_FAILURE;
+  }
+//  else if(!find_new_pos_for_clump(surrounding_faces_map, faces_that_might_move, small_edge_size))
+//  {
+//    status = CUBIT_FAILURE;
+//  }
+  else if(!build_clump_topology(clumps))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!find_new_edges_between_clumps(clumps, old_edge_to_new_edge_map, surrounding_faces_map))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!adjust_backoff_distance(clumps, old_vertex_to_clump_map,
+                 old_edge_to_new_edge_map, backoff_distance))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else if(!split_all_curves_coming_into_clumps(clumps, old_vertex_to_clump_map,
+                 old_edge_to_new_edge_map, backoff_distance, split_positions))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else
+  {
+    int display_clumps = 0;
+    if(display_clumps)
+    {
+      std::map <VERTEXClump*,DLIList<FACE*>*, mapltclump>::iterator iter;
+      for(iter=surrounding_faces_map.begin(); iter != surrounding_faces_map.end(); iter++ )
+      {
+        DLIList<FACE*> *face_list = iter->second;
+        for(i=face_list->size(); i--;)
+        {
+          FACE *cur_face = face_list->get_and_step();
+          F(cur_face, 8);
+        }
+      }
+      for(i=clumps.size(); i--;)
+      {
+        VERTEXClump *vc = clumps.get_and_step();
+        V(vc->new_vert, 4);
+      }
+    }
+  }
+
+  if(status == CUBIT_FAILURE ||
+       !generate_faces_for_surrounding_faces(surrounding_faces_map, old_edge_to_new_edge_map,
+       old_vertex_to_clump_map, new_vol_faces, modified_faces, backoff_distance, faces_to_remove,
+       projected_positions))
+  {
+    status = CUBIT_FAILURE;
+  }
+  else
+  {
+    for(i=faces_to_remove.size(); i--;)
+      api_remove_face(faces_to_remove.get_and_step());
+
+    for(i=clumps.size(); i--;)
+    {
+      VERTEXClump *vc = clumps.get_and_step();
+      clump_positions.append(vc->new_vert->geometry()->coords());
+    }
+
+    if(!combine_old_body_and_new_faces(body, new_vol_faces))
+      status = CUBIT_FAILURE;
+  }
+
+  int cleanup = 1;
+  if(status == CUBIT_SUCCESS && cleanup)
+  {
+    // Get a list of the edges and verts that were
+    // not modified.
+    DLIList<ENTITY*> unmodified_ents, new_ents;
+    edges_and_verts.clear();
+    tmp_list.clear();
+    api_get_edges((ENTITY*)body, edges_and_verts);
+    api_get_vertices((ENTITY*)body, tmp_list);
+    edges_and_verts.add(tmp_list);
+    ENTITY *tmp_ent;
+    edges_and_verts.init();
+    while((tmp_ent = edges_and_verts.next()))
+    {
+      ATTRIB_SNL_SIMPLE *att = find_named_att(tmp_ent, "UNMODIFIED");
+      if(att)
+      {
+        remove_att(tmp_ent, att);
+        unmodified_ents.append(tmp_ent);
+      }
+      else
+        new_ents.append(tmp_ent);
+    }
+
+    // Classify all of the new verts as either a clump, split,
+    // or projected vert.
+    int j;
+    DLIList<VERTEX*> clump_verts, split_verts, projected_verts;
+    DLIList<ENTITY*> vert_ents;
+    for(i=new_ents.size(); i--;)
+    {
+      ENTITY *ent = new_ents.get_and_step();
+      if(is_VERTEX(ent))
+      {
+        vert_ents.append(ent);
+        SPAposition vert_pos = ((VERTEX*)ent)->geometry()->coords();
+        int found = 0;
+        for(j=clump_positions.size(); j>0 && !found; j--)
+        {
+          SPAposition cur_pos = clump_positions.get();
+          if((cur_pos - vert_pos).len_sq() < tol_sq)
+          {
+            found = 1;
+            clump_verts.append_unique((VERTEX*)ent);
+            clump_positions.extract();
+          }
+          else
+            clump_positions.step();
+        }
+        for(j=split_positions.size(); j>0 && !found; j--)
+        {
+          SPAposition cur_pos = split_positions.get();
+          if((cur_pos - vert_pos).len_sq() < tol_sq)
+          {
+            found = 1;
+            split_verts.append_unique((VERTEX*)ent);
+            split_positions.extract();
+          }
+          else
+            split_positions.step();
+        }
+        for(j=projected_positions.size(); j>0 && !found; j--)
+        {
+          SPAposition cur_pos = projected_positions.get();
+          if((cur_pos - vert_pos).len_sq() < tol_sq)
+          {
+            found = 1;
+            projected_verts.append_unique((VERTEX*)ent);
+            projected_positions.extract();
+          }
+          else
+            projected_positions.step();
+        }
+      }
+    }
+
+    // Remove all of the vertices from the list so that we
+    // just have edges.
+    new_ents -= vert_ents;
+
+    // Look at each new edge and try to regularize or composite it
+    // out if appropriate.
+    ENTITY_LIST cur_body_edges;
+    api_get_edges((ENTITY*)body, cur_body_edges);
+    for(i=new_ents.size(); i--;)
+    {
+      EDGE *edge = (EDGE*)new_ents.get_and_step();
+      if(cur_body_edges.lookup((ENTITY*)edge) != -1)
+      {
+        int try_to_remove = 0;
+        // "REMOVE_EDGE" attributes were placed on edges that we want to
+        // try to regularize/composite out.
+        ATTRIB_SNL_SIMPLE *att = find_named_att((ENTITY*)edge, "REMOVE_EDGE");
+        if(att)
+        {
+          remove_att((ENTITY*)edge, att);
+          try_to_remove = 1;
+        }
+        if(try_to_remove)
+        {
+          int failed;
+          ENTITY_LIST edges_after;
+          API_TRIAL_BEGIN;
+          api_clean_entity((ENTITY*)edge);
+          api_get_edges((ENTITY*)body, edges_after);
+          failed = (cur_body_edges.count() == edges_after.count());
+          if(failed)
+            sys_error(12345);
+          API_TRIAL_END;
+          cur_body_edges = edges_after;
+          if(failed)
+          {
+            ATTRIB_SNL_SIMPLE *att = find_named_att((ENTITY*)edge, "COMPOSITE_GEOM");
+            if(!att)
+              add_named_att((ENTITY*)edge, "COMPOSITE_GEOM");
+          }
+        }
+      }
+    }
+
+    // Look at each new vertex (that is still in the model) and composite
+    // it out if appropriate.
+    ENTITY_LIST cur_body_verts;
+    api_get_vertices((ENTITY*)body, cur_body_verts);
+    for(i=vert_ents.size(); i--;)
+    {
+      VERTEX *vert = (VERTEX*)vert_ents.get_and_step();
+      if(cur_body_verts.lookup((ENTITY*)vert) != -1)
+      {
+        int try_to_remove = 0;
+        if(!clump_verts.is_in_list(vert))
+        {
+          ENTITY_LIST vert_edges;
+          api_get_edges((ENTITY*)vert, vert_edges);
+          int num_edges = vert_edges.count();
+          ENTITY *tmp_ent;
+          vert_edges.init();
+          while((tmp_ent = vert_edges.next()))
+          {
+            if(find_named_att(tmp_ent, "COMPOSITE_GEOM"))
+              num_edges--;
+          }
+          if(num_edges == 2)
+            try_to_remove = 1;
+        }
+
+        if(try_to_remove)
+        {
+          if(!find_named_att((ENTITY*)vert, "COMPOSITE_GEOM"))
+            add_named_att((ENTITY*)vert, "COMPOSITE_GEOM");
+        }
+      }
+    }
+  }
+
+  return status;
+}
+
+ATTRIB_SNL_SIMPLE* AcisTopologyTool::find_named_att(ENTITY* ent, const char *name)
+{
+  ATTRIB_SNL_SIMPLE *ret_attrib = NULL;
+  ATTRIB_SNL_SIMPLE *attribute =
+    (ATTRIB_SNL_SIMPLE *) find_attrib(ent, 
+                                      ATTRIB_SNL_TYPE,
+                                      ATTRIB_SNL_SIMPLE_TYPE);
+  for(;attribute != NULL && !ret_attrib;attribute = (ATTRIB_SNL_SIMPLE *)
+        find_next_attrib(attribute,
+                        ATTRIB_SNL_TYPE,
+                        ATTRIB_SNL_SIMPLE_TYPE))
+  {
+    if( attribute->attribute_name() == name )
+      ret_attrib = attribute;
+  }
+  return ret_attrib;
+}
+
+void AcisTopologyTool::add_named_att(ENTITY* ent, const char *name_in)
+{
+  CubitString name(name_in);
+  DLIList<CubitString*> string_list;
+  string_list.append(&name);
+  CubitSimpleAttrib attrib(&string_list, 0, 0);
+  API_BEGIN;
+  new ATTRIB_SNL_SIMPLE(ent, &attrib);
+  API_END;
+}
+
+void AcisTopologyTool::remove_att(ENTITY* ent, ATTRIB_SNL_SIMPLE *att)
+{
+  API_BEGIN;
+  att->unhook();
+  API_END;
+}
+
+CubitStatus AcisTopologyTool::combine_old_body_and_new_faces(BODY *&b, DLIList<FACE*> &new_faces)
+{
+  int i, heal = 0;
+  ENTITY_LIST BODY_list;
+  for(i=new_faces.size(); i--;)
+  {
+    FACE *cur_face = new_faces.get_and_step();
+    ENTITY *owner;
+    api_get_owner((ENTITY*)cur_face, owner);
+    if(!owner || !is_BODY(owner))
+    {
+      FACE *face_list[1];
+      BODY *sheet_body;
+      face_list[0] = cur_face;
+      outcome rc = api_sheet_from_ff(1, face_list, sheet_body);
+      if (!rc.ok())
+        PRINT_ERROR("Couldn't build a BODY with FACE.\n") ;
+      rc = api_body_to_2d(sheet_body);
+      if (!rc.ok())
+        PRINT_ERROR("Couldn't build a volume with Surface.\n" );
+      // Make sure we were successful
+      if ( sheet_body->lump() == NULL ||
+          sheet_body->lump()->shell() == NULL ||
+          sheet_body->lump()->shell()->first_face() == NULL )
+      {
+        PRINT_ERROR("Couldn't build a volume with Surface.\n" );
+      }
+      BODY_list.add(sheet_body);
+    }
+    else
+      BODY_list.add((BODY*)owner);
+  }
+  api_body_to_2d(b);
+  BODY_list.add(b);
+
+  BODY* result_BODY = NULL;
+  if( !heal )
+  {
+    ENTITY_LIST dummy_list, resultant_bodies;
+ //   exact_stitch_options stitch_opts;
+    tolerant_stitch_options stitch_opts;
+    //surfaces better be between GEOMETRY_RESABS or else fail
+    stitch_opts.set_max_stitch_tol( GEOMETRY_RESABS );
+    outcome result = api_stitch( BODY_list, dummy_list, resultant_bodies, &stitch_opts );
+
+    result_BODY = (BODY*)dummy_list.first();
+
+    int is_closed = 1;
+    if(result.ok() && result_BODY)
+      is_closed = is_closed_solid_body(result_BODY);
+
+    if(!is_closed)
+      PRINT_ERROR("Failed to make a closed body after removing the specified topology.\n"
+      "Possible remedies:\n"
+      " Check that input parameters are reasonable values for topology being removed and surrounding topology.\n"
+      " Check if narrow surfaces need to be split into simple 4-sided surfaces (see 'auto_clean split_narrow_regions' command).\n");
+
+    if (!result.ok() || (!result_BODY ) || !is_closed)
+    {
+      // If there are no LUMPs in the resulting BODY, return with a failure
+      if (result_BODY == NULL)
+        PRINT_ERROR("In AcisModifyEngine::create_solid_bodies_from_surfs\n");
+
+      if (result_BODY != NULL) 
+      {
+        AcisQueryEngine::instance()->delete_ACIS_BODY(result_BODY);
+        b = NULL;
+        result_BODY = NULL;
+      }
+
+      return CUBIT_FAILURE;
+    }
+  }
+  /*
+    // If all went well, delete the old Bodies
+  DLIList<TopologyBridge*> old_entities;
+  body_list.reset() ;
+
+  CAST_LIST_TO_PARENT(body_list, old_entities);
+
+  for ( ii = free_faces.size(); ii > 0; ii-- )
+    old_entities.append(free_faces.get_and_step());
+    */
+
+
+#ifdef ACIS_HEALER
+//  BODY *new_master = master;
+  if ( heal )
+  {
+#if 0
+      // Now heal the combined body
+    PRINT_INFO(" Healing the combined volume...\n");
+    if( AcisHealerTool::instance()->init_BODY_for_healing( master ) == CUBIT_SUCCESS )
+    {
+      int percent_before, percent_after, number_splines_simplified;
+      if( AcisHealerTool::instance()->heal_BODY( master, percent_before,
+                                                 percent_after, number_splines_simplified ) == CUBIT_FAILURE )
+        PRINT_ERROR( "Error healing the combined volume\n" );
+      else
+        PRINT_INFO( "Healed the combined volume to %d%% good geometry.\n", percent_after );
+      AcisHealerTool::instance()->end_BODY_for_healing( master );
+    }
+#endif
+  }
+#else
+  PRINT_WARNING("Healer was not included with this version.\n"
+                " Volume healing is usually required for creating\n"
+                " volumes out of surfaces.\n");
+#endif
+
+  if(result_BODY)
+    b = result_BODY;
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::build_clump_topology(DLIList<VERTEXClump*> &clumps)
+{
+  int i;
+
+  for(i=clumps.size(); i--;)
+  {
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    APOINT *p1 = new APOINT(cur_clump->ave_pos);
+    cur_clump->new_vert = new VERTEX(p1);
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::generate_faces_for_surrounding_faces(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                                                        std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                                        std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                                        DLIList<FACE*> &new_vol_faces,
+                                                        DLIList<FACE*> &modified_faces,
+                                                        double &backoff_distance,
+                                                        DLIList<FACE*> &dead_faces,
+                                                        DLIList<SPAposition> &projected_positions)
+{
+  CubitStatus ret = CUBIT_SUCCESS;
+  int i, debug_display = 0;
+  std::map <VERTEXClump*,DLIList<FACE*>*, mapltclump>::iterator iter;
+  DLIList<FACE*> processed_faces;
+  for(iter=surrounding_faces_map.begin(); iter != surrounding_faces_map.end() && ret == CUBIT_SUCCESS; iter++ )
+  {
+    DLIList<FACE*> *face_list = iter->second;
+    for(i=face_list->size(); i && ret == CUBIT_SUCCESS; i--)
+    {
+      FACE *cur_face = face_list->get_and_step();
+      if(debug_display)
+        F(cur_face, i%4+3);
+      if(!generate_faces_for_surrounding_face(cur_face, backoff_distance, old_vertex_to_clump_map, 
+                 old_edge_to_new_edge_map, processed_faces, modified_faces, new_vol_faces, dead_faces,
+                 projected_positions))
+      {
+        ret = CUBIT_FAILURE;
+      }
+    }
+  }
+  return ret;
+}
+
+int AcisTopologyTool::is_lateral_edge(EDGE *edge,
+                  std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map)
+{
+  int ret = 0;
+
+  if(old_edge_to_new_edge_map.count(edge))
+    ret = 1;
+
+  return ret;
+}
+
+CubitStatus AcisTopologyTool::generate_faces_for_surrounding_face(FACE *face,
+                                              double &backoff_distance, 
+                                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                              DLIList<FACE*> &processed_faces,
+                                              DLIList<FACE*> &modified_faces,
+                                              DLIList<FACE*> &new_vol_faces,
+                                              DLIList<FACE*> &dead_faces,
+                                              DLIList<SPAposition> &projected_positions)
+{
+  CubitStatus ret = CUBIT_SUCCESS;
+  DLIList<VERTEX*> processed_verts;
+  DLIList<EDGE*> processed_edges;
+  DLIList<EDGE*> edges_to_imprint;
+  if(!processed_faces.is_in_list(face))
+  {
+    processed_faces.append(face);
+    modified_faces.append(face);
+    ENTITY_LIST face_edges;
+    api_get_edges((ENTITY*)face, face_edges);
+    ENTITY *tmp_ent;
+    face_edges.init();
+    while((tmp_ent = face_edges.next()) && ret == CUBIT_SUCCESS)
+    {
+      EDGE *cur_edge = (EDGE*)tmp_ent;
+      if(!processed_edges.is_in_list(cur_edge))
+      {
+        if(is_lateral_edge(cur_edge, old_edge_to_new_edge_map))
+        {
+          if(!generate_faces_for_lateral_edge(face, cur_edge, backoff_distance, 
+                       old_vertex_to_clump_map, old_edge_to_new_edge_map, processed_verts,
+                       processed_edges, edges_to_imprint, new_vol_faces, dead_faces,
+                       projected_positions))
+          {
+            ret = CUBIT_FAILURE;
+          }
+        }
+        else if(edge_within_clump(cur_edge, old_vertex_to_clump_map))
+        {
+        }
+        else
+        {
+          if(!generate_faces_for_non_lateral_edge(face, cur_edge, backoff_distance, 
+                       old_vertex_to_clump_map, old_edge_to_new_edge_map, processed_verts,
+                       processed_edges, edges_to_imprint, new_vol_faces, dead_faces,
+                       projected_positions))
+          {
+            ret = CUBIT_FAILURE;
+          }
+        }
+      }
+    }
+  }
+  return ret;
+}
+
+CubitStatus AcisTopologyTool::generate_faces_for_non_lateral_edge(FACE *&face, EDGE *edge,
+                                              double &backoff_distance, 
+                                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                              DLIList<VERTEX*> &processed_verts,
+                                              DLIList<EDGE*> &processed_edges,
+                                              DLIList<EDGE*> &edges_to_imprint,
+                                              DLIList<FACE*> &new_vol_faces,
+                                              DLIList<FACE*> &dead_faces,
+                                              DLIList<SPAposition> &projected_positions)
+{
+  CubitStatus ret = CUBIT_SUCCESS;
+  DLIList<VERTEX*> edge_verts;
+  SPAposition tmp_pos;
+  SPAunit_vector cur_dir, other_dir;
+  ENTITY *new_ent;
+
+  processed_edges.append(edge);
+
+  VERTEX *vert = NULL;
+  if(!processed_verts.is_in_list(edge->start()) && old_vertex_to_clump_map.count(edge->start()))
+    vert = edge->start();
+  else if(!processed_verts.is_in_list(edge->end()) && old_vertex_to_clump_map.count(edge->end()))
+    vert = edge->end();
+
+  if(vert)
+  {
+    VERTEX *clump_vert = old_vertex_to_clump_map[vert]->new_vert;
+    EDGE *next_edge;
+    VERTEX *next_vert;
+    get_next_edge_around_clump(edge, vert, face, 
+                  old_vertex_to_clump_map, next_edge, next_vert);
+    if(next_edge && next_vert)
+    {
+      double angle = this->angle_between(face, edge, vert, next_edge, next_vert);
+      if(is_lateral_edge(next_edge, old_edge_to_new_edge_map))
+      {
+        // If the next edge is a lateral edge this will get processed later.
+      }
+      else
+      {
+        SPAposition other_vert_pos = other_vertex(edge, vert)->geometry()->coords();
+        SPAposition next_other_pos = other_vertex(next_edge, next_vert)->geometry()->coords();
+        processed_verts.append(vert);
+        processed_verts.append(next_vert);
+        // Just create a triangular face.
+        if(angle < pi_over_four)
+        {
+          EDGE *new_edge1=NULL, *new_edge3=NULL, *new_edge4=NULL;
+          VERTEX *v1 = new_vert_from_pos(other_vert_pos);
+          VERTEX *v2 = new_vert_from_pos(next_other_pos);
+          new_edge1 = imprint_new_edge_on_face(face, v1, v2);
+          if(!new_edge1)
+            ret = CUBIT_FAILURE;
+          else
+          {
+            face = this->find_keep_face(new_edge1, vert, dead_faces);
+            add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+            api_copy_entity_contents((ENTITY*)new_edge1, new_ent);
+            new_edge1 = (EDGE*)new_ent;
+            v1 = new_vert_from_pos(other_vert_pos);
+            v2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+            STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+            new_edge3 = new EDGE(v1, v2, s, FORWARD);
+            v1 = new_vert_from_pos(next_other_pos);
+            v2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+            s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+            new_edge4 = new EDGE(v1, v2, s, FORWARD);
+            if(new_edge1 && new_edge3 && new_edge4)
+            {
+              // Now create the new face.
+              DLIList<EDGE*> edges_for_new_face;
+              edges_for_new_face.append(new_edge1);
+              edges_for_new_face.append(new_edge3);
+              edges_for_new_face.append(new_edge4);
+              FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+              if(FACE_ptr)
+                new_vol_faces.append(FACE_ptr);
+              else
+              {
+                PRINT_ERROR("Failed to build face from bounding curves.\n");
+                ret = CUBIT_FAILURE;
+              }
+            }
+            else
+            {
+              PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+              ret = CUBIT_FAILURE;
+            }
+          }
+        }
+        // We have two non-lateral edges coming into one or more vertices in a clump
+        // with no lateral edges in between them.  So, there will be no new faces
+        // associated with lateral edges but we need to create one or more faces
+        // depending on the angle between the two edges.
+        else if(angle <= three_pi_over_four)
+        {
+          // Just create one face between this edge and the next edge.
+          // This will require two new edges projected into the face
+          // from the two split points on the edges.
+          SPAposition new_pos1;
+          EDGE *new_edge1=NULL, *new_edge2=NULL, *new_edge3, *new_edge4;
+          tangent_indir(face, edge, vert->geometry()->coords(), cur_dir); 
+          tangent_indir(face, next_edge, next_vert->geometry()->coords(), other_dir); 
+          SPAvector ave_dir = cur_dir + other_dir;
+          SPAvector ave_dir_norm = normalise(ave_dir);
+          angle /= 2.0;
+          double distance = backoff_distance/sin(angle);
+          SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                              (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                              (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+          tmp_pos = mid_pos + distance * ave_dir_norm;
+          face->geometry()->equation().point_perp(tmp_pos, new_pos1);
+
+          // Now create an edge going from the new position to the split
+          // position on each of the edges.
+          VERTEX *v1 = new_vert_from_pos(new_pos1);
+          VERTEX *v2 = new_vert_from_pos(other_vert_pos);
+          new_edge1 = imprint_new_edge_on_face(face, v1, v2);
+          if(!new_edge1)
+            ret = CUBIT_FAILURE;
+          else
+          {
+            add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+            api_copy_entity_contents((ENTITY*)new_edge1, new_ent);
+            new_edge1 = (EDGE*)new_ent;
+            v1 = new_vert_from_pos(new_pos1);
+            v2 = new_vert_from_pos(next_other_pos);
+            new_edge2 = imprint_new_edge_on_face(face, v1, v2);
+            if(!new_edge2)
+              ret = CUBIT_FAILURE;
+            face = this->find_keep_face(new_edge2, vert, dead_faces);
+            if(!face)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge2, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge2, new_ent);
+              new_edge2 = (EDGE*)new_ent;
+              v1 = new_vert_from_pos(other_vert_pos);
+              v2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+              STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+              new_edge3 = new EDGE(v1, v2, s, FORWARD);
+              v1 = new_vert_from_pos(next_other_pos);
+              v2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+              s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+              new_edge4 = new EDGE(v1, v2, s, FORWARD);
+
+              if(new_edge1 && new_edge2 && new_edge3 && new_edge4)
+              {
+                // Now create the new face.
+                DLIList<EDGE*> edges_for_new_face;
+                edges_for_new_face.append(new_edge1);
+                edges_for_new_face.append(new_edge2);
+                edges_for_new_face.append(new_edge3);
+                edges_for_new_face.append(new_edge4);
+                FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                if(FACE_ptr)
+                {
+                  new_vol_faces.append(FACE_ptr);
+                  projected_positions.append(new_pos1);
+                }
+                else
+                {
+                  PRINT_ERROR("Failed to create face from bounding curves.\n");
+                  ret = CUBIT_FAILURE;
+                }
+              }
+              else
+              {
+                PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                ret = CUBIT_FAILURE;
+              }
+            }
+          }
+        }
+        else if(angle <= five_pi_over_four)
+        {
+          // Introduce two new faces between the two edges.
+          EDGE *new_edge1=NULL, *new_edge2=NULL, *new_edge3=NULL, *new_edge4=NULL, *new_edge5=NULL;
+          EDGE *new_edge6, *new_edge7, *new_edge8;
+          SPAposition new_pos1, new_pos2, new_pos3;
+          SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                              (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                              (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+
+          // Project from the current vert into the face at an average direction.
+          tangent_indir(face, edge, vert->geometry()->coords(), cur_dir); 
+          tangent_indir(face, next_edge, next_vert->geometry()->coords(), other_dir); 
+          SPAvector ave_dir = cur_dir + other_dir;
+          SPAvector ave_dir_norm = normalise(ave_dir);
+          angle /= 2.0;
+          double distance = backoff_distance/sin(angle);
+          tmp_pos = mid_pos + distance * ave_dir_norm;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+          int cntr = 0;
+          point_face_containment containment;
+          api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+          // Try to make sure we have a point on the face.
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (clump_vert->geometry()->coords()-new_pos1).len() / 2.0;
+            tmp_pos = mid_pos + distance * ave_dir_norm;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+            api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+          double dist2 = backoff_distance;
+          // Project from each split position into the face to get the
+          // other two new positions.
+          // Now that we have the location of the new position projected into
+          // the face we will create the first new edge.
+          tangent_indir(face, edge, other_vert_pos, cur_dir); 
+          tmp_pos = other_vert_pos + dist2*cur_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+
+          cntr = 0;
+          api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            dist2 = (other_vert_pos-new_pos2).len() / 2.0;
+            tmp_pos = other_vert_pos + dist2*cur_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+            api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          tangent_indir(face, next_edge, next_other_pos, other_dir); 
+          tmp_pos = next_other_pos + dist2*other_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+
+          cntr = 0;
+          api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            dist2 = (next_other_pos-new_pos3).len() / 2.0;
+            tmp_pos = next_other_pos + dist2*other_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+            api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+          // Create the edge going from the new clump vert to new_pos1.
+          VERTEX *v1 = new_vert_from_pos(new_pos1);
+          VERTEX *v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge1 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+          // Make another copy of this.
+          v1 = new_vert_from_pos(new_pos1);
+          v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge8 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge8, "REMOVE_EDGE");
+          // Create the edge going from the cur split to new_pos2.
+          v1 = new_vert_from_pos(new_pos2);
+          v2 = new_vert_from_pos(other_vert_pos);
+          new_edge2 = imprint_new_edge_on_face(face, v1, v2);
+          if(!new_edge2)
+            ret = CUBIT_FAILURE;
+          else
+          {
+            add_named_att((ENTITY*)new_edge2, "REMOVE_EDGE");
+            api_copy_entity_contents((ENTITY*)new_edge2, new_ent);
+            new_edge2 = (EDGE*)new_ent;
+            // Create the edge going from the next split to new_pos3.
+            v1 = new_vert_from_pos(new_pos3);
+            v2 = new_vert_from_pos(next_other_pos);
+            new_edge3 = imprint_new_edge_on_face(face, v1, v2);
+            if(!new_edge3)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge3, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge3, new_ent);
+              new_edge3 = (EDGE*)new_ent;
+              // Create the edge going from new_pos1 to new_pos2.
+              v1 = new_vert_from_pos(new_pos1);
+              v2 = new_vert_from_pos(new_pos2);
+              new_edge4 = imprint_new_edge_on_face(face, v1, v2);
+              if(!new_edge4)
+                ret = CUBIT_FAILURE;
+              else
+              {
+                face = this->find_keep_face(new_edge4, vert, dead_faces);
+                if(!face)
+                  ret = CUBIT_FAILURE;
+                else
+                {
+                  add_named_att((ENTITY*)new_edge4, "REMOVE_EDGE");
+                  api_copy_entity_contents((ENTITY*)new_edge4, new_ent);
+                  new_edge4 = (EDGE*)new_ent;
+                  // Create the edge going from new_pos1 to new_pos3.
+                  v1 = new_vert_from_pos(new_pos1);
+                  v2 = new_vert_from_pos(new_pos3);
+                  new_edge5 = imprint_new_edge_on_face(face, v1, v2);
+                  if(!new_edge5)
+                    ret = CUBIT_FAILURE;
+                  else
+                  {
+                    face = this->find_keep_face(new_edge5, vert, dead_faces);
+                    if(!face)
+                      ret = CUBIT_FAILURE;
+                    else
+                    {
+                      add_named_att((ENTITY*)new_edge5, "REMOVE_EDGE");
+                      api_copy_entity_contents((ENTITY*)new_edge5, new_ent);
+                      new_edge5 = (EDGE*)new_ent;
+                      v1 = new_vert_from_pos(other_vert_pos);
+                      v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+                      s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                      new_edge6 = new EDGE(v1, v2, s, FORWARD);
+                      v1 = new_vert_from_pos(next_other_pos);
+                      v2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+                      s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                      new_edge7 = new EDGE(v1, v2, s, FORWARD);
+                      if(new_edge1 && new_edge2 && new_edge4 && new_edge6)
+                      {
+                        // Now create the new face.
+                        DLIList<EDGE*> edges_for_new_face;
+                        edges_for_new_face.append(new_edge1);
+                        edges_for_new_face.append(new_edge2);
+                        edges_for_new_face.append(new_edge4);
+                        edges_for_new_face.append(new_edge6);
+                        FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                        if(FACE_ptr)
+                        {
+                          new_vol_faces.append(FACE_ptr);
+                          projected_positions.append(new_pos1);
+                          projected_positions.append(new_pos2);
+                          if(new_edge8 && new_edge3 && new_edge5 && new_edge7)
+                          {
+                            // Now create the new face.
+                            DLIList<EDGE*> edges_for_new_face;
+                            edges_for_new_face.append(new_edge8);
+                            edges_for_new_face.append(new_edge3);
+                            edges_for_new_face.append(new_edge5);
+                            edges_for_new_face.append(new_edge7);
+                            FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                            if(FACE_ptr)
+                            {
+                              new_vol_faces.append(FACE_ptr);
+                              projected_positions.append(new_pos3);
+                            }
+                            else
+                            {
+                              PRINT_ERROR("Failed to build face from bounding curves.\n");
+                              ret = CUBIT_FAILURE;
+                            }
+                          }
+                          else
+                          {
+                            PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                            ret = CUBIT_FAILURE;
+                          }
+                        }
+                        else
+                        {
+                          PRINT_ERROR("Failed to build face from bounding curves.\n");
+                          ret = CUBIT_FAILURE;
+                        }
+                      }
+                      else
+                      {
+                        PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                        ret = CUBIT_FAILURE;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        else if(angle <= seven_pi_over_four)
+        {
+          // Add three new faces.
+          EDGE *new_edge1=NULL, *new_edge2=NULL, *new_edge3=NULL, *new_edge4=NULL, *new_edge5=NULL;
+          EDGE *new_edge6, *new_edge7, *new_edge8, *new_edge9, *new_edge10, *new_edge11, *new_edge12;
+          SPAposition new_pos1, new_pos2, new_pos3, new_pos4, new_pos5;
+          SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                              (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                              (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+
+          // Project from the current vert into the face at an average direction.
+          SPAunit_vector cur_in_dir, next_in_dir, cur_other_in_dir, next_other_in_dir;
+          tangent_indir(face, edge, vert->geometry()->coords(), cur_in_dir); 
+          tangent_indir(face, next_edge, next_vert->geometry()->coords(), next_in_dir); 
+          SPAvector ave_dir = cur_in_dir + next_in_dir;
+          SPAvector ave_dir_norm = normalise(ave_dir);
+          angle /= 2.0;
+          double distance = backoff_distance/sin(angle);
+          tmp_pos = mid_pos + distance * ave_dir_norm;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+          int cntr = 0;
+          point_face_containment containment;
+          api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+          // Try to make sure we have a point on the face.
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (clump_vert->geometry()->coords()-new_pos1).len() / 2.0;
+            tmp_pos = mid_pos + distance * ave_dir_norm;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+            api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+          double dist2 = backoff_distance;
+          // Project from each split position into the face to get the
+          // other two new positions.
+          // Now that we have the location of the new position projected into
+          // the face we will create the first new edge.
+          tangent_indir(face, edge, other_vert_pos, cur_other_in_dir); 
+          tmp_pos = other_vert_pos + dist2*cur_other_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+
+          cntr = 0;
+          api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            dist2 = (other_vert_pos-new_pos2).len() / 2.0;
+            tmp_pos = other_vert_pos + dist2*cur_other_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+            api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          tangent_indir(face, next_edge, next_other_pos, next_other_in_dir); 
+          tmp_pos = next_other_pos + dist2*next_other_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+
+          cntr = 0;
+          api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            dist2 = (next_other_pos-new_pos3).len() / 2.0;
+            tmp_pos = next_other_pos + dist2*next_other_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+            api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          tmp_pos = vert->geometry()->coords() + dist2*cur_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos4);
+
+          cntr = 0;
+          api_point_in_face(new_pos4, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            dist2 = (vert->geometry()->coords()-new_pos4).len() / 2.0;
+            tmp_pos = vert->geometry()->coords() + dist2*cur_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos4);
+            api_point_in_face(new_pos4, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          tmp_pos = next_vert->geometry()->coords() + dist2*next_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos5);
+
+          cntr = 0;
+          api_point_in_face(new_pos5, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            dist2 = (next_vert->geometry()->coords()-new_pos5).len() / 2.0;
+            tmp_pos = next_vert->geometry()->coords() + dist2*next_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos5);
+            api_point_in_face(new_pos5, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          // Create the edge going from the new clump vert to new_pos4.
+          VERTEX *v1 = new_vert_from_pos(new_pos4);
+          VERTEX *v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge1 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+          // Make another copy of this.
+          v1 = new_vert_from_pos(new_pos4);
+          v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge8 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge8, "REMOVE_EDGE");
+          // Create the edge going from new clump vert to new_pos5
+          v1 = new_vert_from_pos(new_pos5);
+          v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge2 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge2, "REMOVE_EDGE");
+          // Make another copy of this.
+          v1 = new_vert_from_pos(new_pos5);
+          v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge3 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge3, "REMOVE_EDGE");
+
+          // Create the edge going from the cur split to new_pos2.
+          v1 = new_vert_from_pos(new_pos2);
+          v2 = new_vert_from_pos(other_vert_pos);
+          new_edge4 = imprint_new_edge_on_face(face, v1, v2);
+          if(!new_edge4)
+            ret = CUBIT_FAILURE;
+          else
+          {
+            add_named_att((ENTITY*)new_edge4, "REMOVE_EDGE");
+            api_copy_entity_contents((ENTITY*)new_edge4, new_ent);
+            new_edge4 = (EDGE*)new_ent;
+            // Create the edge going from the next split to new_pos3.
+            v1 = new_vert_from_pos(new_pos3);
+            v2 = new_vert_from_pos(next_other_pos);
+            new_edge5 = imprint_new_edge_on_face(face, v1, v2);
+            if(!new_edge5)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge5, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge5, new_ent);
+              new_edge5 = (EDGE*)new_ent;
+              // Create the edge going from new_pos4 to new_pos2.
+              v1 = new_vert_from_pos(new_pos4);
+              v2 = new_vert_from_pos(new_pos2);
+              new_edge6 = imprint_new_edge_on_face(face, v1, v2);
+              if(!new_edge6)
+                ret = CUBIT_FAILURE;
+              else
+              {
+                face = this->find_keep_face(new_edge6, vert, dead_faces);
+                if(!face)
+                  ret = CUBIT_FAILURE;
+                else
+                {
+                  add_named_att((ENTITY*)new_edge6, "REMOVE_EDGE");
+                  api_copy_entity_contents((ENTITY*)new_edge6, new_ent);
+                  new_edge6 = (EDGE*)new_ent;
+                  // Create the edge going from new_pos1 to new_pos4.
+                  v1 = new_vert_from_pos(new_pos1);
+                  v2 = new_vert_from_pos(new_pos4);
+                  new_edge7 = imprint_new_edge_on_face(face, v1, v2);
+                  if(!new_edge7)
+                    ret = CUBIT_FAILURE;
+                  else
+                  {
+                    face = this->find_keep_face(new_edge7, vert, dead_faces);
+                    if(!face)
+                      ret = CUBIT_FAILURE;
+                    else
+                    {
+                      add_named_att((ENTITY*)new_edge7, "REMOVE_EDGE");
+                      api_copy_entity_contents((ENTITY*)new_edge7, new_ent);
+                      new_edge7 = (EDGE*)new_ent;
+                      // Create the edge going from new_pos1 to new_pos5.
+                      v1 = new_vert_from_pos(new_pos1);
+                      v2 = new_vert_from_pos(new_pos5);
+                      new_edge9 = imprint_new_edge_on_face(face, v1, v2);
+                      if(!new_edge9)
+                        ret = CUBIT_FAILURE;
+                      else
+                      {
+                        face = this->find_keep_face(new_edge9, next_vert, dead_faces);
+                        if(!face)
+                          ret = CUBIT_FAILURE;
+                        else
+                        {
+                          add_named_att((ENTITY*)new_edge9, "REMOVE_EDGE");
+                          api_copy_entity_contents((ENTITY*)new_edge9, new_ent);
+                          new_edge9 = (EDGE*)new_ent;
+                          // Create the edge going from new_pos3 to new_pos5.
+                          v1 = new_vert_from_pos(new_pos3);
+                          v2 = new_vert_from_pos(new_pos5);
+                          new_edge10 = imprint_new_edge_on_face(face, v1, v2);
+                          if(!new_edge10)
+                            ret = CUBIT_FAILURE;
+                          else
+                          {
+                            face = this->find_keep_face(new_edge10, next_vert, dead_faces);
+                            if(!face)
+                              ret = CUBIT_FAILURE;
+                            else
+                            {
+                              add_named_att((ENTITY*)new_edge10, "REMOVE_EDGE");
+                              api_copy_entity_contents((ENTITY*)new_edge10, new_ent);
+                              new_edge10 = (EDGE*)new_ent;
+                              v1 = new_vert_from_pos(other_vert_pos);
+                              v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+                              s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                              new_edge11 = new EDGE(v1, v2, s, FORWARD);
+                              v1 = new_vert_from_pos(next_other_pos);
+                              v2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+                              s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                              new_edge12 = new EDGE(v1, v2, s, FORWARD);
+                              if(new_edge1 && new_edge6 && new_edge4 && new_edge11)
+                              {
+                                // Now create the new face.
+                                DLIList<EDGE*> edges_for_new_face;
+                                edges_for_new_face.append(new_edge1);
+                                edges_for_new_face.append(new_edge11);
+                                edges_for_new_face.append(new_edge4);
+                                edges_for_new_face.append(new_edge6);
+                                FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                if(FACE_ptr)
+                                {
+                                  new_vol_faces.append(FACE_ptr);
+                                  projected_positions.append(new_pos4);
+                                  projected_positions.append(new_pos2);
+                                  if(new_edge8 && new_edge7 && new_edge2 && new_edge9)
+                                  {
+                                    // Now create the new face.
+                                    DLIList<EDGE*> edges_for_new_face;
+                                    edges_for_new_face.append(new_edge8);
+                                    edges_for_new_face.append(new_edge2);
+                                    edges_for_new_face.append(new_edge9);
+                                    edges_for_new_face.append(new_edge7);
+                                    FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                    if(FACE_ptr)
+                                    {
+                                      new_vol_faces.append(FACE_ptr);
+                                      projected_positions.append(new_pos1);
+                                      projected_positions.append(new_pos5);
+                                      if(new_edge3 && new_edge5 && new_edge10 && new_edge12)
+                                      {
+                                        // Now create the new face.
+                                        DLIList<EDGE*> edges_for_new_face;
+                                        edges_for_new_face.append(new_edge3);
+                                        edges_for_new_face.append(new_edge5);
+                                        edges_for_new_face.append(new_edge10);
+                                        edges_for_new_face.append(new_edge12);
+                                        FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                        if(FACE_ptr)
+                                        {
+                                          new_vol_faces.append(FACE_ptr);
+                                          projected_positions.append(new_pos3);
+                                        }
+                                        else
+                                        {
+                                          PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                          ret = CUBIT_FAILURE;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                        ret = CUBIT_FAILURE;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                      ret = CUBIT_FAILURE;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                    ret = CUBIT_FAILURE;
+                                  }
+                                }
+                                else
+                                {
+                                  PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                  ret = CUBIT_FAILURE;
+                                }
+                              }
+                              else
+                              {
+                                PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                ret = CUBIT_FAILURE;
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        else
+        {
+          // Add 4 new faces.
+          EDGE *new_edge1=NULL, *new_edge2=NULL, *new_edge3=NULL, *new_edge4=NULL, *new_edge5=NULL;
+          EDGE *new_edge6, *new_edge7, *new_edge8, *new_edge9, *new_edge10, *new_edge11, *new_edge12;
+          EDGE *new_edge13, *new_edge14, *new_edge15, *new_edge16;
+          SPAposition new_pos1, new_pos2, new_pos3, new_pos4, new_pos5, new_pos6, new_pos7;
+          SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                              (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                              (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+
+          // Project from the current vert into the face at an average direction.
+          SPAunit_vector cur_in_dir, next_in_dir, cur_other_in_dir, next_other_in_dir, mid_dir;
+          SPAunit_vector cur_mid_dir, next_mid_dir;
+          tangent_indir(face, edge, vert->geometry()->coords(), cur_in_dir); 
+          tangent_indir(face, next_edge, next_vert->geometry()->coords(), next_in_dir); 
+          tangent_indir(face, edge, other_vert_pos, cur_other_in_dir); 
+          tangent_indir(face, next_edge, next_other_pos, next_other_in_dir); 
+          mid_dir = normalise(normalise(next_vert->geometry()->coords() - next_other_pos) + 
+            normalise(vert->geometry()->coords() - other_vert_pos));
+          cur_mid_dir = normalise(mid_dir + cur_in_dir);
+          next_mid_dir = normalise(mid_dir + next_in_dir);
+
+          double distance = backoff_distance;
+          tmp_pos = mid_pos + distance * mid_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+          int cntr = 0;
+          point_face_containment containment;
+          api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+          // Try to make sure we have a point on the face.
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (clump_vert->geometry()->coords()-new_pos1).len() / 2.0;
+            tmp_pos = mid_pos + distance * mid_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+            api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          distance = sqrt(2.0)*backoff_distance;
+          tmp_pos = vert->geometry()->coords() + distance*cur_mid_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+          cntr = 0;
+          api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (clump_vert->geometry()->coords()-new_pos2).len() / 2.0;
+            tmp_pos = vert->geometry()->coords() + distance*cur_mid_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+            api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          distance = sqrt(2.0)*backoff_distance;
+          tmp_pos = next_vert->geometry()->coords() + distance*next_mid_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+          cntr = 0;
+          api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (clump_vert->geometry()->coords()-new_pos3).len() / 2.0;
+            tmp_pos = next_vert->geometry()->coords() + distance*next_mid_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+            api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          distance = backoff_distance;
+          tmp_pos = vert->geometry()->coords() + distance*cur_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos4);
+          cntr = 0;
+          api_point_in_face(new_pos4, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (vert->geometry()->coords()-new_pos4).len() / 2.0;
+            tmp_pos = vert->geometry()->coords() + distance*cur_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos4);
+            api_point_in_face(new_pos4, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          distance = backoff_distance;
+          tmp_pos = next_vert->geometry()->coords() + distance*next_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos5);
+          cntr = 0;
+          api_point_in_face(new_pos5, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (next_vert->geometry()->coords()-new_pos5).len() / 2.0;
+            tmp_pos = next_vert->geometry()->coords() + distance*next_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos5);
+            api_point_in_face(new_pos5, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          distance = backoff_distance;
+          tmp_pos = next_other_pos + distance*next_other_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos6);
+          cntr = 0;
+          api_point_in_face(new_pos6, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (next_other_pos-new_pos6).len() / 2.0;
+            tmp_pos = next_other_pos + distance*next_other_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos6);
+            api_point_in_face(new_pos6, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          distance = backoff_distance;
+          tmp_pos = other_vert_pos + distance*cur_other_in_dir;
+          api_find_cls_ptto_face(tmp_pos, face, new_pos7);
+          cntr = 0;
+          api_point_in_face(new_pos7, face, *(SPAtransf*)NULL_REF, containment); 
+          while(containment == point_boundary_face && cntr++ < 10)
+          {
+            distance = (other_vert_pos-new_pos7).len() / 2.0;
+            tmp_pos = other_vert_pos + distance*cur_other_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos7);
+            api_point_in_face(new_pos7, face, *(SPAtransf*)NULL_REF, containment); 
+          }
+
+          // Create the edge going from the new clump vert to new_pos4.
+          VERTEX *v1 = new_vert_from_pos(new_pos4);
+          VERTEX *v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge1 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+          // Make another copy of this.
+          api_copy_entity_contents((ENTITY*)new_edge1, new_ent);
+          new_edge2 = (EDGE*)new_ent;
+          // Create the edge going from the new clump vert to new_pos1.
+          v1 = new_vert_from_pos(new_pos1);
+          v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge3 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge3, "REMOVE_EDGE");
+          // Make another copy of this.
+          api_copy_entity_contents((ENTITY*)new_edge3, new_ent);
+          new_edge4 = (EDGE*)new_ent;
+          // Create the edge going from the new clump vert to new_pos5.
+          v1 = new_vert_from_pos(new_pos5);
+          v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+          s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+          new_edge5 = new EDGE(v1, v2, s, FORWARD);
+          add_named_att((ENTITY*)new_edge5, "REMOVE_EDGE");
+          // Make another copy of this.
+          api_copy_entity_contents((ENTITY*)new_edge5, new_ent);
+          new_edge6 = (EDGE*)new_ent;
+
+          // Create the edge going from the cur split to new_pos7.
+          v1 = new_vert_from_pos(new_pos7);
+          v2 = new_vert_from_pos(other_vert_pos);
+          new_edge7 = imprint_new_edge_on_face(face, v1, v2);
+          if(!new_edge7)
+            ret = CUBIT_FAILURE;
+          else
+          {
+            add_named_att((ENTITY*)new_edge7, "REMOVE_EDGE");
+            api_copy_entity_contents((ENTITY*)new_edge7, new_ent);
+            new_edge7 = (EDGE*)new_ent;
+            // Create the edge going from the next split to new_pos6.
+            v1 = new_vert_from_pos(new_pos6);
+            v2 = new_vert_from_pos(next_other_pos);
+            new_edge8 = imprint_new_edge_on_face(face, v1, v2);
+            if(!new_edge8)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge8, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge8, new_ent);
+              new_edge8 = (EDGE*)new_ent;
+              // Create the edge going from new_pos4 to new_pos7.
+              v1 = new_vert_from_pos(new_pos4);
+              v2 = new_vert_from_pos(new_pos7);
+              new_edge9 = imprint_new_edge_on_face(face, v1, v2);
+              if(!new_edge9)
+                ret = CUBIT_FAILURE;
+              else
+              {
+                face = this->find_keep_face(new_edge9, vert, dead_faces);
+                if(!face)
+                  ret = CUBIT_FAILURE;
+                else
+                {
+                  add_named_att((ENTITY*)new_edge9, "REMOVE_EDGE");
+                  api_copy_entity_contents((ENTITY*)new_edge9, new_ent);
+                  new_edge9 = (EDGE*)new_ent;
+                  // Create the edge going from new_pos2 to new_pos4.
+                  v1 = new_vert_from_pos(new_pos2);
+                  v2 = new_vert_from_pos(new_pos4);
+                  new_edge10 = imprint_new_edge_on_face(face, v1, v2);
+                  if(!new_edge10)
+                    ret = CUBIT_FAILURE;
+                  else
+                  {
+                    add_named_att((ENTITY*)new_edge10, "REMOVE_EDGE");
+                    api_copy_entity_contents((ENTITY*)new_edge10, new_ent);
+                    new_edge10 = (EDGE*)new_ent;
+                    // Create the edge going from new_pos1 to new_pos2.
+                    v1 = new_vert_from_pos(new_pos1);
+                    v2 = new_vert_from_pos(new_pos2);
+                    new_edge11 = imprint_new_edge_on_face(face, v1, v2);
+                    if(!new_edge11)
+                      ret = CUBIT_FAILURE;
+                    else
+                    {
+                      face = this->find_keep_face(new_edge11, vert, dead_faces);
+                      if(!face)
+                        ret = CUBIT_FAILURE;
+                      else
+                      {
+                        add_named_att((ENTITY*)new_edge11, "REMOVE_EDGE");
+                        api_copy_entity_contents((ENTITY*)new_edge11, new_ent);
+                        new_edge11 = (EDGE*)new_ent;
+                        // Create the edge going from new_pos1 to new_pos3.
+                        v1 = new_vert_from_pos(new_pos1);
+                        v2 = new_vert_from_pos(new_pos3);
+                        new_edge12 = imprint_new_edge_on_face(face, v1, v2);
+                        if(!new_edge12)
+                          ret = CUBIT_FAILURE;
+                        else
+                        {
+                          add_named_att((ENTITY*)new_edge12, "REMOVE_EDGE");
+                          api_copy_entity_contents((ENTITY*)new_edge12, new_ent);
+                          new_edge12 = (EDGE*)new_ent;
+                          // Create the edge going from new_pos3 to new_pos5.
+                          v1 = new_vert_from_pos(new_pos3);
+                          v2 = new_vert_from_pos(new_pos5);
+                          new_edge13 = imprint_new_edge_on_face(face, v1, v2);
+                          if(!new_edge13)
+                            ret = CUBIT_FAILURE;
+                          else
+                          {
+                            face = this->find_keep_face(new_edge13, next_vert, dead_faces);
+                            if(!face)
+                              ret = CUBIT_FAILURE;
+                            else
+                            {
+                              add_named_att((ENTITY*)new_edge13, "REMOVE_EDGE");
+                              api_copy_entity_contents((ENTITY*)new_edge13, new_ent);
+                              new_edge13 = (EDGE*)new_ent;
+                              // Create the edge going from new_pos6 to new_pos5.
+                              v1 = new_vert_from_pos(new_pos6);
+                              v2 = new_vert_from_pos(new_pos5);
+                              new_edge14 = imprint_new_edge_on_face(face, v1, v2);
+                              if(!new_edge14)
+                                ret = CUBIT_FAILURE;
+                              else
+                              {
+                                face = this->find_keep_face(new_edge14, next_vert, dead_faces);
+                                if(!face)
+                                  ret = CUBIT_FAILURE;
+                                else
+                                {
+                                  add_named_att((ENTITY*)new_edge14, "REMOVE_EDGE");
+                                  api_copy_entity_contents((ENTITY*)new_edge14, new_ent);
+                                  new_edge14 = (EDGE*)new_ent;
+                                  v1 = new_vert_from_pos(other_vert_pos);
+                                  v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+                                  s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                                  new_edge15 = new EDGE(v1, v2, s, FORWARD);
+                                  v1 = new_vert_from_pos(next_other_pos);
+                                  v2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+                                  s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                                  new_edge16 = new EDGE(v1, v2, s, FORWARD);
+                                  if(new_edge1 && new_edge7 && new_edge9 && new_edge15)
+                                  {
+                                    // Now create the new face.
+                                    DLIList<EDGE*> edges_for_new_face;
+                                    edges_for_new_face.append(new_edge1);
+                                    edges_for_new_face.append(new_edge15);
+                                    edges_for_new_face.append(new_edge7);
+                                    edges_for_new_face.append(new_edge9);
+                                    FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                    if(FACE_ptr)
+                                    {
+                                      new_vol_faces.append(FACE_ptr);
+                                      projected_positions.append(new_pos4);
+                                      projected_positions.append(new_pos7);
+                                      if(new_edge2 && new_edge3 && new_edge10 && new_edge11)
+                                      {
+                                        // Now create the new face.
+                                        DLIList<EDGE*> edges_for_new_face;
+                                        edges_for_new_face.append(new_edge2);
+                                        edges_for_new_face.append(new_edge3);
+                                        edges_for_new_face.append(new_edge10);
+                                        edges_for_new_face.append(new_edge11);
+                                        FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                        if(FACE_ptr)
+                                        {
+                                          new_vol_faces.append(FACE_ptr);
+                                          projected_positions.append(new_pos2);
+                                          projected_positions.append(new_pos1);
+                                          if(new_edge4 && new_edge5 && new_edge12 && new_edge13)
+                                          {
+                                            // Now create the new face.
+                                            DLIList<EDGE*> edges_for_new_face;
+                                            edges_for_new_face.append(new_edge4);
+                                            edges_for_new_face.append(new_edge5);
+                                            edges_for_new_face.append(new_edge12);
+                                            edges_for_new_face.append(new_edge13);
+                                            FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                            if(FACE_ptr)
+                                            {
+                                              new_vol_faces.append(FACE_ptr);
+                                              projected_positions.append(new_pos3);
+                                              projected_positions.append(new_pos5);
+                                              if(new_edge6 && new_edge8 && new_edge14 && new_edge16)
+                                              {
+                                                // Now create the new face.
+                                                DLIList<EDGE*> edges_for_new_face;
+                                                edges_for_new_face.append(new_edge6);
+                                                edges_for_new_face.append(new_edge8);
+                                                edges_for_new_face.append(new_edge14);
+                                                edges_for_new_face.append(new_edge16);
+                                                FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                                if(FACE_ptr)
+                                                {
+                                                  new_vol_faces.append(FACE_ptr);
+                                                  projected_positions.append(new_pos6);
+                                                }
+                                                else
+                                                {
+                                                  PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                                  ret = CUBIT_FAILURE;
+                                                }
+                                              }
+                                              else
+                                              {
+                                                PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                                ret = CUBIT_FAILURE;
+                                              }
+                                            }
+                                            else
+                                            {
+                                              PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                              ret = CUBIT_FAILURE;
+                                            }
+                                          }
+                                          else
+                                          {
+                                            PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                            ret = CUBIT_FAILURE;
+                                          }
+                                        }
+                                        else
+                                        {
+                                          PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                          ret = CUBIT_FAILURE;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                        ret = CUBIT_FAILURE;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                      ret = CUBIT_FAILURE;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                    ret = CUBIT_FAILURE;
+                                  }
+                                }
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    else
+      ret = CUBIT_FAILURE;
+  }
+  return ret;
+}
+
+EDGE* AcisTopologyTool::get_other_edge(EDGE *edge, VERTEX *vert, FACE *face)
+{
+  ENTITY_LIST face_edges;
+  api_get_edges((ENTITY*)face, face_edges);
+  face_edges.init();
+  ENTITY *tmp_ent;
+  EDGE *other_edge = NULL;
+  while((tmp_ent = face_edges.next()) && !other_edge)
+  {
+    if(tmp_ent != edge)
+    {
+      ENTITY_LIST edge_verts;
+      api_get_vertices(tmp_ent, edge_verts);
+      ENTITY *tmp_ent2;
+      edge_verts.init();
+      while((tmp_ent2 = edge_verts.next()) && !other_edge)
+      {
+        if(tmp_ent2 == vert)
+          other_edge = (EDGE*)tmp_ent;
+      }
+    }
+  }
+  return other_edge;
+}
+
+VERTEX* AcisTopologyTool::other_vertex(EDGE *edge, VERTEX *vert)
+{
+  VERTEX *other_vert = NULL;
+  if(edge->start() == edge->end())
+  {
+  }
+  else
+  {
+    if(edge->start() == vert)
+      other_vert = edge->end();
+    else
+      other_vert = edge->start();
+  }
+  return other_vert;
+}
+
+void AcisTopologyTool::get_next_edge_around_clump(EDGE *cur_edge, VERTEX *cur_vert,
+                                                    FACE *cur_face, 
+                                                    std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                                    EDGE *&next_edge, VERTEX *&next_vert)
+{
+  next_edge = NULL;
+  next_vert = NULL;
+
+  if(cur_edge && cur_vert && cur_face)
+  {
+    EDGE *tmp_edge = get_other_edge(cur_edge, cur_vert, cur_face);
+    if(tmp_edge)
+    {
+      VERTEX *tmp_vert = cur_vert;
+      while(edge_within_clump(tmp_edge, old_vertex_to_clump_map))
+      {
+        tmp_vert = other_vertex(tmp_edge, tmp_vert);
+        tmp_edge = get_other_edge(tmp_edge, tmp_vert, cur_face);
+      }
+      next_edge = tmp_edge;
+      next_vert = tmp_vert;
+    }
+  }
+}
+
+double AcisTopologyTool::angle_between(FACE *face, EDGE *e1, VERTEX *v1,
+                                     EDGE *e2, VERTEX *v2)
+{
+  double angle = 0.0;
+  SPAposition clos;
+  SPAunit_vector norm1, norm2;
+  SPAunit_vector tan1_norm, tan2_norm;
+  EDGE *cur_edge, *next_edge;
+  VERTEX *cur_vert, *next_vert;
+
+  CubitVector prev_tan;
+  cur_edge = e1;
+  cur_vert = v1;
+  while(cur_edge != e2)
+  {
+    ENTITY_LIST vert_edges;
+    api_get_edges((ENTITY*)cur_vert, vert_edges);
+    vert_edges.remove(cur_edge);
+    next_edge = NULL;
+    vert_edges.init();
+    ENTITY *tmp_ent;
+    // Find the next edge in the face (and next vert)
+    while((tmp_ent = vert_edges.next()) && !next_edge)
+    {
+      ENTITY_LIST edge_faces;
+      api_get_faces(tmp_ent, edge_faces);
+      if(edge_faces.lookup(face) != -1)
+      {
+        next_edge = (EDGE*)tmp_ent;
+        if(next_edge->start() == cur_vert)
+          next_vert = next_edge->end();
+        else
+          next_vert = next_edge->start();
+      }
+    }
+    SPAvector tan1, tan2;
+    if(cur_vert == cur_edge->start())
+      tan1 = cur_edge->start_deriv();
+    else
+      tan1 = -(cur_edge->end_deriv());
+    if(cur_vert == next_edge->start())
+      tan2 = next_edge->start_deriv();
+    else
+      tan2 = -(next_edge->end_deriv());
+    tan1_norm = normalise(tan1);
+    tan2_norm = normalise(tan2);
+    face->geometry()->equation().point_perp(cur_vert->geometry()->coords(), clos, norm1); 
+    if(face->sense() == REVERSED)
+      norm1 = -norm1;
+
+    SPAvector ave_norm = normalise(norm1);
+
+    CubitVector cub_ave_norm(ave_norm.x(), ave_norm.y(), ave_norm.z());
+    CubitVector cub_tan1(tan1_norm.x(), tan1_norm.y(), tan1_norm.z());
+    CubitVector cub_tan2(tan2_norm.x(), tan2_norm.y(), tan2_norm.z());
+
+    double cur_angle;
+    COEDGE *co1 = cur_edge->coedge(face);
+    if(co1->end() == cur_vert)
+      cur_angle = cub_ave_norm.vector_angle(cub_tan2, cub_tan1);
+    else
+      cur_angle = cub_ave_norm.vector_angle(cub_tan1, cub_tan2);
+
+    // Get the angle that this curve has gone through from
+    // one end to another.
+    if(cur_edge != e1)
+    {
+      CubitVector temp_tan1 = -cub_tan1;
+      double dot = temp_tan1 % prev_tan;
+      if(dot < -1.0)
+        dot = -1.0;
+      else if(dot > 1.0)
+        dot = 1.0;
+      double temp_angle = acos(dot);
+      //temp_angle = cub_ave_norm.vector_angle(prev_tan, temp_tan1);
+      angle += temp_angle;
+    }
+
+    prev_tan = cub_tan2;
+
+    if(cur_angle == 0.0)
+    {
+      double dist = 10.0 * GEOMETRY_RESABS;
+      SPAposition test_pos = next_vert->geometry()->coords() - dist * tan2_norm;
+      SPApar_pos uv;
+      face->geometry()->equation().point_perp(test_pos, clos, *(SPApar_pos*)NULL_REF, uv); 
+      point_face_containment containment;
+      api_point_in_face(clos, face, *(SPAtransf*)NULL_REF, containment, uv); 
+      if(containment == point_inside_face)
+        cur_angle = 2.0*CUBIT_PI;
+    }
+
+    angle += cur_angle;
+    // For each time we set cur_edge equal to next_edge and 
+    // traverse around we need to subtract PI to get the 
+    // correct angle in the end. 
+    if(cur_edge != e1)
+      angle -= CUBIT_PI;
+
+    cur_edge = next_edge;
+    cur_vert = next_vert;
+  }
+
+  return angle;
+}
+
+void AcisTopologyTool::tangent_indir( FACE *FACE_ptr, EDGE *EDGE_ptr,
+                               const SPAposition &acis_pos, SPAunit_vector &in_dir )
+{
+  // Get the normal to the FACE at the position
+  SPAposition acis_pos_on_surf;
+  SPAunit_vector acis_face_norm;
+  (FACE_ptr->geometry()->equation()).point_perp( acis_pos,
+    acis_pos_on_surf, acis_face_norm );
+
+  // Adjust for the FACE sense
+  if( FACE_ptr->sense() == REVERSED )
+    acis_face_norm = -acis_face_norm;
+
+  // Get a vector tangent to the EDGE, adjusted for the EDGE sense on the FACE
+  SPAunit_vector acis_tangent_vec = (EDGE_ptr->geometry()->equation()).
+    point_direction( acis_pos );
+  if( EDGE_ptr->sense() == REVERSED )
+    acis_tangent_vec = -acis_tangent_vec;
+
+  COEDGE *COEDGE_ptr = EDGE_ptr->coedge( FACE_ptr );
+  if( COEDGE_ptr->sense() == REVERSED )
+    acis_tangent_vec = -acis_tangent_vec;
+
+  SPAvector tangent_indir = acis_tangent_vec * acis_face_norm;
+  in_dir = normalise(-tangent_indir);
+}
+
+EDGE* AcisTopologyTool::imprint_new_edge_on_face(FACE *face, VERTEX *v1, 
+                                                 VERTEX *v2)
+{
+  EDGE *ret_edge = NULL;
+  double tol = GEOMETRY_RESABS*GEOMETRY_RESABS;
+  SPAposition clos;
+  SPAunit_vector norm;
+  face->geometry()->equation().point_perp(v1->geometry()->coords(), clos, norm);
+  SPAvector edge0 = v2->geometry()->coords() - v1->geometry()->coords();
+  SPAvector edge1 = norm;
+  SPAvector plane_normal = edge0 * edge1;
+  SPAunit_vector plane_normal_normalized = normalise(plane_normal);
+  CubitVector plane_norm(plane_normal_normalized.x(), plane_normal_normalized.y(), plane_normal_normalized.z());
+  STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+  EDGE *edge = new EDGE(v1, v2, s, FORWARD);
+  EDGE *new_edge = AcisModifyEngine::instance()->project_EDGE(edge, face);
+  if(new_edge)
+  {
+    ENTITY *body;
+    api_get_owner((ENTITY*)face, body);
+    ENTITY_LIST body_edges_before;
+    api_get_edges(body, body_edges_before);
+    DLIList<TopologyBridge*> temporary_bridges;
+    AcisModifyEngine::instance()->imprint((BODY*)body, face, new_edge, temporary_bridges);
+    temporary_bridges.uniquify_ordered();
+    while(temporary_bridges.size())
+      delete temporary_bridges.pop();
+    ENTITY_LIST body_edges_after;
+    api_get_edges(body, body_edges_after);
+    ENTITY *tmp_ent;
+    body_edges_after.remove(body_edges_before);
+    body_edges_after.init();
+    if(body_edges_after.iteration_count() == 1)
+      ret_edge = (EDGE*)body_edges_after.next();
+    else
+    {
+      while((tmp_ent = body_edges_after.next()) && !new_edge)
+      {
+        EDGE *cur_edge = (EDGE*)tmp_ent;
+        if((cur_edge->start_pos()-v1->geometry()->coords()).len_sq() < tol)
+        {
+          if((cur_edge->end_pos()-v2->geometry()->coords()).len_sq() < tol)
+            ret_edge = cur_edge;
+        }
+        else if((cur_edge->start_pos()-v2->geometry()->coords()).len_sq() < tol)
+        {
+          if((cur_edge->end_pos()-v1->geometry()->coords()).len_sq() < tol)
+            ret_edge = cur_edge;
+        }
+      }
+    }
+  }
+
+  return ret_edge;
+}
+
+FACE* AcisTopologyTool::find_keep_face(EDGE *edge,
+                                    VERTEX *vert,
+                                    DLIList<FACE*> &dead_faces)
+{
+  FACE *keep_face = NULL;
+  ENTITY_LIST edge_faces;
+  api_get_faces((ENTITY*)edge, edge_faces);
+  edge_faces.init();
+  if(edge_faces.count() == 1)
+    keep_face = (FACE*)edge_faces.next();
+  else if(edge_faces.count() == 2)
+  {
+    ENTITY *cur_face = edge_faces.next();
+    ENTITY_LIST tmp_verts;
+    api_get_vertices(cur_face, tmp_verts);
+    if(tmp_verts.lookup(vert) != -1)
+    {
+      keep_face = (FACE*)edge_faces.next();
+      dead_faces.append((FACE*)cur_face);
+    }
+    else
+    {
+      keep_face = (FACE*)cur_face;
+      dead_faces.append((FACE*)edge_faces.next());
+    }
+  }
+  else
+    PRINT_ERROR("Unexpected number of faces after split.\n");
+
+  if(!keep_face)
+    PRINT_ERROR("Failed to find the face to keep after imprinting.\n");
+
+  return keep_face;
+}
+
+VERTEX* AcisTopologyTool::new_vert_from_pos(const SPAposition &pos)
+{
+  APOINT *p = new APOINT(pos);
+  return new VERTEX(p);
+}
+
+CubitStatus AcisTopologyTool::generate_faces_for_lateral_edge(FACE *&face, EDGE *edge,
+                                              double &backoff_distance, 
+                                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                              DLIList<VERTEX*> &processed_verts,
+                                              DLIList<EDGE*> &processed_edges,
+                                              DLIList<EDGE*> &edges_to_imprint,
+                                              DLIList<FACE*> &new_vol_faces,
+                                              DLIList<FACE*> &dead_faces,
+                                              DLIList<SPAposition> &projected_positions)
+{
+  CubitStatus ret = CUBIT_SUCCESS;
+  int i;
+  int d, num_divisions = 5;
+  double start, end;
+  DLIList<EDGE*> new_face_edges;
+  DLIList<VERTEX*> edge_verts;
+  ENTITY *new_entity;
+  ENTITY *new_ent;
+  SPAunit_vector cur_dir, other_dir;
+  EDGE *next_edge;
+  VERTEX *next_vert;
+  DLIList<VERTEX*> split_verts;
+
+  processed_edges.append(edge);
+  // Put these in the list manually to make sure we go from the 
+  // beginning of the edge to the end.  This is the direction
+  // we assume below when stepping along the edge generating
+  // points for the slitting curve.
+  edge_verts.append(edge->start());
+  edge_verts.append(edge->end());
+  // Add the new edge corresponding to this old edge to the list of
+  // edges that will make up the new face.
+  api_copy_entity_contents((ENTITY*)old_edge_to_new_edge_map[edge], new_entity);
+  new_face_edges.append((EDGE*)new_entity);
+  // Make sure we do the start vertex first.
+  edge_verts.reset();
+  for(i=edge_verts.size(); i && ret == CUBIT_SUCCESS; i--)
+  {
+    VERTEX *vert = edge_verts.get_and_step();
+    EDGE *side_edge = NULL;
+    // Build any extra faces that are needed
+    // at the vertex
+    if(!processed_verts.is_in_list(vert))
+    {
+      get_next_edge_around_clump(edge, vert, face, 
+                    old_vertex_to_clump_map, next_edge, next_vert);
+      if(next_edge && next_vert)
+      {
+        double angle = this->angle_between(face, edge, vert, next_edge, next_vert);
+        if(!is_lateral_edge(next_edge, old_edge_to_new_edge_map))
+        {
+          processed_edges.append(next_edge);
+          processed_verts.append(vert);
+          if(angle <= three_pi_over_four)
+          {
+            // Just use the split point on the next edge
+            // to finish off this new face.
+            SPAposition other_vert_pos = other_vertex(next_edge, next_vert)->geometry()->coords();
+            VERTEXClump *clump = old_vertex_to_clump_map[vert];
+            VERTEX *vert1 = new_vert_from_pos(other_vert_pos);
+            VERTEX *vert2 = new_vert_from_pos(clump->new_vert->geometry()->coords());
+            STRAIGHT *s = new STRAIGHT(vert1->geometry()->coords(), normalise(vert2->geometry()->coords() - vert1->geometry()->coords()));
+            side_edge = new EDGE(vert1, vert2, s, FORWARD);
+            split_verts.append(vert1);
+          }
+          else if(angle <= five_pi_over_four)
+          {
+            // Introduce one extra face in addition to
+            // the new face we are constructing.  This will require making
+            // 3 new edges.  This will require projecting two new positions
+            // into the face.
+            VERTEX *vert1, *vert2, *vert3, *vert4;
+            EDGE *new_edge1, *new_edge2=NULL, *new_edge3=NULL, *new_edge4;
+            SPAposition new_pos1, new_pos2, split_pos_on_surf, tmp_pos;
+
+            SPAposition other_vert_pos = other_vertex(next_edge, next_vert)->geometry()->coords();
+            // Make the first new edge.  This will be the edge going into the
+            // current face and separating the new face associated with the 
+            // lateral (current) edge and the new face next to it linking up to the 
+            // non-lateral edge.
+            tangent_indir(face, edge, vert->geometry()->coords(), cur_dir); 
+            tangent_indir(face, next_edge, next_vert->geometry()->coords(), other_dir); 
+            SPAvector ave_dir = cur_dir + other_dir;
+            SPAvector ave_dir_norm = normalise(ave_dir);
+            angle /= 2.0;
+            double distance = backoff_distance/sin(angle);
+            tmp_pos = vert->geometry()->coords() + distance * ave_dir_norm;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos1);
+            // Now that we have the location of the new position projected into
+            // the face we will create the first new edge.
+            vert1 = new_vert_from_pos(new_pos1);
+            vert2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+            STRAIGHT *s = new STRAIGHT(vert1->geometry()->coords(), normalise(vert2->geometry()->coords() - vert1->geometry()->coords()));
+            new_edge1 = new EDGE(vert1, vert2, s, FORWARD);
+            // Create a new split edge associated with this new edge.  It will be used below for
+            // building the new face associated with the lateral (current) edge.
+            add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+            api_copy_entity_contents((ENTITY*)new_edge1, new_ent);
+            side_edge = (EDGE*)new_ent;
+            api_copy_entity_contents((ENTITY*)vert1, new_ent);
+            split_verts.append((VERTEX*)new_ent);
+            // Now create the second new edge we will need.  This will be an edge projected
+            // into the face from the split position on the non-lateral edge. We won't create 
+            // a split associated with it because it should never need to be retrieved later
+            // since we are processing the non-lateral edge at this time.
+            tangent_indir(face, next_edge, other_vert_pos, other_dir); 
+            tmp_pos = other_vert_pos + backoff_distance*other_dir;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos2);
+            vert3 = new_vert_from_pos(new_pos2);
+            vert4 = new_vert_from_pos(other_vert_pos);
+            new_edge2 = imprint_new_edge_on_face(face, vert3, vert4);
+            if(!new_edge2)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge2, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge2, new_ent);
+              new_edge2 = (EDGE*)new_ent;
+              // Now create the third new edge which will connect the two new edges we
+              // just created.
+              new_edge3 = imprint_new_edge_on_face(face, vert1, vert3);
+              if(!new_edge3)
+                ret = CUBIT_FAILURE;
+              else
+              {
+                face = this->find_keep_face(new_edge3, vert, dead_faces);
+                if(!face)
+                  ret = CUBIT_FAILURE;
+                else
+                {
+                  add_named_att((ENTITY*)new_edge3, "REMOVE_EDGE");
+                  api_copy_entity_contents((ENTITY*)new_edge3, new_ent);
+                  new_edge3 = (EDGE*)new_ent;
+                  VERTEX *tmp_vert1 = new_vert_from_pos(other_vert_pos);
+                  VERTEX *tmp_vert2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+                  s = new STRAIGHT(tmp_vert1->geometry()->coords(), normalise(tmp_vert2->geometry()->coords() - tmp_vert1->geometry()->coords()));
+                  new_edge4 = new EDGE(tmp_vert1, tmp_vert2, s, FORWARD);
+
+                  if(new_edge1 && new_edge2 && new_edge3 && new_edge4)
+                  {
+                    DLIList<EDGE*> edge_list;
+                    edge_list.append(new_edge1);
+                    edge_list.append(new_edge3);
+                    edge_list.append(new_edge2);
+                    edge_list.append(new_edge4);
+                    FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edge_list) ;
+                    if(FACE_ptr)
+                    {
+                      new_vol_faces.append(FACE_ptr);
+                      projected_positions.append(new_pos1);
+                      projected_positions.append(new_pos2);
+                    }
+                    else
+                    {
+                      PRINT_ERROR("Failed to build face from bounding curves.\n");
+                      ret = CUBIT_FAILURE;
+                    }
+                  }
+                  else
+                  {
+                    PRINT_ERROR("Failed to get all of the new edges needed for new face.\n");
+                    ret = CUBIT_FAILURE;
+                  }
+                }
+              }
+            }
+          }
+          else if(angle <= seven_pi_over_four)
+          {
+            // Introduce two extra faces in addition to
+            // the new face we are constructing.  
+            VERTEX *vert1, *vert2;
+            EDGE *new_edge1, *new_edge2, *new_edge3, *new_edge4;
+            EDGE *new_edge5, *new_edge6, *new_edge7, *new_edge8;
+            SPAposition new_pos1, new_pos2, new_pos3, new_pos4, tmp_pos;
+
+            SPAposition next_other_pos = other_vertex(next_edge, next_vert)->geometry()->coords();
+            // Make the first new edge.  This will be the edge going into the
+            // current face and separating the new face associated with the 
+            // lateral (current) edge and the new face next to it linking up to the 
+            // non-lateral edge.
+            SPAunit_vector cur_in_dir, next_in_dir, next_other_in_dir;
+            tangent_indir(face, edge, vert->geometry()->coords(), cur_in_dir); 
+            tangent_indir(face, next_edge, next_vert->geometry()->coords(), next_in_dir); 
+            tangent_indir(face, next_edge, next_other_pos, next_other_in_dir); 
+            SPAunit_vector ave_dir = normalise(cur_in_dir + next_in_dir);
+            angle /= 2.0;
+            double distance = backoff_distance/sin(angle);
+            SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                                (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                                (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+            // Create the 4 new positions needed.
+            tmp_pos = mid_pos + distance * ave_dir;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos1);
+            tmp_pos = vert->geometry()->coords() + backoff_distance * cur_in_dir;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos2);
+            tmp_pos = next_vert->geometry()->coords() + backoff_distance * next_in_dir;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos3);
+            tmp_pos = next_other_pos + backoff_distance * next_other_in_dir;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos4);
+
+            // Create the edge that will close off the face associated with the lateral
+            // edge.
+            vert1 = new_vert_from_pos(new_pos2);
+            vert2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+            STRAIGHT *s = new STRAIGHT(vert1->geometry()->coords(), normalise(vert2->geometry()->coords() - vert1->geometry()->coords()));
+            new_edge1 = new EDGE(vert1, vert2, s, FORWARD);
+            add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+            // Make a copy of this edge.  It will be used below for
+            // building the new face associated with the lateral (current) edge.
+            api_copy_entity_contents((ENTITY*)new_edge1, new_ent);
+            side_edge = (EDGE*)new_ent;
+            // Keep track of this vertex.
+            api_copy_entity_contents((ENTITY*)vert1, new_ent);
+            split_verts.append((VERTEX*)new_ent);
+            // Create next new edge.
+            vert1 = new_vert_from_pos(new_pos3);
+            vert2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+            s = new STRAIGHT(vert1->geometry()->coords(), normalise(vert2->geometry()->coords() - vert1->geometry()->coords()));
+            new_edge2 = new EDGE(vert1, vert2, s, FORWARD);
+            if(!new_edge2)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge2, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge2, new_ent);
+              new_edge3 = (EDGE*)new_ent;
+              // Create next edge.
+              vert1 = new_vert_from_pos(new_pos4);
+              vert2 = new_vert_from_pos(next_other_pos);
+              new_edge4 = imprint_new_edge_on_face(face, vert1, vert2);
+              if(!new_edge4)
+                ret = CUBIT_FAILURE;
+              else
+              {
+                add_named_att((ENTITY*)new_edge4, "REMOVE_EDGE");
+                api_copy_entity_contents((ENTITY*)new_edge4, new_ent);
+                new_edge4 = (EDGE*)new_ent;
+                vert1 = new_vert_from_pos(new_pos4);
+                vert2 = new_vert_from_pos(new_pos3);
+                new_edge5 = imprint_new_edge_on_face(face, vert1, vert2);
+                if(!new_edge5)
+                  ret = CUBIT_FAILURE;
+                else
+                {
+                  face = this->find_keep_face(new_edge5, next_vert, dead_faces);
+                  if(!face)
+                    ret = CUBIT_FAILURE;
+                  else
+                  {
+                    add_named_att((ENTITY*)new_edge5, "REMOVE_EDGE");
+                    api_copy_entity_contents((ENTITY*)new_edge5, new_ent);
+                    new_edge5 = (EDGE*)new_ent;
+                    vert1 = new_vert_from_pos(new_pos1);
+                    vert2 = new_vert_from_pos(new_pos3);
+                    new_edge6 = imprint_new_edge_on_face(face, vert1, vert2);
+                    if(!new_edge6)
+                      ret = CUBIT_FAILURE;
+                    else
+                    {
+                      face = this->find_keep_face(new_edge6, vert, dead_faces);
+                      if(!face)
+                        ret = CUBIT_FAILURE;
+                      else
+                      {
+                        add_named_att((ENTITY*)new_edge6, "REMOVE_EDGE");
+                        api_copy_entity_contents((ENTITY*)new_edge6, new_ent);
+                        new_edge6 = (EDGE*)new_ent;
+                        vert1 = new_vert_from_pos(new_pos1);
+                        vert2 = new_vert_from_pos(new_pos2);
+                        new_edge7 = imprint_new_edge_on_face(face, vert1, vert2);
+                        if(!new_edge7)
+                          ret = CUBIT_FAILURE;
+                        else
+                        {
+                          face = this->find_keep_face(new_edge7, vert, dead_faces);
+                          if(!face)
+                            ret = CUBIT_FAILURE;
+                          else
+                          {
+                            add_named_att((ENTITY*)new_edge7, "REMOVE_EDGE");
+                            api_copy_entity_contents((ENTITY*)new_edge7, new_ent);
+                            new_edge7 = (EDGE*)new_ent;
+                            vert1 = new_vert_from_pos(next_other_pos);
+                            vert2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+                            s = new STRAIGHT(vert1->geometry()->coords(), normalise(vert2->geometry()->coords() - vert1->geometry()->coords()));
+                            new_edge8 = new EDGE(vert1, vert2, s, FORWARD);
+                            if(!new_edge8)
+                              ret = CUBIT_FAILURE;
+                            else
+                            {
+                              if(new_edge4 && new_edge8 && new_edge5 && new_edge2)
+                              {
+                                DLIList<EDGE*> edge_list;
+                                edge_list.append(new_edge2);
+                                edge_list.append(new_edge5);
+                                edge_list.append(new_edge8);
+                                edge_list.append(new_edge4);
+                                FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edge_list) ;
+                                if(FACE_ptr)
+                                {
+                                  new_vol_faces.append(FACE_ptr);
+                                  projected_positions.append(new_pos3);
+                                  projected_positions.append(new_pos4);
+                                  if(new_edge3 && new_edge6 && new_edge7 && new_edge1)
+                                  {
+                                    DLIList<EDGE*> edge_list;
+                                    edge_list.append(new_edge3);
+                                    edge_list.append(new_edge6);
+                                    edge_list.append(new_edge7);
+                                    edge_list.append(new_edge1);
+                                    FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edge_list) ;
+                                    if(FACE_ptr)
+                                    {
+                                      new_vol_faces.append(FACE_ptr);
+                                      projected_positions.append(new_pos1);
+                                      projected_positions.append(new_pos2);
+                                    }
+                                    else
+                                    {
+                                      PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                      ret = CUBIT_FAILURE;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    PRINT_ERROR("Failed to get all of the new edges needed for new face.\n");
+                                    ret = CUBIT_FAILURE;
+                                  }
+                                }
+                                else
+                                {
+                                  PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                  ret = CUBIT_FAILURE;
+                                }
+                              }
+                              else
+                              {
+                                PRINT_ERROR("Failed to get all of the new edges needed for new face.\n");
+                                ret = CUBIT_FAILURE;
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+          else
+          {
+            // Add 4 new faces.
+            EDGE *new_edge1, *new_edge3, *new_edge4, *new_edge5;
+            EDGE *new_edge6, *new_edge8, *new_edge10, *new_edge11, *new_edge12;
+            EDGE *new_edge13, *new_edge14, *new_edge16;
+            SPAposition new_pos1, new_pos2, new_pos3, new_pos4, new_pos5, new_pos6;
+
+            SPAposition next_other_pos = other_vertex(next_edge, next_vert)->geometry()->coords();
+            SPAposition cur_other_vert_pos = other_vertex(edge, vert)->geometry()->coords();
+            // Project from the current vert into the face at an average direction.
+            SPAunit_vector cur_in_dir, next_in_dir, next_other_in_dir, mid_dir;
+            SPAunit_vector cur_mid_dir, next_mid_dir;
+            tangent_indir(face, edge, vert->geometry()->coords(), cur_in_dir); 
+            tangent_indir(face, next_edge, next_vert->geometry()->coords(), next_in_dir); 
+            tangent_indir(face, next_edge, next_other_pos, next_other_in_dir); 
+            mid_dir = normalise(normalise(next_vert->geometry()->coords() - next_other_pos) + 
+              normalise(vert->geometry()->coords() - cur_other_vert_pos));
+            cur_mid_dir = normalise(mid_dir + cur_in_dir);
+            next_mid_dir = normalise(mid_dir + next_in_dir);
+            SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                                (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                                (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+
+            VERTEX *clump_vert = old_vertex_to_clump_map[vert]->new_vert;
+            double distance = backoff_distance;
+            SPAposition tmp_pos = mid_pos + distance * mid_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+            int cntr = 0;
+            point_face_containment containment;
+            api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+            // Try to make sure we have a point on the face.
+            while(containment == point_boundary_face && cntr++ < 10)
+            {
+              distance = (clump_vert->geometry()->coords()-new_pos1).len() / 2.0;
+              tmp_pos = mid_pos + distance * mid_dir;
+              api_find_cls_ptto_face(tmp_pos, face, new_pos1);
+              api_point_in_face(new_pos1, face, *(SPAtransf*)NULL_REF, containment); 
+            }
+
+            distance = sqrt(2.0)*backoff_distance;
+            tmp_pos = vert->geometry()->coords() + distance*cur_mid_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+            cntr = 0;
+            api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+            while(containment == point_boundary_face && cntr++ < 10)
+            {
+              distance = (clump_vert->geometry()->coords()-new_pos2).len() / 2.0;
+              tmp_pos = vert->geometry()->coords() + distance*cur_mid_dir;
+              api_find_cls_ptto_face(tmp_pos, face, new_pos2);
+              api_point_in_face(new_pos2, face, *(SPAtransf*)NULL_REF, containment); 
+            }
+
+            distance = sqrt(2.0)*backoff_distance;
+            tmp_pos = next_vert->geometry()->coords() + distance*next_mid_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+            cntr = 0;
+            api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+            while(containment == point_boundary_face && cntr++ < 10)
+            {
+              distance = (clump_vert->geometry()->coords()-new_pos3).len() / 2.0;
+              tmp_pos = next_vert->geometry()->coords() + distance*next_mid_dir;
+              api_find_cls_ptto_face(tmp_pos, face, new_pos3);
+              api_point_in_face(new_pos3, face, *(SPAtransf*)NULL_REF, containment); 
+            }
+
+            distance = backoff_distance;
+            tmp_pos = vert->geometry()->coords() + distance*cur_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos4);
+            cntr = 0;
+            api_point_in_face(new_pos4, face, *(SPAtransf*)NULL_REF, containment); 
+            while(containment == point_boundary_face && cntr++ < 10)
+            {
+              distance = (vert->geometry()->coords()-new_pos4).len() / 2.0;
+              tmp_pos = vert->geometry()->coords() + distance*cur_in_dir;
+              api_find_cls_ptto_face(tmp_pos, face, new_pos4);
+              api_point_in_face(new_pos4, face, *(SPAtransf*)NULL_REF, containment); 
+            }
+
+            distance = backoff_distance;
+            tmp_pos = next_vert->geometry()->coords() + distance*next_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos5);
+            cntr = 0;
+            api_point_in_face(new_pos5, face, *(SPAtransf*)NULL_REF, containment); 
+            while(containment == point_boundary_face && cntr++ < 10)
+            {
+              distance = (next_vert->geometry()->coords()-new_pos5).len() / 2.0;
+              tmp_pos = next_vert->geometry()->coords() + distance*next_in_dir;
+              api_find_cls_ptto_face(tmp_pos, face, new_pos5);
+              api_point_in_face(new_pos5, face, *(SPAtransf*)NULL_REF, containment); 
+            }
+
+            distance = backoff_distance;
+            tmp_pos = next_other_pos + distance*next_other_in_dir;
+            api_find_cls_ptto_face(tmp_pos, face, new_pos6);
+            cntr = 0;
+            api_point_in_face(new_pos6, face, *(SPAtransf*)NULL_REF, containment); 
+            while(containment == point_boundary_face && cntr++ < 10)
+            {
+              distance = (next_other_pos-new_pos6).len() / 2.0;
+              tmp_pos = next_other_pos + distance*next_other_in_dir;
+              api_find_cls_ptto_face(tmp_pos, face, new_pos6);
+              api_point_in_face(new_pos6, face, *(SPAtransf*)NULL_REF, containment); 
+            }
+
+            // Create the edge going from the new clump vert to new_pos4.
+            VERTEX *v1 = new_vert_from_pos(new_pos4);
+            // Keep track of this vertex.
+            api_copy_entity_contents((ENTITY*)v1, new_ent);
+            split_verts.append((VERTEX*)new_ent);
+            VERTEX *v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+            STRAIGHT *s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+            new_edge1 = new EDGE(v1, v2, s, FORWARD);
+            add_named_att((ENTITY*)new_edge1, "REMOVE_EDGE");
+            // Make another copy of this.
+            api_copy_entity_contents((ENTITY*)new_edge1, new_ent);
+            side_edge = (EDGE*)new_ent;
+            // Create the edge going from the new clump vert to new_pos1.
+            v1 = new_vert_from_pos(new_pos1);
+            v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+            s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+            new_edge3 = new EDGE(v1, v2, s, FORWARD);
+            add_named_att((ENTITY*)new_edge3, "REMOVE_EDGE");
+            // Make another copy of this.
+            api_copy_entity_contents((ENTITY*)new_edge3, new_ent);
+            new_edge4 = (EDGE*)new_ent;
+            // Create the edge going from the new clump vert to new_pos5.
+            v1 = new_vert_from_pos(new_pos5);
+            v2 = new_vert_from_pos(clump_vert->geometry()->coords());
+            s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+            new_edge5 = new EDGE(v1, v2, s, FORWARD);
+            add_named_att((ENTITY*)new_edge5, "REMOVE_EDGE");
+            // Make another copy of this.
+            api_copy_entity_contents((ENTITY*)new_edge5, new_ent);
+            new_edge6 = (EDGE*)new_ent;
+
+            // Create the edge going from the next split to new_pos6.
+            v1 = new_vert_from_pos(new_pos6);
+            v2 = new_vert_from_pos(next_other_pos);
+            new_edge8 = imprint_new_edge_on_face(face, v1, v2);
+            if(!new_edge8)
+              ret = CUBIT_FAILURE;
+            else
+            {
+              add_named_att((ENTITY*)new_edge8, "REMOVE_EDGE");
+              api_copy_entity_contents((ENTITY*)new_edge8, new_ent);
+              new_edge8 = (EDGE*)new_ent;
+              // Create the edge going from new_pos2 to new_pos4.
+              v1 = new_vert_from_pos(new_pos2);
+              v2 = new_vert_from_pos(new_pos4);
+              new_edge10 = imprint_new_edge_on_face(face, v1, v2);
+              if(!new_edge10)
+                ret = CUBIT_FAILURE;
+              else
+              {
+                add_named_att((ENTITY*)new_edge10, "REMOVE_EDGE");
+                api_copy_entity_contents((ENTITY*)new_edge10, new_ent);
+                new_edge10 = (EDGE*)new_ent;
+                // Create the edge going from new_pos1 to new_pos2.
+                v1 = new_vert_from_pos(new_pos1);
+                v2 = new_vert_from_pos(new_pos2);
+                new_edge11 = imprint_new_edge_on_face(face, v1, v2);
+                if(!new_edge11)
+                  ret = CUBIT_FAILURE;
+                else
+                {
+                  face = this->find_keep_face(new_edge11, vert, dead_faces);
+                  if(!face)
+                    ret = CUBIT_FAILURE;
+                  else
+                  {
+                    add_named_att((ENTITY*)new_edge11, "REMOVE_EDGE");
+                    api_copy_entity_contents((ENTITY*)new_edge11, new_ent);
+                    new_edge11 = (EDGE*)new_ent;
+                    // Create the edge going from new_pos1 to new_pos3.
+                    v1 = new_vert_from_pos(new_pos1);
+                    v2 = new_vert_from_pos(new_pos3);
+                    new_edge12 = imprint_new_edge_on_face(face, v1, v2);
+                    if(!new_edge12)
+                      ret = CUBIT_FAILURE;
+                    else
+                    {
+                      add_named_att((ENTITY*)new_edge12, "REMOVE_EDGE");
+                      api_copy_entity_contents((ENTITY*)new_edge12, new_ent);
+                      new_edge12 = (EDGE*)new_ent;
+                      // Create the edge going from new_pos3 to new_pos5.
+                      v1 = new_vert_from_pos(new_pos3);
+                      v2 = new_vert_from_pos(new_pos5);
+                      new_edge13 = imprint_new_edge_on_face(face, v1, v2);
+                      if(!new_edge13)
+                        ret = CUBIT_FAILURE;
+                      else
+                      {
+                        face = this->find_keep_face(new_edge13, next_vert, dead_faces);
+                        if(!face)
+                          ret = CUBIT_FAILURE;
+                        else
+                        {
+                          add_named_att((ENTITY*)new_edge13, "REMOVE_EDGE");
+                          api_copy_entity_contents((ENTITY*)new_edge13, new_ent);
+                          new_edge13 = (EDGE*)new_ent;
+                          // Create the edge going from new_pos6 to new_pos5.
+                          v1 = new_vert_from_pos(new_pos6);
+                          v2 = new_vert_from_pos(new_pos5);
+                          new_edge14 = imprint_new_edge_on_face(face, v1, v2);
+                          if(!new_edge14)
+                            ret = CUBIT_FAILURE;
+                          else
+                          {
+                            face = this->find_keep_face(new_edge14, next_vert, dead_faces);
+                            if(!face)
+                              ret = CUBIT_FAILURE;
+                            else
+                            {
+                              add_named_att((ENTITY*)new_edge14, "REMOVE_EDGE");
+                              api_copy_entity_contents((ENTITY*)new_edge14, new_ent);
+                              new_edge14 = (EDGE*)new_ent;
+                              v1 = new_vert_from_pos(next_other_pos);
+                              v2 = new_vert_from_pos(old_vertex_to_clump_map[next_vert]->new_vert->geometry()->coords());
+                              s = new STRAIGHT(v1->geometry()->coords(), normalise(v2->geometry()->coords() - v1->geometry()->coords()));
+                              new_edge16 = new EDGE(v1, v2, s, FORWARD);
+                              if(new_edge1 && new_edge3 && new_edge10 && new_edge11)
+                              {
+                                // Now create the new face.
+                                DLIList<EDGE*> edges_for_new_face;
+                                edges_for_new_face.append(new_edge1);
+                                edges_for_new_face.append(new_edge3);
+                                edges_for_new_face.append(new_edge10);
+                                edges_for_new_face.append(new_edge11);
+                                FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                if(FACE_ptr)
+                                {
+                                  new_vol_faces.append(FACE_ptr);
+                                  projected_positions.append(new_pos2);
+                                  projected_positions.append(new_pos1);
+                                  if(new_edge4 && new_edge5 && new_edge12 && new_edge13)
+                                  {
+                                    // Now create the new face.
+                                    DLIList<EDGE*> edges_for_new_face;
+                                    edges_for_new_face.append(new_edge4);
+                                    edges_for_new_face.append(new_edge5);
+                                    edges_for_new_face.append(new_edge12);
+                                    edges_for_new_face.append(new_edge13);
+                                    FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                    if(FACE_ptr)
+                                    {
+                                      new_vol_faces.append(FACE_ptr);
+                                      projected_positions.append(new_pos3);
+                                      projected_positions.append(new_pos5);
+                                      if(new_edge6 && new_edge8 && new_edge14 && new_edge16)
+                                      {
+                                        // Now create the new face.
+                                        DLIList<EDGE*> edges_for_new_face;
+                                        edges_for_new_face.append(new_edge6);
+                                        edges_for_new_face.append(new_edge8);
+                                        edges_for_new_face.append(new_edge14);
+                                        edges_for_new_face.append(new_edge16);
+                                        FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, edges_for_new_face);
+                                        if(FACE_ptr)
+                                        {
+                                          new_vol_faces.append(FACE_ptr);
+                                          projected_positions.append(new_pos6);
+                                        }
+                                        else
+                                        {
+                                          PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                          ret = CUBIT_FAILURE;
+                                        }
+                                      }
+                                      else
+                                      {
+                                        PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                        ret = CUBIT_FAILURE;
+                                      }
+                                    }
+                                    else
+                                    {
+                                      PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                      ret = CUBIT_FAILURE;
+                                    }
+                                  }
+                                  else
+                                  {
+                                    PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                    ret = CUBIT_FAILURE;
+                                  }
+                                }
+                                else
+                                {
+                                  PRINT_ERROR("Failed to build face from bounding curves.\n");
+                                  ret = CUBIT_FAILURE;
+                                }
+                              }
+                              else
+                              {
+                                PRINT_ERROR("Failed to get all of the required edges for a new face.\n");
+                                ret = CUBIT_FAILURE;
+                              }
+                            }
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        else
+        {
+          if(angle <= seven_pi_over_four)
+          {
+            // Introduce one edge to separate this new
+            // face with the one that will be created 
+            // for the next lateral edge.
+            VERTEX *vert1, *vert2;
+            EDGE *new_edge1;
+            SPAposition new_pos1;
+            // Make the first new edge.  This will be the edge going into the
+            // current face and separating the new face associated with this 
+            // lateral (current) edge and the face associated with the adjacent
+            // lateral edge.
+            SPAposition mid_pos((vert->geometry()->coords().x() + next_vert->geometry()->coords().x())/2.0,
+                                (vert->geometry()->coords().y() + next_vert->geometry()->coords().y())/2.0,
+                                (vert->geometry()->coords().z() + next_vert->geometry()->coords().z())/2.0);
+            tangent_indir(face, edge, vert->geometry()->coords(), cur_dir); 
+            tangent_indir(face, next_edge, next_vert->geometry()->coords(), other_dir); 
+            SPAvector ave_dir = cur_dir + other_dir;
+            SPAvector ave_dir_norm = normalise(ave_dir);
+            angle /= 2.0;
+            double distance = backoff_distance/sin(angle);
+            SPAposition tmp_pos = mid_pos + distance * ave_dir_norm;
+            face->geometry()->equation().point_perp(tmp_pos, new_pos1);
+            // Now that we have the location of the new position projected into
+            // the face we will create the first new edge.
+            vert1 = new_vert_from_pos(new_pos1);
+            vert2 = new_vert_from_pos(old_vertex_to_clump_map[vert]->new_vert->geometry()->coords());
+            STRAIGHT *s = new STRAIGHT(vert1->geometry()->coords(), normalise(vert2->geometry()->coords() - vert1->geometry()->coords()));
+            new_edge1 = new EDGE(vert1, vert2, s, FORWARD);
+            // Create a new split edge associated with this new edge.  It will be retrieved later for
+            // processing the adjacent lateral edge.
+            side_edge = new_edge1;
+            add_named_att((ENTITY*)side_edge, "REMOVE_EDGE");
+            split_verts.append(vert1);
+            projected_positions.append(new_pos1);
+          }
+          else
+          {
+            // Introduce three edges and two extra faces
+            // to separate this new
+            // face with the one that will be created 
+            // for the next lateral edge.
+            PRINT_ERROR("Unhandled angle on adjacent face.\n");
+            ret = CUBIT_FAILURE;
+          }
+        }
+      }
+      else
+        ret = CUBIT_FAILURE;
+    }
+    if(side_edge)
+    {
+      new_face_edges.append(side_edge);
+    }
+  }
+  if(ret == CUBIT_SUCCESS)
+  {
+    // Make sure we have 2 split positions.
+    if(split_verts.size() != 2)
+    {
+      PRINT_ERROR("Problem finding new positions for building new topology.\n");
+      ret = CUBIT_FAILURE;
+    }
+    else
+    {
+      // Start with the split position at the start of the edge.
+      // We want to build a list of points used to split the surface.
+      split_verts.reset();
+
+      int num_in_array = 2;
+      SPAposition *pos_array = NULL;
+      // Check to see if the curve is basically a straight line.  If it
+      // is we will just need the end points of the splitting curve.
+      // Otherwise we need to step along the curve and generate points
+      // to be used in generating the splitting curve.
+      if(edge->geometry()->equation().type() != straight_type && 
+        !this->is_roughly_straight_curve_wrt_surf(edge, face))
+      {
+        num_in_array += num_divisions-1;
+        pos_array = new SPAposition[num_in_array];
+        SPAposition pos;
+        SPAinterval range = edge->param_range();
+        if(edge->sense() == REVERSED)
+          range.negate();
+        start = range.start_pt();
+        end = range.end_pt();
+        double dt = (end-start)/(double)num_divisions;
+        double cur_t = start + dt;
+        for(d=1; d<num_divisions; d++)
+        {
+          edge->geometry()->equation().eval(cur_t, pos);
+          tangent_indir(face, edge, pos, cur_dir); 
+          pos += backoff_distance * cur_dir;
+          SPAposition clos;
+          face->geometry()->equation().point_perp(pos, clos);
+          pos_array[d] = clos;
+          cur_t += dt;
+        }
+        pos_array[0] = split_verts.get()->geometry()->coords();
+        pos_array[num_in_array-1] = split_verts.next()->geometry()->coords();
+      }
+
+      EDGE *split_edge = NULL;
+      if(num_in_array == 2)
+      {
+        split_edge = imprint_new_edge_on_face(face, split_verts.get(), split_verts.next());
+        if(!split_edge)
+        {
+          PRINT_WARNING("Failed to imprint curve on surface.\n"
+            "Re-trying with a more accurate curve.\n");
+          num_in_array += num_divisions-1;
+          pos_array = new SPAposition[num_in_array];
+          SPAposition pos;
+          SPAinterval range = edge->param_range();
+          if(edge->sense() == REVERSED)
+            range.negate();
+          start = range.start_pt();
+          end = range.end_pt();
+          double dt = (end-start)/(double)num_divisions;
+          double cur_t = start + dt;
+          for(d=1; d<num_divisions; d++)
+          {
+            edge->geometry()->equation().eval(cur_t, pos);
+            tangent_indir(face, edge, pos, cur_dir); 
+            pos += backoff_distance * cur_dir;
+            SPAposition clos;
+            face->geometry()->equation().point_perp(pos, clos);
+            pos_array[d] = clos;
+            cur_t += dt;
+          }
+          pos_array[0] = split_verts.get()->geometry()->coords();
+          pos_array[num_in_array-1] = split_verts.next()->geometry()->coords();
+        }
+      }
+      if(!split_edge && num_in_array > 2)
+      {
+        EDGE *new_edge = NULL;
+        api_curve_spline(num_in_array, pos_array, NULL, NULL, new_edge);
+        if(face->geometry()->equation().type() != plane_type)
+          new_edge = AcisModifyEngine::instance()->project_EDGE(new_edge, face, 0);
+        ENTITY *body;
+        api_get_owner((ENTITY*)face, body);
+        ENTITY_LIST face_edges_before;
+        api_get_edges((ENTITY*)face, face_edges_before);
+        DLIList<TopologyBridge*> temporary_bridges;
+        AcisModifyEngine::instance()->imprint((BODY*)body, face, new_edge, temporary_bridges);
+        temporary_bridges.uniquify_ordered();
+        while(temporary_bridges.size())
+          delete temporary_bridges.pop();
+        ENTITY_LIST face_edges_after;
+        api_get_edges((ENTITY*)face, face_edges_after);
+        face_edges_after.remove(face_edges_before);
+        if(face_edges_after.iteration_count() == 1)
+        {
+          face_edges_after.init();
+          split_edge = (EDGE*)face_edges_after.next();
+        }
+      }
+      if(pos_array)
+        delete [] pos_array;
+
+      if(!split_edge)
+      {
+        PRINT_ERROR("Failed to find curve to use in splitting face.\n");
+        ret = CUBIT_FAILURE;
+      }
+      else
+      {
+        ENTITY_LIST edge_faces;
+        api_get_faces((ENTITY*)split_edge, edge_faces);
+        if(edge_faces.count() == 2)
+        {
+          edge_faces.init();
+          FACE *f1 = (FACE*)edge_faces.next();
+          ENTITY_LIST tmp_edges;
+          api_get_edges((ENTITY*)f1, tmp_edges);
+          FACE *face_to_remove;
+          if(tmp_edges.lookup(edge) != -1)
+          {
+            face = (FACE*)edge_faces.next();
+            face_to_remove = f1;
+          }
+          else
+          {
+            face = f1;
+            face_to_remove = (FACE*)edge_faces.next();
+          }
+          dead_faces.append(face_to_remove);
+        }
+        if(split_edge)
+        {
+          add_named_att((ENTITY*)split_edge, "REMOVE_EDGE");
+          api_copy_entity_contents((ENTITY*)split_edge, new_ent);
+          split_edge = (EDGE*)new_ent;
+          new_face_edges.append(split_edge);
+        }
+        else
+        {
+          PRINT_ERROR("Failed to find curve to use in splitting face.\n");
+          ret = CUBIT_FAILURE;
+        }
+        if(ret == CUBIT_SUCCESS)
+        {
+          // Clean up memory.
+          if(new_face_edges.size() == 4)
+          {
+            FACE* FACE_ptr = AcisModifyEngine::instance()->make_FACE(PLANE_SURFACE_TYPE, new_face_edges);
+            if(FACE_ptr)
+              new_vol_faces.append(FACE_ptr);
+            else
+            {
+              PRINT_ERROR("Failed to build face from bounding curves.\n");
+              ret = CUBIT_FAILURE;
+            }
+          }
+          else
+            PRINT_ERROR("Unexpected number of edges for new face.\n");
+        }
+      }
+    }
+  }
+  return ret;
+}
+
+int AcisTopologyTool::is_roughly_straight_curve_wrt_surf(EDGE *cur_edge, FACE *cur_face)
+{
+  SPAinterval range = cur_edge->geometry()->equation().param_range();
+  double start = range.start_pt();
+  double end = range.end_pt();
+  int num_divisions = 5;
+  double dt = (end-start)/(double)num_divisions;
+  double cur_t = start;
+  int i;
+  SPAunit_vector ref_dir;
+  SPAposition pos, clos;
+  SPAvector tan, cur_dir;
+  for(i=num_divisions+1; i--;)
+  {
+    cur_edge->geometry()->equation().eval(cur_t, pos, tan);
+    SPAunit_vector norm;
+    cur_face->geometry()->equation().point_perp(pos, clos, norm);
+    SPAunit_vector tan_norm = normalise(tan);
+    cur_dir = norm * tan_norm;
+    if(i == num_divisions)
+      ref_dir = normalise(cur_dir);
+    else
+    {
+      SPAunit_vector cur_normalized = normalise(cur_dir);
+      double dot = ref_dir % cur_normalized;
+      if(dot < .9)
+        return 0;
+    }
+    cur_t += dt;
+  }
+  return 1;
+}
+
+CubitStatus AcisTopologyTool::split_all_curves_coming_into_clumps(DLIList<VERTEXClump*> &clumps,
+                                                         std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                                         std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                                         double &backoff_distance,
+                                                         DLIList<SPAposition> &split_positions)
+{
+  int i, j;
+  for(i=clumps.size(); i--;)
+  {
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    for(j=cur_clump->verts.size(); j--;)
+    {
+      VERTEX *cur_vert = cur_clump->verts.get_and_step();
+      ENTITY_LIST vert_edges;
+      api_get_edges((ENTITY*)cur_vert, vert_edges);
+      ENTITY *tmp_ent;
+      vert_edges.init();
+      while((tmp_ent = vert_edges.next()))
+      {
+        EDGE *cur_edge = (EDGE*)tmp_ent;
+        if(!edge_within_clump(cur_edge, old_vertex_to_clump_map) && !old_edge_to_new_edge_map.count(cur_edge))
+        {
+          double param;
+          double len = cur_edge->length();
+          if(backoff_distance > 0.9*len)
+          {
+            PRINT_ERROR("Failed to back off from small topology a distance of %lf without\n"
+              "running into other topology.  One possible solution is to increase\n"
+              "the small curve size so that more topology is included in the topology\n"
+              "to be removed.\n", backoff_distance);
+            return CUBIT_FAILURE;
+          }
+          SPAinterval range = cur_edge->param_range();
+          int is_periodic = cur_edge->geometry()->equation().periodic();
+          if(cur_edge->sense() == REVERSED)
+            range.negate();
+          double start_param = range.start_pt();
+          double end_param = range.end_pt();
+          
+          double edge_param = cur_edge->geometry()->equation().param(cur_vert->geometry()->coords());
+          if(is_periodic)
+          {
+            double period = cur_edge->geometry()->equation().param_period();
+            while(edge_param < start_param - GEOMETRY_RESABS)
+              edge_param += period;
+            while(edge_param > end_param + GEOMETRY_RESABS)
+              edge_param -= period;
+          }
+          if(fabs(start_param-edge_param) < fabs(end_param-edge_param))
+            param = start_param + (end_param-start_param)*backoff_distance/len;
+          else
+            param = end_param + (start_param-end_param)*backoff_distance/len;
+          SPAposition pos;
+          cur_edge->geometry()->equation().eval(param, pos);
+          split_positions.append(pos);
+          APOINT *ap = new APOINT(pos);
+          VERTEX *v = new VERTEX(ap);
+          sg_split_edge_at_vertex(cur_edge, v);
+        }
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::adjust_backoff_distance(DLIList<VERTEXClump*> &clumps,
+                                                         std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                                                         std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                                         double &backoff_distance)
+{
+  int i, j;
+  for(i=clumps.size(); i--;)
+  {
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    for(j=cur_clump->verts.size(); j--;)
+    {
+      VERTEX *cur_vert = cur_clump->verts.get_and_step();
+      ENTITY_LIST vert_edges;
+      api_get_edges((ENTITY*)cur_vert, vert_edges);
+      ENTITY *tmp_ent;
+      vert_edges.init();
+      while((tmp_ent = vert_edges.next()))
+      {
+        EDGE *cur_edge = (EDGE*)tmp_ent;
+        if(!edge_within_clump(cur_edge, old_vertex_to_clump_map) && !old_edge_to_new_edge_map.count(cur_edge))
+        {
+          double len = cur_edge->length();
+          if(backoff_distance > 0.4*len)
+          {
+            backoff_distance = 0.4*len;
+            PRINT_WARNING("Changing backoff distance to %lf.\n", backoff_distance);
+          }
+        }
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::find_new_edges_between_clumps(DLIList<VERTEXClump*> &clumps,
+                                std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                                std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map)
+{
+  int i, j, k;
+  DLIList<VERTEXClump*> copy_of_clumps = clumps;
+
+  while(copy_of_clumps.size() > 1)
+  {
+    VERTEXClump *cur_clump = copy_of_clumps.extract();
+    DLIList<FACE*> *cur_clump_faces = surrounding_faces_map[cur_clump];
+    for(i=copy_of_clumps.size(); i--;)
+    {
+      VERTEXClump *other_clump = copy_of_clumps.get_and_step();
+      DLIList<EDGE*> common_edges;
+      for(j=cur_clump->verts.size(); j--;)
+      {
+        VERTEX *cur_vert = cur_clump->verts.get_and_step();
+        for(k=other_clump->verts.size(); k--;)
+        {
+          VERTEX *other_vert = other_clump->verts.get_and_step();
+          EDGE *common_edge = find_common_edge(cur_vert, other_vert);
+          if(common_edge)
+          {
+            ENTITY_LIST fs;
+            api_get_faces((ENTITY*)common_edge, fs);
+            ENTITY *tmp_ent;
+            fs.init();
+            int ok_to_proceed = 0;
+            while((tmp_ent = fs.next()) && !ok_to_proceed)
+            {
+              if(!cur_clump_faces->is_in_list((FACE*)tmp_ent))
+                ok_to_proceed = 1;
+            }
+
+            if(ok_to_proceed)
+              common_edges.append_unique(common_edge);
+          }
+        }
+      }
+      if(common_edges.size() > 0)
+      {
+        EDGE *new_edge = NULL;
+        int r;
+        int has_a_straight = 0;
+        for(r=common_edges.size(); r && !has_a_straight; r--)
+        {
+          EDGE *cur_com_edge = common_edges.get_and_step();
+          if(cur_com_edge->geometry()->equation().type() == straight_type)
+            has_a_straight = 1;
+        }
+        
+        if(has_a_straight)
+        {
+          APOINT *p1 = new APOINT(cur_clump->ave_pos);
+          APOINT *p2 = new APOINT(other_clump->ave_pos);
+          VERTEX *v1 = new VERTEX(p1);
+          VERTEX *v2 = new VERTEX(p2);
+          STRAIGHT *s = new STRAIGHT(cur_clump->ave_pos, normalise(other_clump->ave_pos - cur_clump->ave_pos));
+          new_edge = new EDGE(v1, v2, s, FORWARD);
+        }
+        else
+        {
+          DLIList<EDGE*> copy = common_edges;
+          EDGE *guide_edge = copy.get();
+          copy.move_to(guide_edge);
+          copy.extract();
+
+          SPAposition closest;
+          double cur_t;
+          SPAparameter param;
+          int num_divisions = 20;
+          SPAposition* pos_array = new SPAposition[num_divisions+1];
+          SPAinterval range = guide_edge->param_range();
+          // Get range with respect to underlying curve.
+          if(guide_edge->sense() == REVERSED)
+            range.negate();
+          double dt = range.length()/(double)num_divisions;
+          double start = range.start_pt();
+          double end = range.end_pt();
+          guide_edge->geometry()->equation().point_perp(cur_clump->ave_pos, closest);
+          double start_dist = (closest - guide_edge->start_pos()).len_sq();
+          double end_dist = (closest - guide_edge->end_pos()).len_sq();
+          if(start_dist > end_dist)
+          {
+            double tmp = start;
+            start = end;
+            end = tmp;
+            dt *= -1.0;
+          }
+
+          cur_t = start + dt;
+          SPAposition pos;
+          pos_array[0] = cur_clump->ave_pos;
+          for(r=1; r<num_divisions; r++)
+          {
+            SPAposition ave_pos;
+            guide_edge->geometry()->equation().eval(cur_t, ave_pos);
+            pos = ave_pos;
+            for(int e=copy.size(); e--;)
+            {
+              EDGE *cur_e = copy.get_and_step();
+              cur_e->geometry()->equation().point_perp(pos, closest);
+              ave_pos.set_x(ave_pos.x() + closest.x());
+              ave_pos.set_y(ave_pos.y() + closest.y());
+              ave_pos.set_z(ave_pos.z() + closest.z());
+            }
+            ave_pos.set_x(ave_pos.x() / (copy.size() + 1));
+            ave_pos.set_y(ave_pos.y() / (copy.size() + 1));
+            ave_pos.set_z(ave_pos.z() / (copy.size() + 1));
+            pos_array[r] = ave_pos;
+            cur_t += dt;
+          }
+          pos_array[num_divisions] = other_clump->ave_pos;
+          outcome result = api_curve_spline(num_divisions+1, pos_array, 
+                  NULL, NULL, new_edge);
+          delete [] pos_array;
+        }
+
+        for(r=common_edges.size(); r--;)
+        {
+          EDGE *cur_com_edge = common_edges.get_and_step();
+          ENTITY* copy;
+          api_copy_entity_contents((ENTITY*)new_edge, copy);
+          old_edge_to_new_edge_map[cur_com_edge] = (EDGE*)copy;
+        }
+        api_del_entity((ENTITY*)new_edge);
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+EDGE* AcisTopologyTool::find_common_edge (FACE *f1, FACE *f2)
+{
+  ENTITY_LIST f1_edge_list;
+  api_get_edges((ENTITY*)f1, f1_edge_list);
+  ENTITY *tmp_ent, *tmp_ent2;
+  f1_edge_list.init();
+  while((tmp_ent = f1_edge_list.next()))
+  {
+    ENTITY_LIST edge_faces;
+    api_get_faces(tmp_ent, edge_faces);
+    while((tmp_ent2 = edge_faces.next()))
+    {
+      if(tmp_ent2 == f2)
+        return (EDGE*)tmp_ent;
+    }
+  }
+  return NULL;
+}
+
+EDGE* AcisTopologyTool::find_common_edge (VERTEX *v1, VERTEX *v2)
+{
+  ENTITY_LIST v1_edge_list;
+  api_get_edges((ENTITY*)v1, v1_edge_list);
+  ENTITY *tmp_ent, *tmp_ent2;
+  v1_edge_list.init();
+  while((tmp_ent = v1_edge_list.next()))
+  {
+    ENTITY_LIST edge_verts;
+    api_get_vertices(tmp_ent, edge_verts);
+    while((tmp_ent2 = edge_verts.next()))
+    {
+      if(tmp_ent2 == v2)
+        return (EDGE*)tmp_ent;
+    }
+  }
+  return NULL;
+}
+
+CubitStatus AcisTopologyTool::find_new_pos_for_clump(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                                            DLIList<FACE*> &faces_to_move,
+                                            double &size)
+{
+  std::map<VERTEXClump*, DLIList<FACE*>*, mapltclump>::iterator iter;
+  double tol = (2.0 * size) * (2.0 * size);
+
+  SPAposition clos;
+  SPAunit_vector norm;
+  for(iter=surrounding_faces_map.begin(); iter != surrounding_faces_map.end(); iter++ )
+  {
+    VERTEXClump *cur_clump = iter->first;
+    DLIList<FACE*> *surrounding_faces = iter->second;
+    DLIList<FACE*> copy_of_surrounding_faces = *surrounding_faces;
+    copy_of_surrounding_faces -= faces_to_move;
+    if(copy_of_surrounding_faces.size() > 1)
+    {
+      FACE *start_face = copy_of_surrounding_faces.extract();
+      start_face->geometry()->equation().point_perp(cur_clump->ave_pos, clos, norm);
+      CubitVector normal(norm.x(), norm.y(), norm.z());
+      CubitVector closest(clos.x(), clos.y(), clos.z());
+      CubitPlane plane1(normal, closest);
+      FACE *next_face = copy_of_surrounding_faces.extract();
+      EDGE *common_edge = find_common_edge(start_face, next_face);
+      if(common_edge)
+      {
+        if(cur_clump->verts.is_in_list(common_edge->start()))
+          cur_clump->ave_pos = common_edge->start()->geometry()->coords();
+        else if(cur_clump->verts.is_in_list(common_edge->end()))
+          cur_clump->ave_pos = common_edge->end()->geometry()->coords();
+      }
+      else
+      {
+        next_face->geometry()->equation().point_perp(cur_clump->ave_pos, clos, norm);
+        CubitVector normal2(norm.x(), norm.y(), norm.z());
+        CubitVector closest2(clos.x(), clos.y(), clos.z());
+        CubitPlane plane2(normal2, closest2);
+        CubitVector line_origin, line_dir;
+        if(plane1.intersect(plane2, line_origin, line_dir))
+        {
+          CubitVector ave_pos(cur_clump->ave_pos.x(), cur_clump->ave_pos.y(),
+            cur_clump->ave_pos.z());
+          if(ave_pos.about_equal(line_origin))
+          {
+            cur_clump->ave_pos.set_x(line_origin.x());
+            cur_clump->ave_pos.set_y(line_origin.y());
+            cur_clump->ave_pos.set_z(line_origin.z());
+          }
+          else
+          {
+            CubitVector v2(ave_pos - line_origin);
+            double dot = v2 % line_dir;
+            CubitVector pt3 = line_origin + dot * line_dir;
+            cur_clump->ave_pos.set_x(pt3.x());
+            cur_clump->ave_pos.set_y(pt3.y());
+            cur_clump->ave_pos.set_z(pt3.z());
+          }
+        }
+      }
+
+      if(common_edge && copy_of_surrounding_faces.size() > 0)
+      {
+        next_face = copy_of_surrounding_faces.extract();
+        next_face->geometry()->equation().point_perp(cur_clump->ave_pos, clos, norm);
+        CubitVector normal2(norm.x(), norm.y(), norm.z());
+        CubitVector closest2(clos.x(), clos.y(), clos.z());
+        CubitPlane plane2(normal2, closest2);
+        SPAunit_vector tang;
+        common_edge->geometry()->equation().point_perp(cur_clump->ave_pos, clos, tang);
+        CubitVector closest(clos.x(), clos.y(), clos.z());
+        CubitVector tangent(tang.x(), tang.y(), tang.z());
+        CubitVector new_pt = plane2.intersect(closest, tangent);
+        CubitVector clump_pos(cur_clump->ave_pos.x(), cur_clump->ave_pos.y(),
+          cur_clump->ave_pos.z());
+        if((new_pt - clump_pos).length_squared() < tol)
+        {
+          cur_clump->ave_pos.set_x(new_pt.x());
+          cur_clump->ave_pos.set_y(new_pt.y());
+          cur_clump->ave_pos.set_z(new_pt.z());
+        }
+      }
+    }
+    else if(copy_of_surrounding_faces.size() == 1)
+    {
+      FACE *start_face = copy_of_surrounding_faces.get();
+      start_face->geometry()->equation().point_perp(cur_clump->ave_pos, clos, norm);
+      cur_clump->ave_pos = clos;
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::choose_best_face_to_move(DLIList<FACE*> &faces_that_might_move,
+                                              std::map <FACE*, int, mapltid> &face_clump_count_map,
+                                              DLIList<VERTEX*> &all_verts_in_clumps)
+{
+  if(faces_that_might_move.size() == 2)
+  {
+    FACE *face1 = faces_that_might_move.get_and_step();
+    FACE *face2 = faces_that_might_move.get();
+    if(face_clump_count_map[face1] < face_clump_count_map[face2])
+    {
+      faces_that_might_move.move_to(face2);
+      faces_that_might_move.extract();
+    }
+    else if(face_clump_count_map[face2] < face_clump_count_map[face1])
+    {
+      faces_that_might_move.move_to(face1);
+      faces_that_might_move.extract();
+    }
+    else
+    {
+      DLIList<VERTEX*> face1_verts, face2_verts;
+      ENTITY_LIST face1_VERTS, face2_VERTS;
+      api_get_vertices((ENTITY*)face1, face1_VERTS);
+      api_get_vertices((ENTITY*)face2, face2_VERTS);
+      face1_VERTS.init();
+      face2_VERTS.init();
+      ENTITY *tmp_ent;
+      while((tmp_ent = face1_VERTS.next()))
+        face1_verts.append((VERTEX*)tmp_ent);
+      while((tmp_ent = face2_VERTS.next()))
+        face2_verts.append((VERTEX*)tmp_ent);
+      face1_verts.intersect(all_verts_in_clumps);
+      face2_verts.intersect(all_verts_in_clumps);
+      if(face1_verts.size() > face2_verts.size())
+      {
+        faces_that_might_move.move_to(face1);
+        faces_that_might_move.extract();
+      }
+      else
+      {
+        // face 2 has more than or equal the number of
+        // face 1 so remove face2 from the list so that
+        // face 1 is moved.
+        faces_that_might_move.move_to(face2);
+        faces_that_might_move.extract();
+      }
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::ensure_possible_solution(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &faces_that_dont_intersect_map,
+                                             DLIList<FACE*> &faces_that_might_move)
+{
+  std::map<VERTEXClump*, DLIList<FACE*>*, mapltclump>::iterator iter;
+
+  for(iter=faces_that_dont_intersect_map.begin(); iter != faces_that_dont_intersect_map.end(); iter++ )
+    faces_that_might_move += *(iter->second);
+
+  faces_that_might_move.uniquify_unordered();
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::find_faces_that_dont_intersect(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                            std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &faces_that_dont_intersect_map,
+                            double &small_dist)
+{
+  int i;
+  double tol = (2.0 * small_dist) * (2.0 * small_dist);
+  std::map<VERTEXClump*, DLIList<FACE*>*, mapltclump>::iterator iter;
+
+  // Find out which face(s) must move for each vertex in the clump.
+  for(iter=surrounding_faces_map.begin(); iter != surrounding_faces_map.end(); iter++ )
+  {
+    DLIList<FACE*> *no_intersection_list = new DLIList<FACE*>;
+    VERTEXClump *cur_clump = iter->first;
+    DLIList<FACE*> *cur_face_list = iter->second;
+    DLIList<FACE*> copy_of_face_list = *cur_face_list;
+    while(copy_of_face_list.size() > 1)
+    {
+      FACE *start_face = copy_of_face_list.extract();
+      ENTITY_LIST start_face_edges;
+      api_get_edges((ENTITY*)start_face, start_face_edges);
+      SPAposition clos;
+      SPAunit_vector norm;
+      start_face->geometry()->equation().point_perp(cur_clump->ave_pos, clos, norm);
+      CubitVector normal(norm.x(), norm.y(), norm.z());
+      CubitVector closest(clos.x(), clos.y(), clos.z());
+      CubitPlane plane1(normal, closest);
+      for(i=copy_of_face_list.size(); i--;)
+      {
+        FACE *other_face = copy_of_face_list.get_and_step();
+        EDGE *common_edge = find_common_edge(start_face, other_face);
+        if(!common_edge)
+        {
+          other_face->geometry()->equation().point_perp(cur_clump->ave_pos, clos, norm);
+          CubitVector normal2(norm.x(), norm.y(), norm.z());
+          CubitVector closest2(clos.x(), clos.y(), clos.z());
+          CubitPlane plane2(normal2, closest2);
+          CubitVector line_origin, line_dir;
+          if(plane1.intersect(plane2, line_origin, line_dir))
+          {
+            CubitVector ave_pos(cur_clump->ave_pos.x(), cur_clump->ave_pos.y(),
+              cur_clump->ave_pos.z());
+            double dist;
+            if(ave_pos.about_equal(line_origin))
+              dist = 0.0;
+            else
+            {
+              CubitVector v2(ave_pos - line_origin);
+              double dot = v2 % line_dir;
+              CubitVector pt3 = line_origin + dot * line_dir;
+              dist = (pt3 - ave_pos).length_squared();
+            }
+            if(dist > tol)
+            {
+              no_intersection_list->append_unique(start_face);
+              no_intersection_list->append_unique(other_face);
+            }
+          }
+          else
+          {
+            no_intersection_list->append_unique(start_face);
+            no_intersection_list->append_unique(other_face);
+          }
+        }
+      }
+    }
+    faces_that_dont_intersect_map[cur_clump] = no_intersection_list;
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus AcisTopologyTool::find_face_clump_counts(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                                std::map <FACE*, int, mapltid> &face_clump_count_map)
+{
+  int i;
+  std::map<VERTEXClump*, DLIList<FACE*>*, mapltclump>::iterator iter;
+
+  // Initialize all counts to zero.
+  for(iter=surrounding_faces_map.begin(); iter != surrounding_faces_map.end(); iter++ )
+  {
+    for(i=iter->second->size(); i--;)
+    {
+      FACE *cur_face = iter->second->get_and_step();
+      face_clump_count_map[cur_face] = 0;
+    }
+  }
+
+  // Find number of times face is referenced in a clump.
+  for(iter=surrounding_faces_map.begin(); iter != surrounding_faces_map.end(); iter++ )
+  {
+    for(i=iter->second->size(); i--;)
+    {
+      FACE *cur_face = iter->second->get_and_step();
+      face_clump_count_map[cur_face] = face_clump_count_map[cur_face] + 1;
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+void AcisTopologyTool::find_ave_clump_pos(VERTEXClump *&clump)
+{
+  int i;
+
+  clump->ave_pos = SPAposition(0,0,0);
+  for(i=clump->verts.size(); i--;)
+  {
+    VERTEX *cur_vert = clump->verts.get_and_step();
+    clump->ave_pos.set_x(clump->ave_pos.x() + cur_vert->geometry()->coords().x());
+    clump->ave_pos.set_y(clump->ave_pos.y() + cur_vert->geometry()->coords().y());
+    clump->ave_pos.set_z(clump->ave_pos.z() + cur_vert->geometry()->coords().z());
+  }
+  clump->ave_pos.set_x(clump->ave_pos.x()/clump->verts.size());
+  clump->ave_pos.set_y(clump->ave_pos.y()/clump->verts.size());
+  clump->ave_pos.set_z(clump->ave_pos.z()/clump->verts.size());
+}
+
+CubitStatus AcisTopologyTool::get_all_verts_in_clumps(DLIList<VERTEXClump*> &clumps,
+                                               DLIList<VERTEX*> &all_verts_in_clumps)
+{
+  int i;
+  for(i=clumps.size(); i--;)
+  {
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    all_verts_in_clumps += cur_clump->verts;
+    // While we are here calculate an average position for
+    // each clump.
+    find_ave_clump_pos(cur_clump);
+  }
+
+  all_verts_in_clumps.uniquify_ordered();
+
+  return CUBIT_SUCCESS;
+}
+
+/*
+void AcisTopologyTool::propagate_over_narrow_face(FACE *narrow_face,
+                                                  EDGE *edge,
+                                                  DLIList<FACE*> &processed_faces,
+                                                  DLIList<EDGE*> &small_edges,
+                                                  double small_edge_length)
+{
+  processed_faces.append(narrow_face);
+  ENTITY_LIST face_edges;
+  api_get_edges((ENTITY*)narrow_face, face_edges);
+  ENTITY *tmp_ent;
+  face_edges.init();
+  while((tmp_ent = face_edges.next()))
+  {
+    EDGE *cur_edge = (EDGE*)tmp_ent;
+    if(cur_edge != edge)
+    {
+      if(cur_edge->length() < small_edge_length)
+      {
+        if(!small_edges.is_in_list(cur_edge))
+        {
+          small_edges.append(cur_edge);
+          propagate_from_small_edge(cur_edge, small_edges,
+                      processed_faces, small_edge_length);
+        }
+      }
+      ENTITY_LIST edge_faces;
+      api_get_faces((ENTITY*)cur_edge, edge_faces);
+      edge_faces.init();
+      while((tmp_ent = edge_faces.next()))
+      {
+        FACE *cur_face = (FACE*)tmp_ent;
+        if(cur_face != narrow_face)
+        {
+          if(!processed_faces.is_in_list(cur_face))
+          {
+            if(narrow_region_exists(cur_face, small_edge_length))
+            {
+              propagate_over_narrow_face(cur_face, cur_edge, processed_faces,
+                small_edges, small_edge_length);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+*/
+void AcisTopologyTool::point_perp_trimmed(EDGE *edge, 
+                                  SPAposition &pos_in,
+                                  SPAposition &pos_out,
+                                  double *edge_param)
+{
+  SPAinterval range = edge->param_range();
+  SPAparameter crv_param, tmp_edge_param;
+  edge->geometry()->equation().point_perp(pos_in, pos_out, *(SPAparameter*)NULL_REF, crv_param);
+  if(edge->sense() == REVERSED)
+  {
+    if(crv_param > -range.start_pt())
+    {
+      tmp_edge_param = range.start_pt();
+      pos_out = edge->start_pos();
+    }
+    else if(crv_param < -range.end_pt())
+    {
+      tmp_edge_param = range.start_pt();
+      pos_out = edge->end_pos();
+    }
+    else
+      tmp_edge_param = -crv_param;
+  }
+  else
+  {
+    if(crv_param > range.end_pt())
+    {
+      tmp_edge_param = range.end_pt();
+      pos_out = edge->end_pos();
+    }
+    else if(crv_param < range.start_pt())
+    {
+      tmp_edge_param = range.start_pt();
+      pos_out = edge->start_pos();
+    }
+    else
+      tmp_edge_param = crv_param;
+  }
+
+  if(edge_param)
+    *edge_param = tmp_edge_param;
+}
+/*
+int AcisTopologyTool::is_narrow_region_at_point(EDGE *e1,
+                                               SPAposition &pt_on_e1,
+                                               EDGE *e2,
+                                               const double &tol_sq,
+                                               SPAposition &closest)
+{
+  int ret = 0;
+  SPAvector tan_1, tan_2;
+  double param;
+  point_perp_trimmed(e2, pt_on_e1, closest, &param);
+  double dist = (pt_on_e1-closest).len_sq();
+  if(dist < tol_sq)
+  {
+    if(e2->sense() == REVERSED)
+      param = -param;
+    SPAparameter e1_param;
+    SPAposition tmp_pos;
+    e1->geometry()->equation().point_perp(pt_on_e1, tmp_pos, *(SPAparameter*)NULL_REF, e1_param);
+    tan_1 = e1->geometry()->equation().eval_deriv(e1_param);
+    tan_2 = e2->geometry()->equation().eval_deriv(param);
+    SPAunit_vector utan1 = normalise(tan_1);
+    SPAunit_vector utan2 = normalise(tan_2);
+    if(fabs(utan1 % utan2) > .9)
+      ret = 1;
+  }
+  return ret;
+}
+*/
+/*
+int AcisTopologyTool::narrow_region_exists(FACE *face,
+                                          const double &tol)
+{
+  int ret = 0;
+  ENTITY_LIST face_edges;
+  api_get_edges((ENTITY*)face, face_edges);
+  while(face_edges.iteration_count() > 1 && !ret)
+  {
+    EDGE *cur_edge = (EDGE*)face_edges.first();
+    face_edges.remove(cur_edge);
+
+    face_edges.init();
+    ENTITY *tmp_ent;
+    // Compare this edge with the remaining edges on the face.
+    while((tmp_ent = face_edges.next()) && !ret)
+    {
+      EDGE *other_edge = (EDGE*)tmp_ent;
+
+      DLIList<SPAposition*> e1_pos_list, e2_pos_list;
+      DLIList<VERTEX*> e1_vert_list, e2_vert_list;
+      ret = narrow_region_exists(cur_edge, other_edge, face, tol,
+        e1_pos_list, e2_pos_list, e1_vert_list, e2_vert_list);
+      while(e1_pos_list.size())
+        delete e1_pos_list.pop();
+      while(e2_pos_list.size())
+        delete e2_pos_list.pop();
+    }
+  }
+  return ret;
+}
+*/
+/*
+int AcisTopologyTool::narrow_region_exists(EDGE *e1,
+                                            EDGE *e2,
+                                            FACE *face,
+                                            const double &tol,
+                                            DLIList<SPAposition*> &e1_pos_list,
+                                            DLIList<SPAposition*> &e2_pos_list,
+                                            DLIList<VERTEX*> &e1_vert_list,
+                                            DLIList<VERTEX*> &e2_vert_list)
+{
+  double same_pt_tol = GEOMETRY_RESABS*GEOMETRY_RESABS;
+  int ret = 0;
+  double tol_sq = tol*tol;
+  double small_step = 5.0*tol;
+  double small_step_sq = small_step*small_step;
+  VERTEX *e1_start_vert = e1->start();
+  VERTEX *e1_end_vert = e1->end();
+  double max_dist_sq = 0.0;
+
+  SPAposition closest;
+
+  // Project cur endpoints onto other.
+  if(is_narrow_region_at_point(e1, e1->start_pos(), e2, tol_sq, closest))
+  {
+    max_dist_sq = (closest - e1->start_pos()).len_sq();
+    e1_pos_list.append(new SPAposition(e1->start_pos()));
+    e2_pos_list.append(new SPAposition(closest));
+    e1_vert_list.append(e1_start_vert);
+    e2_vert_list.append(NULL);
+  }
+  if(is_narrow_region_at_point(e1, e1->end_pos(), e2, tol_sq, closest))
+  {
+    double cur_dist_sq = (closest - e1->end_pos()).len_sq();
+    max_dist_sq = max_dist_sq > cur_dist_sq ? max_dist_sq : cur_dist_sq;
+    e1_pos_list.append(new SPAposition(e1->end_pos()));
+    e2_pos_list.append(new SPAposition(closest));
+    e1_vert_list.append(e1_end_vert);
+    e2_vert_list.append(NULL);
+  }
+
+  if(e1_pos_list.size() < 2)
+  {
+    VERTEX *e2_start_vert = e2->start();
+    VERTEX *e2_end_vert = e2->end();
+    if(is_narrow_region_at_point(e2, e2->start_pos(), e1, tol_sq, closest))
+    {
+      double cur_dist_sq = (closest - e2->start_pos()).len_sq();
+      max_dist_sq = max_dist_sq > cur_dist_sq ? max_dist_sq : cur_dist_sq;
+      e2_pos_list.append(new SPAposition(e2->start_pos()));
+      e1_pos_list.append(new SPAposition(closest));
+      e2_vert_list.append(e2_start_vert);
+      e1_vert_list.append(NULL);
+    }
+    if(e1_pos_list.size() < 2)
+    {
+      if(is_narrow_region_at_point(e2, e2->end_pos(), e1, tol_sq, closest))
+      {
+        double cur_dist_sq = (closest - e2->end_pos()).len_sq();
+        max_dist_sq = max_dist_sq > cur_dist_sq ? max_dist_sq : cur_dist_sq;
+        e2_pos_list.append(new SPAposition(e2->end_pos()));
+        e1_pos_list.append(new SPAposition(closest));
+        e2_vert_list.append(e2_end_vert);
+        e1_vert_list.append(NULL);
+      }
+    }
+  }
+
+  if(e1_pos_list.size() == 2)
+  {
+    if((*e1_pos_list.get() - *e1_pos_list.next()).len_sq() < same_pt_tol)
+    {
+      if((*e2_pos_list.get() - *e2_pos_list.next()).len_sq() < same_pt_tol)
+      {
+        e1_pos_list.reset();
+        e2_pos_list.reset();
+        e1_vert_list.reset();
+        e2_vert_list.reset();
+        delete e1_pos_list.remove();
+        delete e2_pos_list.remove();
+        e1_vert_list.remove();
+        e2_vert_list.remove();
+      }
+    }
+  }
+
+  if(e1_pos_list.size() == 2)
+  {
+    double dist_tol = sqrt(max_dist_sq)*5.0;
+    e1_pos_list.reset();
+    e2_pos_list.reset();
+    SPAposition *cur1 = e1_pos_list.get_and_step();
+    SPAposition *cur2 = e1_pos_list.get();
+    SPAposition *other1 = e2_pos_list.get_and_step();
+    SPAposition *other2 = e2_pos_list.get();
+
+    SPAposition tmp_pos;
+    SPAparameter e1param1, e1param2;
+    e1->geometry()->equation().point_perp(*cur1, tmp_pos, *(SPAparameter*)NULL_REF, e1param1);
+    e1->geometry()->equation().point_perp(*cur2, tmp_pos, *(SPAparameter*)NULL_REF, e1param2);
+    double len1 = fabs(e1->geometry()->equation().length(e1param1, e1param2));
+    if(len1 > dist_tol)
+    {
+      SPAparameter e2param1, e2param2;
+      e2->geometry()->equation().point_perp(*other1, tmp_pos, *(SPAparameter*)NULL_REF, e2param1);
+      e2->geometry()->equation().point_perp(*other2, tmp_pos, *(SPAparameter*)NULL_REF, e2param2);
+      double len2 = fabs(e2->geometry()->equation().length(e2param1, e2param2));
+      if(len2 > dist_tol)
+      {
+        // Check mid point.
+        double mid_param = (e1param1 + e1param2)/2.0;
+        SPAposition cur3;
+        e1->geometry()->equation().eval(mid_param, cur3);
+        if(is_narrow_region_at_point(e1, cur3, e2, tol_sq, closest))
+        {
+          // Sanity check to make sure we aren't splitting off negative space.
+          SPAposition mid((cur3.x()+closest.x())/2.0, (cur3.y()+closest.y())/2.0, (cur3.z()+closest.z())/2.0);
+          SPAposition tmp_pt;
+          api_find_cls_ptto_face(mid, face, tmp_pt);
+          if((mid-tmp_pt).len_sq() < same_pt_tol)
+            ret = 1;
+        }
+      }
+      else
+      {
+        e1_pos_list.remove(cur1);
+        e1_pos_list.remove(cur2);
+        e2_pos_list.remove(other1);
+        e2_pos_list.remove(other2);
+        delete cur1;
+        delete cur2;
+        delete other1;
+        delete other2;
+      }
+    }
+    else
+    {
+      e1_pos_list.remove(cur1);
+      e1_pos_list.remove(cur2);
+      e2_pos_list.remove(other1);
+      e2_pos_list.remove(other2);
+      delete cur1;
+      delete cur2;
+      delete other1;
+      delete other2;
+    }
+  }
+
+  if(!ret && e1_pos_list.size() > 0)
+  {
+    int i;
+    e1_pos_list.reset();
+    e2_pos_list.reset();
+    e1_vert_list.reset();
+    e2_vert_list.reset();
+    for(i=e1_pos_list.size(); i--;)
+    {
+      SPAposition *e1_pos = e1_pos_list.get_and_step();
+      SPAposition *e2_pos = e2_pos_list.get_and_step();
+      VERTEX *e1_vert = e1_vert_list.get_and_step();
+      VERTEX *e2_vert = e2_vert_list.get_and_step();
+
+      VERTEX *cur_vert = NULL;
+      EDGE *cur_edge = NULL, *other_edge = NULL;
+      if(e1_vert)
+      {
+        cur_edge = e1;
+        other_edge = e2;
+        cur_vert = e1_vert;
+      }
+      else if(e2_vert)
+      {
+        cur_edge = e2;
+        other_edge = e1;
+        cur_vert = e2_vert;
+      }
+      if(cur_vert)
+      {
+        SPAposition prev_pos = cur_vert->geometry()->coords(), next_pos;
+        double num_incs = 20.0;
+        SPAinterval crv_range = cur_edge->param_range();
+        if(cur_edge->sense() == REVERSED)
+          crv_range.negate();
+        double start, end;
+        if((cur_vert != cur_edge->start()) != (cur_edge->sense() == REVERSED))
+        {
+          start = crv_range.end_pt();
+          end = crv_range.start_pt();
+        }
+        else
+        {
+          start = crv_range.start_pt();
+          end = crv_range.end_pt();
+        }
+        double step = (end-start)/num_incs;  
+        double prev_param = start;
+        double next_param = start + step;
+        int still_good = 1;
+        // Do coarse traversal along curve to see where we start deviating from
+        // narrow.
+        int cntr = 0;
+        while(still_good)
+        {
+          cur_edge->geometry()->equation().eval(next_param, next_pos);
+          cntr++;
+          if(!is_narrow_region_at_point(cur_edge, next_pos, other_edge, tol_sq, closest) ||
+                        cntr > num_incs)
+            still_good = 0;
+          else
+          {
+            prev_param = next_param;
+            prev_pos = next_pos;
+            next_param += step;
+          }
+        }
+        SPAparameter param1, param2;
+        SPAposition tmp_pos;
+        cur_edge->geometry()->equation().point_perp(prev_pos, tmp_pos, *(SPAparameter*)NULL_REF, param1);
+        cur_edge->geometry()->equation().point_perp(next_pos, tmp_pos, *(SPAparameter*)NULL_REF, param2);
+        double cur_arc_length = fabs(cur_edge->geometry()->equation().length(param1, param2));
+        // Do bisection of remaining interval to zero in on point where
+        // we go from narrow to non-narrow.
+        SPAposition mid_pos;
+        while(cur_arc_length > small_step)
+        {
+          double mid_param = (prev_param + next_param)/2.0;
+          cur_edge->geometry()->equation().eval(mid_param, mid_pos);
+          if(is_narrow_region_at_point(cur_edge, mid_pos, other_edge, tol_sq, closest))
+          {
+            prev_param = mid_param;
+            prev_pos = mid_pos;
+          }
+          else
+          {
+            next_param = mid_param;
+            next_pos = mid_pos;
+          }
+          cur_edge->geometry()->equation().point_perp(prev_pos, tmp_pos, *(SPAparameter*)NULL_REF, param1);
+          cur_edge->geometry()->equation().point_perp(next_pos, tmp_pos, *(SPAparameter*)NULL_REF, param2);
+          cur_arc_length = fabs(cur_edge->geometry()->equation().length(param1, param2));
+        }
+        if((cur_vert->geometry()->coords() - prev_pos).len_sq() > small_step_sq)
+        {
+          if(cur_edge == e1)
+          {
+            e1_pos_list.append(new SPAposition(mid_pos));
+            e2_pos_list.append(new SPAposition(closest));
+          }
+          else
+          {
+            e2_pos_list.append(new SPAposition(mid_pos));
+            e1_pos_list.append(new SPAposition(closest));
+          }
+          e1_vert_list.append(NULL);
+          e2_vert_list.append(NULL);
+          ret = 1;
+        }
+      }
+    }
+  }
+  return ret;
+}
+*/
+/*
+void AcisTopologyTool::propagate_from_small_edge(EDGE *edge,
+                                                 DLIList<EDGE*> &small_edges,
+                                                 DLIList<FACE*> &processed_faces,
+                                                 double small_edge_length)
+{
+  // First find any small edges connected to this edge.
+  ENTITY_LIST edge_verts;
+  api_get_vertices((ENTITY*)edge, edge_verts);
+  ENTITY *tmp_ent;
+  edge_verts.init();
+  while((tmp_ent = edge_verts.next()))
+  {
+    ENTITY_LIST vert_edges;
+    api_get_edges(tmp_ent, vert_edges);
+    vert_edges.init();
+    while((tmp_ent = vert_edges.next()))
+    {
+      EDGE *cur_edge = (EDGE*)tmp_ent;
+      if(cur_edge != edge)
+      {
+        if(cur_edge->length() < small_edge_length)
+        {
+          if(!small_edges.is_in_list(cur_edge))
+          {
+            small_edges.append(cur_edge);
+            propagate_from_small_edge(cur_edge, small_edges, processed_faces, small_edge_length);
+          }
+        }
+      }
+    }
+  }
+  // Now look at adjacent narrow faces and recursively process them.
+  ENTITY_LIST edge_faces;
+  api_get_faces((ENTITY*)edge, edge_faces);
+  edge_faces.init();
+  while((tmp_ent = edge_faces.next()))
+  {
+    FACE *cur_face = (FACE*)tmp_ent;
+    if(!processed_faces.is_in_list(cur_face))
+    {
+      if(narrow_region_exists(cur_face, small_edge_length))
+      {
+        propagate_over_narrow_face(cur_face, edge, processed_faces,
+          small_edges, small_edge_length);
+      }
+    }
+  }
+}
+*/
+CubitStatus AcisTopologyTool::setup_clump_map(DLIList<EDGE*> &edges_to_remove,
+                            DLIList<FACE*> &faces_to_remove,
+                            double small_edge_size,
+                            DLIList<VERTEXClump*> &clumps, 
+                            std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map)
+{
+  int i;
+  DLIList<EDGE*> small_edges;
+
+  // Look at the passed-in curves and surfaces and determine if any of the curves
+  // are small enough to be swallowed up by a clump.  Otherwise put a clump at every
+  // vertex.
+  for(i=edges_to_remove.size(); i--;)
+  {
+    EDGE *edge = edges_to_remove.get_and_step();
+    if(edge->length() < small_edge_size)
+      small_edges.append_unique(edge);
+  }
+  for(i=faces_to_remove.size(); i--;)
+  {
+    FACE *face = faces_to_remove.get_and_step();
+    ENTITY_LIST edges;
+    api_get_edges((ENTITY*)face, edges);
+    edges.init();
+    ENTITY *tmp_ent = NULL;
+    while( (tmp_ent = edges.next()) != NULL )
+    {
+      EDGE *tmp_edge = (EDGE*)tmp_ent;
+      if(tmp_edge->length() < small_edge_size)
+        small_edges.append_unique(tmp_edge);
+    }
+  }
+  /*
+  // If told to do so propagate the topology to be removed to include
+  // other narrow surfaces and small edges.
+  if(propagate)
+  {
+    DLIList<FACE*> processed_faces;
+    // First look at all of the edges connected to small edges
+    // to see if there are other small edges.
+    DLIList<EDGE*> copy_of_small_edges = small_edges;
+    while(copy_of_small_edges.size())
+    {
+      EDGE *edge = copy_of_small_edges.extract();
+      propagate_from_small_edge(edge, small_edges,
+               processed_faces, small_edge_size);
+    }
+  }
+*/
+  while(small_edges.size())
+  {
+    VERTEXClump *new_clump = new VERTEXClump;
+    new_clump->new_vert = NULL;
+    EDGE *edge = small_edges.extract();
+    ENTITY_LIST verts;
+    api_get_vertices(edge, verts);
+    verts.init();
+    ENTITY *tmp_ent;
+    while((tmp_ent=verts.next()))
+    {
+      VERTEX *tmp_vert = (VERTEX*)tmp_ent;
+      new_clump->verts.append_unique(tmp_vert);
+      get_neighbor_small_edges(edge, tmp_vert, new_clump, small_edges);
+    }
+    clumps.append(new_clump);
+  }
+  // Fill out the pt to clump map for the clumps we have created.
+  build_old_vertex_to_clump_map(clumps, old_vertex_to_clump_map);
+  // Now create a clump for any remaining pts that were
+  // not put in other clumps.
+  for(i=edges_to_remove.size(); i--;)
+  {
+    EDGE *edge = edges_to_remove.get_and_step();
+    ENTITY_LIST verts;
+    api_get_vertices(edge, verts);
+    verts.init();
+    ENTITY *tmp_ent;
+    while((tmp_ent = verts.next()))
+    {
+      VERTEX *tmp_vert = (VERTEX*)tmp_ent;
+      if(!old_vertex_to_clump_map.count(tmp_vert))
+      {
+        VERTEXClump *new_clump = new VERTEXClump;
+        new_clump->new_vert = NULL;
+        new_clump->verts.append(tmp_vert);
+        old_vertex_to_clump_map[tmp_vert] = new_clump;
+        clumps.append(new_clump);
+      }
+    }
+  }
+  for(i=faces_to_remove.size(); i--;)
+  {
+    FACE *face = faces_to_remove.get_and_step();
+    ENTITY_LIST edges;
+    api_get_edges((ENTITY*)face, edges);
+    edges.init();
+    ENTITY *tmp_ent;
+    while((tmp_ent = edges.next()))
+    {
+      EDGE *tmp_edge = (EDGE*)tmp_ent;
+      ENTITY_LIST verts;
+      api_get_vertices(tmp_edge, verts);
+      verts.init();
+      ENTITY *tmp_ent2;
+      while((tmp_ent2 = verts.next()))
+      {
+        VERTEX *tmp_vert = (VERTEX*)tmp_ent2;
+        if(!old_vertex_to_clump_map.count(tmp_vert))
+        {
+          VERTEXClump *new_clump = new VERTEXClump;
+          new_clump->new_vert = NULL;
+          new_clump->verts.append(tmp_vert);
+          old_vertex_to_clump_map[tmp_vert] = new_clump;
+          clumps.append(new_clump);
+        }
+      }
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+/*
+void AcisTopologyTool::propagate_to_find_other_small_edges(EDGE *edge, 
+                                                            VERTEX *cur_vert, 
+                                                            DLIList<EDGE*> &small_edges, 
+                                                            double small_edge_length)
+{
+  ENTITY_LIST vert_edges;
+  api_get_edges((ENTITY*)cur_vert, vert_edges);
+  ENTITY *tmp_ent;
+  vert_edges.init();
+  while((tmp_ent = vert_edges.next()))
+  {
+    EDGE *cur_edge = (EDGE*)tmp_ent;
+    if(cur_edge != edge && cur_edge->length() < small_edge_length &&
+      !small_edges.is_in_list(cur_edge))
+    {
+      small_edges.append(cur_edge);
+      ENTITY_LIST edge_verts;
+      api_get_vertices((ENTITY*)cur_edge, edge_verts);
+      edge_verts.init();
+      while((tmp_ent = edge_verts.next()))
+      {
+        VERTEX *vert = (VERTEX*)tmp_ent;
+        if(vert != cur_vert)
+          propagate_to_find_other_small_edges(cur_edge, vert, small_edges, small_edge_length);
+      }
+    }
+  }
+}
+*/
+void AcisTopologyTool::build_old_vertex_to_clump_map(DLIList<VERTEXClump*> &clumps,
+                        std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map)
+{
+  int i, j;
+
+  for(i=clumps.size(); i--;)
+  {
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    for(j=cur_clump->verts.size(); j--;)
+    {
+      VERTEX *cur_vert = cur_clump->verts.get_and_step();
+      old_vertex_to_clump_map[cur_vert] = cur_clump;
+    }
+  }
+}
+
+void AcisTopologyTool::get_neighbor_small_edges(EDGE *edge,
+                                               VERTEX *vert,
+                                               VERTEXClump *&clump,
+                                               DLIList<EDGE*> &small_edges)
+{
+  ENTITY_LIST edges;
+  api_get_edges(vert, edges);
+  edges.remove(edge);
+  ENTITY *tmp_ent;
+  edges.init();
+  while((tmp_ent = edges.next()))
+  {
+    EDGE *tmp_edge = (EDGE*)tmp_ent;
+    if(small_edges.is_in_list(tmp_edge))
+    {
+      small_edges.move_to(tmp_edge);
+      small_edges.extract();
+      ENTITY_LIST verts;
+      api_get_vertices(tmp_edge, verts);
+      ENTITY *tmp_ent2;
+      verts.init();
+      while((tmp_ent2 = verts.next()))
+      {
+        VERTEX *tmp_vert = (VERTEX*)tmp_ent2;
+        if(tmp_vert != vert)
+        {
+          clump->verts.append_unique(tmp_vert);
+          get_neighbor_small_edges(tmp_edge, tmp_vert, clump, small_edges);
+        }
+      }
+    }
+  }
+}
+
+CubitStatus AcisTopologyTool::find_faces_surrounding_clumps(DLIList<VERTEXClump*> &clumps,
+                            std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                            DLIList<VERTEX*> &all_verts_in_clumps,
+                            std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                            DLIList<FACE*> &faces_to_remove)
+{
+  int i, j, k;
+
+  for(i=clumps.size(); i--;)
+  {
+    DLIList<FACE*> *faces_surrounding_clump = new DLIList<FACE*>;
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    for(j=cur_clump->verts.size(); j--;)
+    {
+      VERTEX *cur_vert = cur_clump->verts.get_and_step();
+      ENTITY_LIST vert_faces;
+      api_get_faces(cur_vert, vert_faces);
+      ENTITY *tmp_ent;
+      /*
+      DLIList<FACE*> faces_to_remove_from_local_list;
+      vert_faces.init();
+      while((tmp_ent = vert_faces.next()))
+      {
+        FACE *cur_face = (FACE*)tmp_ent;
+        ENTITY_LIST face_verts;
+        api_get_vertices((ENTITY*)cur_face, face_verts);
+        for(k=all_verts_in_clumps.size(); k--;)
+          face_verts.remove(all_verts_in_clumps.get_and_step());
+        if(face_verts.iteration_count() == 0)
+        {
+          ENTITY_LIST face_edges;
+          api_get_edges((ENTITY*)cur_face, face_edges);
+          ENTITY *tmp_ent2;
+          EDGE *short_edge = NULL;
+          face_edges.init();
+          while((tmp_ent2 = face_edges.next()) && !short_edge)
+          {
+            EDGE *cur_edge = (EDGE*)tmp_ent2;
+            if(edge_within_clump(cur_edge, old_vertex_to_clump_map))
+              short_edge = cur_edge;
+          }
+          if(short_edge)
+          {
+            faces_to_remove.append_unique(cur_face);
+            faces_to_remove_from_local_list.append(cur_face);
+          }
+        }
+      }
+      */
+      for(k=faces_to_remove.size(); k--;)
+        vert_faces.remove((ENTITY*)faces_to_remove.get_and_step());
+      vert_faces.init();
+      while((tmp_ent = vert_faces.next()))
+        faces_surrounding_clump->append((FACE*)tmp_ent);
+    }
+    faces_surrounding_clump->uniquify_ordered();
+    surrounding_faces_map[cur_clump] = faces_surrounding_clump;
+  }
+
+  return CUBIT_SUCCESS;
+  /*
+  int i, j, k;
+
+  for(i=clumps.size(); i--;)
+  {
+    DLIList<FACE*> *faces_surrounding_clump = new DLIList<FACE*>;
+    VERTEXClump *cur_clump = clumps.get_and_step();
+    for(j=cur_clump->verts.size(); j--;)
+    {
+      VERTEX *cur_vert = cur_clump->verts.get_and_step();
+      ENTITY_LIST vert_faces;
+      api_get_faces(cur_vert, vert_faces);
+      DLIList<FACE*> faces_to_remove_from_local_list;
+      ENTITY *tmp_ent;
+      vert_faces.init();
+      while((tmp_ent = vert_faces.next()))
+      {
+        FACE *cur_face = (FACE*)tmp_ent;
+        ENTITY_LIST face_verts;
+        api_get_vertices((ENTITY*)cur_face, face_verts);
+        for(k=all_verts_in_clumps.size(); k--;)
+          face_verts.remove(all_verts_in_clumps.get_and_step());
+        if(face_verts.iteration_count() == 0)
+        {
+          ENTITY_LIST face_edges;
+          api_get_edges((ENTITY*)cur_face, face_edges);
+          ENTITY *tmp_ent2;
+          EDGE *short_edge = NULL;
+          face_edges.init();
+          while((tmp_ent2 = face_edges.next()) && !short_edge)
+          {
+            EDGE *cur_edge = (EDGE*)tmp_ent2;
+            if(edge_within_clump(cur_edge, old_vertex_to_clump_map))
+              short_edge = cur_edge;
+          }
+          if(short_edge)
+          {
+            faces_to_remove.append_unique(cur_face);
+            faces_to_remove_from_local_list.append(cur_face);
+          }
+        }
+      }
+      for(k=faces_to_remove_from_local_list.size(); k--;)
+        vert_faces.remove((ENTITY*)faces_to_remove_from_local_list.get_and_step());
+      vert_faces.init();
+      while((tmp_ent = vert_faces.next()))
+        faces_surrounding_clump->append((FACE*)tmp_ent);
+    }
+    faces_surrounding_clump->uniquify_ordered();
+    surrounding_faces_map[cur_clump] = faces_surrounding_clump;
+  }
+
+  return CUBIT_SUCCESS;
+  */
+}
+
+int AcisTopologyTool::edge_within_clump(EDGE *edge,
+                       std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map)
+{
+  int ret = 0;
+  VERTEX *v1 = edge->start();
+  VERTEX *v2 = edge->end();
+  if(old_vertex_to_clump_map.count(v1) > 0)
+  {
+    VERTEXClump *c1 = old_vertex_to_clump_map[v1];
+    if(old_vertex_to_clump_map.count(v2) > 0)
+    {
+      VERTEXClump *c2 = old_vertex_to_clump_map[v2];
+      if(c1 == c2)
+        ret = 1;
+    }
+  }
+  return ret;
+}
+
+void f(RefFace* face, int color)
+{
+  GfxDebug::draw_ref_face(face, color);
+  GfxDebug::flush();
+}
+
+void e(RefEdge* edge, int color)
+{
+  GfxDebug::draw_ref_edge(edge, color);
+  GfxDebug::flush();
+}
+
+void v(RefVertex* vert, int color)
+{
+  GfxDebug::draw_ref_vertex(vert, color);
+  GfxDebug::flush();
+}
+
+void p(CubitVector* v, int color)
+{
+  GfxDebug::draw_point(v, color);
+  GfxDebug::flush();
+}
+
+void pos(SPAposition* p, int color)
+{
+  GfxDebug::draw_point(p->x(), p->y(), p->z(), color);
+  GfxDebug::flush();
+}
+
+void en(ENTITY* ent, int color)
+{
+  AcisDrawTool::instance()->draw_ENTITY(ent, color, 0, 1);
+}

Copied: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.hpp (from rev 3491, cgm/branches/cubit/geom/ACIS_SRC/AcisTopologyTool.hpp)
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.hpp	                        (rev 0)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTopologyTool.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -0,0 +1,218 @@
+//- Class: AcisTopologyTool 
+//- File: AcisTopologyTool.hpp
+//- Type: class definition
+//- Description: Tool for removing topology
+//- from a model.
+//- Owner: Brett Clark
+//
+
+#ifndef ACISTOPOLOGYTOOL_HPP
+#define ACISTOPOLOGYTOOL_HPP
+
+#include "DLIList.hpp"
+#include "kernapi.hxx"
+#include "position.hxx"
+#include <map>
+
+class ENTITY;
+class VERTEX;
+class EDGE;
+class FACE;
+class ATTRIB_SNL_SIMPLE;
+
+typedef struct {
+  DLIList<VERTEX*> verts;
+  SPAposition ave_pos;
+  VERTEX *new_vert;
+} VERTEXClump;
+
+typedef struct {
+  VERTEXClump *c1, *c2;
+  EDGE *new_edge;
+} Link;
+
+struct mapltid
+{
+  bool operator()(const ENTITY *e1, const ENTITY *e2) const
+  {
+    tag_id_type id1, id2;
+    api_get_entity_id((ENTITY*)e1, id1);
+    api_get_entity_id((ENTITY*)e2, id2);
+    return (id1 < id2);
+  }
+};
+
+struct mapltclump
+{
+  bool operator()(const VERTEXClump *c1, const VERTEXClump *c2) const
+  {
+    tag_id_type id1, id2;
+    api_get_entity_id((ENTITY*)(c1->verts[0]), id1);
+    api_get_entity_id((ENTITY*)(c2->verts[0]), id2);
+    return (id1 < id2);
+  }
+};
+
+class AcisTopologyTool
+{
+  public:
+
+    //Constructor
+    AcisTopologyTool(){};
+
+    //Destructor
+    virtual ~AcisTopologyTool(){};
+
+
+  CubitStatus remove_topology(BODY *&body,
+                              DLIList<EDGE*> &edges_to_remove,
+                              DLIList<FACE*> &faces_to_remove,
+                              double backoff_distance,
+                              double small_edge_size);
+
+private:
+
+  ATTRIB_SNL_SIMPLE* find_named_att(ENTITY* ent, const char *name);
+  void add_named_att(ENTITY* ent, const char *name_in);
+  void remove_att(ENTITY* ent, ATTRIB_SNL_SIMPLE *att);
+  CubitStatus combine_old_body_and_new_faces(BODY *&b, DLIList<FACE*> &new_faces);
+  VERTEX* new_vert_from_pos(const SPAposition &pos);
+  CubitStatus build_clump_topology(DLIList<VERTEXClump*> &clumps);
+  void tangent_indir( FACE *FACE_ptr, EDGE *EDGE_ptr,
+                              const SPAposition &acis_pos, SPAunit_vector &in_dir );
+  int is_roughly_straight_curve_wrt_surf(EDGE *cur_edge, FACE *cur_face);
+  FACE* find_keep_face(EDGE *edge, VERTEX *vert, DLIList<FACE*> &dead_faces);
+  EDGE* imprint_new_edge_on_face(FACE *face, VERTEX *v1, VERTEX *v2);
+  double angle_between(FACE *face, EDGE *e1, VERTEX *v1, EDGE *e2, VERTEX *v2);
+  EDGE* get_other_edge(EDGE *edge, VERTEX *vert, FACE *face);
+  VERTEX* other_vertex(EDGE *edge, VERTEX *vert);
+  void get_next_edge_around_clump(EDGE *cur_edge, VERTEX *cur_vert,
+                              FACE *cur_face, 
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              EDGE *&next_edge, VERTEX *&next_vert);
+  CubitStatus generate_faces_for_non_lateral_edge(FACE *&face, EDGE *edge,
+                              double &backoff_distance, 
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              DLIList<VERTEX*> &processed_verts,
+                              DLIList<EDGE*> &processed_edges,
+                              DLIList<EDGE*> &edges_to_imprint,
+                              DLIList<FACE*> &new_vol_faces,
+                              DLIList<FACE*> &dead_faces,
+                              DLIList<SPAposition> &projected_positions);
+  CubitStatus generate_faces_for_lateral_edge(FACE *&face, EDGE *edge,
+                              double &backoff_distance, 
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              DLIList<VERTEX*> &processed_verts,
+                              DLIList<EDGE*> &processed_edges,
+                              DLIList<EDGE*> &edges_to_imprint,
+                              DLIList<FACE*> &new_vol_faces,
+                              DLIList<FACE*> &dead_faces,
+                              DLIList<SPAposition> &projected_positions);
+  int is_lateral_edge(EDGE *edge, std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map);
+  CubitStatus generate_faces_for_surrounding_faces(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              DLIList<FACE*> &new_vol_faces,
+                              DLIList<FACE*> &modified_faces,
+                              double &backoff_distance,
+                              DLIList<FACE*> &dead_faces,
+                              DLIList<SPAposition> &projected_positions);
+  /*
+  void propagate_from_small_edge(EDGE *edge,
+                              DLIList<EDGE*> &small_edges,
+                              DLIList<FACE*> &processed_faces,
+                              double small_edge_length);
+                              */
+  CubitStatus generate_faces_for_surrounding_face(FACE *face,
+                              double &backoff_distance, 
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              DLIList<FACE*> &processed_faces,
+                              DLIList<FACE*> &modified_faces,
+                              DLIList<FACE*> &new_vol_faces,
+                              DLIList<FACE*> &dead_faces,
+                              DLIList<SPAposition> &projected_positions);
+  CubitStatus split_all_curves_coming_into_clumps(DLIList<VERTEXClump*> &clumps,
+                              std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              double &backoff_distance, DLIList<SPAposition> &split_positions);
+  CubitStatus adjust_backoff_distance(DLIList<VERTEXClump*> &clumps,
+                              std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              double &backoff_distance);
+  CubitStatus find_new_edges_between_clumps(DLIList<VERTEXClump*> &clumps,
+                              std::map <EDGE*, EDGE*, mapltid> &old_edge_to_new_edge_map,
+                              std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map);
+  CubitStatus find_new_pos_for_clump(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                              DLIList<FACE*> &faces_to_move,
+                              double &size);
+  EDGE* find_common_edge (FACE *f1, FACE *f2);
+  EDGE* find_common_edge (VERTEX *v1, VERTEX *v2);
+  CubitStatus choose_best_face_to_move(DLIList<FACE*> &faces_that_might_move,
+                              std::map <FACE*, int, mapltid> &face_clump_count_map,
+                              DLIList<VERTEX*> &all_verts_in_clumps);
+  CubitStatus ensure_possible_solution(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &faces_that_dont_intersect_map,
+                              DLIList<FACE*> &faces_that_might_move);
+  CubitStatus find_faces_that_dont_intersect(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                              std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &faces_that_dont_intersect_map,
+                              double &small_dist);
+  CubitStatus find_face_clump_counts(std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                              std::map <FACE*, int, mapltid> &face_clump_count_map);
+  int edge_within_clump(EDGE *edge,
+                              std::map <VERTEX*,VERTEXClump*, mapltid> &old_vertex_to_clump_map);
+  void point_perp_trimmed(EDGE *edge, 
+                              SPAposition &pos_in,
+                              SPAposition &pos_out,
+                              double *param);
+  /*
+  int narrow_region_exists(EDGE *e1,
+                              EDGE *e2,
+                              FACE *face,
+                              const double &tol,
+                              DLIList<SPAposition*> &e1_pos_list,
+                              DLIList<SPAposition*> &e2_pos_list,
+                              DLIList<VERTEX*> &e1_vert_list,
+                              DLIList<VERTEX*> &e2_vert_list);
+  int narrow_region_exists(FACE *face, const double &tol);
+  int is_narrow_region_at_point(EDGE *e1,
+                              SPAposition &pt_on_e1,
+                              EDGE *e2,
+                              const double &tol_sq,
+                              SPAposition &closest);
+                              */
+  CubitStatus find_faces_surrounding_clumps(DLIList<VERTEXClump*> &clumps,
+                              std::map <VERTEXClump*, DLIList<FACE*>*, mapltclump> &surrounding_faces_map,
+                              DLIList<VERTEX*> &all_verts_in_clumps,
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map,
+                              DLIList<FACE*> &faces_to_remove);
+  void find_ave_clump_pos(VERTEXClump *&clump);
+  CubitStatus get_all_verts_in_clumps(DLIList<VERTEXClump*> &clumps,
+                              DLIList<VERTEX*> &all_verts_in_clumps);
+  void build_old_vertex_to_clump_map(DLIList<VERTEXClump*> &clumps,
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map);
+  void get_neighbor_small_edges(EDGE *edge,
+                              VERTEX *vert,
+                              VERTEXClump *&clump,
+                              DLIList<EDGE*> &small_edges);
+  /*
+  void propagate_to_find_other_small_edges(EDGE *edge, 
+                              VERTEX *cur_vert, 
+                              DLIList<EDGE*> &small_edges, 
+                              double small_edge_length);
+  void propagate_over_narrow_face(FACE *narrow_face,
+                              EDGE *edge,
+                              DLIList<FACE*> &processed_faces,
+                              DLIList<EDGE*> &small_edges,
+                              double small_edge_length);
+                              */
+  CubitStatus setup_clump_map(DLIList<EDGE*> &edges_to_remove,
+                              DLIList<FACE*> &faces_to_remove,
+                              double small_edge_size,
+                              DLIList<VERTEXClump*> &clumps, 
+                              std::map <VERTEX*, VERTEXClump*, mapltid> &old_vertex_to_clump_map);
+
+};
+
+#endif

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -9,40 +9,7 @@
 #ifdef UNIX_PORT
 #include "undefwin_.h"
 #endif
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/acis.hxx"
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/geom/point.hxx"
-#include "kernel/kerndata/geom/transfrm.hxx"
-#include "kernel/kerndata/top/edge.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#include "kernel/kerndata/top/face.hxx"
-#include "kernel/kerndata/top/loop.hxx"
-#include "kernel/kerndata/top/wire.hxx"
-#include "kernel/kernutil/law/law.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "kernel/spline/api/spl_api.hxx"
-#include "cover/kernapi/api/coverapi.hxx"
-#include "blend/kernapi/api/blendapi.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "constrct/kernapi/api/cstrapi.hxx"
-#include "skin/kernapi/api/skinapi.hxx"
-#include "offset/kernapi/api/ofstapi.hxx"
-#include "boolean/kernapi/api/boolapi.hxx"
-#include "baseutil/vector/position.hxx"
-#include "baseutil/vector/unitvec.hxx"
-#include "baseutil/logical.h"
 
-#ifdef ACIS_LOCAL_OPS
-  #include "lop_husk/api/lop_api.hxx"
-  #include "lopt_husk/api/loptapi.hxx"
-  #include "rem_husk/api/rem_api.hxx"
-#endif
-
-#include "kernel/geomhusk/copyent.hxx" // copy single entity
-
-#else
 #include "acis.hxx"
 #include "api.hxx"
 #include "kernapi.hxx"
@@ -52,6 +19,8 @@
 #include "coedge.hxx"
 #include "loop.hxx"
 #include "face.hxx"
+#include "shell.hxx"
+#include "lump.hxx"
 #include "body.hxx"
 #include "wire.hxx"
 #include "law.hxx"
@@ -77,10 +46,12 @@
 #include "utils.hxx" // sg_body_to_1d
 #include "heal_api.hxx"
 #include "rbi_api.hxx"
+#include "at_real.hxx"
+//#include "insanity_list.hxx" // api_check_entity
+#include "warp_api.hxx"
+#include "posarray.hxx"
 
-#if CUBIT_ACIS_VERSION >= 1600
 #include "lop_opts.hxx"
-#endif
 
 #ifdef ACIS_LOCAL_OPS
   #include "lop_api.hxx"
@@ -90,7 +61,6 @@
 
 #include "copyent.hxx" // copy_single_entity
 #include "acistype.hxx" // is_closed_solid_body
-#endif
 
 #ifdef UNIX_PORT
 #include "defwin_.h"
@@ -99,7 +69,7 @@
 
 // ********** BEGIN CUBIT INCLUDES            **********
 #include "AcisTweakTool.hpp"
-
+#include "AcisTopologyTool.hpp"
 #include "AcisQueryEngine.hpp"
 #include "AcisModifyEngine.hpp"
 #include "GeometryQueryTool.hpp"
@@ -112,17 +82,24 @@
 #include "PointACIS.hpp"
 
 #include "DLIList.hpp"
+#include "GfxDebug.hpp"
 
 #include "attrib_cubit_owner.hpp"
 
 #include "CubitUtil.hpp"
 
-#include "GfxDebug.hpp"
 #include "GfxPreview.hpp"
+//#include "GfxDebug.hpp"
 #include "AcisDrawTool.hpp"
 #include "CubitPlane.hpp"
 #include "GMem.hpp"
 
+#include "RandomMersenne.hpp"
+#include <time.h>
+
+#define MSG if(silent==CUBIT_FALSE)
+//#define GfxPreview GfxDebug
+
 // ********** END CUBIT INCLUDES              **********
 
 AcisTweakTool* AcisTweakTool::instance_ = 0;
@@ -149,6 +126,8 @@
    // For convenience, setup pointers to AcisQueryEngine and AcisModifyEngine
    AQE = AcisQueryEngine::instance();
    AME = AcisModifyEngine::instance();
+
+   silent = CUBIT_FALSE;
 }
 
 AcisTweakTool::~AcisTweakTool()
@@ -160,8248 +139,325 @@
   api_terminate_blending();
 }
 
-//=============================================================================
-// Function   : tweak_chamfer
-// Member Type: PUBLIC
-// Description: Chamfer curves on solid bodies.  The left and right offsets are
-//              with respect to the curve direction.  If the given right offset
-//              is negative, the left offset is used.  Users can preview to
-//              clarify the meaning of left and right.
-// Author     : Eric Nielsen
-// Date       :
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_chamfer( DLIList<Curve*> &curve_list,
-                              double left_offset,
-                              DLIList<BodySM*> &new_bodysm_list,
-                              double right_offset,
-                              CubitBoolean keep_old_body,
-                              CubitBoolean preview )
+CubitStatus AcisTweakTool::tweak_bend( DLIList<BodySM*> &bend_bodies,
+	                      DLIList<BodySM*> &new_bodysm_list,
+	                      CubitVector& neutral_root,
+	                      CubitVector& bend_axis,
+	                      CubitVector& bend_direction,
+                          double radius,
+                          double angle,
+                          DLIList<CubitVector*> bend_regions,
+                          double width /*= -1*/,
+                          CubitBoolean center_bend /*= CUBIT_FALSE*/,
+                          int num_points /*= 0*/,
+                          CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                          CubitBoolean preview /*= CUBIT_FALSE*/)
 {
-  int i;
-  outcome result;
+    /*
+    http://doc.spatial.com/r19/index.php/Entity_Bending
+    outcome api_bend_entity  ( ENTITY *  in_entity,  
+                              SPAposition &  neutral_root,  
+                              SPAunit_vector &  bend_axis,  
+                              SPAunit_vector &  bend_direction,  
+                              double  radius,  
+                              double  angle,  
+                              double  width = -1,  
+                              logical  f_center_bend = FALSE,  
+                              int  n_points = 0,  
+                              SPAposition *  bend_regions = NULL,  
+                              AcisOptions *  opts = NULL   
+                             )
+    */
+    int i = 0;
+    int delete_attribs =
+        (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
 
-  BodySM *body_ptr;
-
-  BODY *BODY_ptr;
-  BODY *copied_BODY_ptr;
-
-  int delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  if( right_offset <= 0.0 )
-    right_offset = left_offset;
-
-  // Copy the incoming ref_edge_list since we will be pulling
-  // edges out of it.
-  DLIList<CurveACIS*> copied_ref_edge_list(curve_list.size());
-  CAST_LIST( curve_list, copied_ref_edge_list, CurveACIS );
-  if (curve_list.size() != copied_ref_edge_list.size())
-  {
-    PRINT_ERROR("Non-ACIS Curve found\n");
-    return CUBIT_FAILURE;
-  }
-
-  copied_ref_edge_list.reset();
-  while( copied_ref_edge_list.size() )
-  {
-    DLIList<EDGE*> EDGE_list;
-    if( AME->get_copied_EDGES_of_body( copied_ref_edge_list, EDGE_list,
-      copied_BODY_ptr ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Get original Body and BODY
-    body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-    BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-    // Now, blend the edges on this body
-    if( chamfer_edges( EDGE_list, left_offset, right_offset ) == CUBIT_FAILURE )
-    {
-      api_delent(copied_BODY_ptr);
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    if( !preview )
-    {
-      // If we've made it this far, the copied_BODY has been
-      // modified and we can update it in CUBIT
-
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( copied_BODY_ptr );
-
-      BodySM* new_body_ptr = AME->get_new_Body( body_ptr, BODY_ptr,
-        copied_BODY_ptr, keep_old_body );
-
-      if( new_body_ptr )
-        new_bodysm_list.append( new_body_ptr );
-    }
-    else
-    {
-      GfxPreview::clear(); // should previews always be cleared?
-
-      ENTITY_LIST face_list;
-      api_get_faces( copied_BODY_ptr, face_list);
-      AcisBridge *ab_face_ptr = NULL;
-      for( i=0; i<face_list.count(); i++ )
-      {
-        ab_face_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( face_list[i] );
-        if( !ab_face_ptr )
-        {
-          // Draw this face
-          AcisDrawTool::instance()->draw_FACE( (FACE*)face_list[i], CUBIT_BLUE );
-        }
-      }
-
-      api_delent(copied_BODY_ptr);
-    }
-  }
-
-  if( preview )
-    GfxPreview::flush();
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_chamfer
-// Member Type: PUBLIC
-// Description: Chamfer vertices on solid or sheet bodies.  On a solid body
-//              there can be up to 3 offsets; on a sheet body up to 2 offsets.
-//              The offsets are in the direction of the supplied edges.  If
-//              multiple vertices are supplied, only one offset value is
-//              allowed and the edges are not used.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_chamfer( DLIList<Point*> &point_list,
-                              double offset1,
-                              DLIList<BodySM*> &new_bodysm_list,
-                              Curve *edge1,
-                              double offset2,
-                              Curve *edge2,
-                              double offset3,
-                              Curve *edge3,
-                              CubitBoolean keep_old_body,
-                              CubitBoolean preview )
-{
-  // Sort out vertices between sheet and solid bodies
-  DLIList<Point*> solid_points, sheet_points;
-  if( sort_points_by_body_type( point_list, solid_points, sheet_points ) ==
-    CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  // Do simple forms
-  if( edge1 == NULL || offset2 <= 0.0 )
-  {
-    if( tweak_chamfer_solid( solid_points, offset1, new_bodysm_list,
-      keep_old_body, preview )== CUBIT_FAILURE )
-      return CUBIT_FAILURE;
-    return tweak_chamfer_fillet_sheet( sheet_points, offset1, 1,
-      new_bodysm_list, keep_old_body, preview );
-  }
-
-  if( solid_points.size() > 1 || sheet_points.size() > 1 )
-  {
-    PRINT_ERROR( "cannot chamfer multiple vertices with a variable radius.\n" );
-    return CUBIT_FAILURE;
-  }
-
-  if( solid_points.size() )
-  {
-    Point *point_ptr = solid_points.get();
-    BodySM *bodysm_ptr = NULL;
-
-    if( tweak_chamfer_solid( point_ptr, offset1, edge1, offset2, edge2,
-      offset3, edge3, bodysm_ptr, keep_old_body, preview ) == CUBIT_FAILURE )
-      return CUBIT_FAILURE;
-
-    new_bodysm_list.append( bodysm_ptr );
-    return CUBIT_SUCCESS;
-  }
-
-  if( sheet_points.size() )
-  {
-    Point *point_ptr = sheet_points.get();
-    BodySM *bodysm_ptr = NULL;
-
-    if( tweak_chamfer_sheet( point_ptr, offset1, edge1, offset2, edge2,
-      bodysm_ptr, keep_old_body, preview ) == CUBIT_FAILURE )
-      return CUBIT_FAILURE;
-
-    new_bodysm_list.append( bodysm_ptr );
-    return CUBIT_SUCCESS;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_fillet
-// Member Type: PUBLIC
-// Description: Create a round fillet (or blend) at the given curves on solid
-//              bodies.
-// Author     : Eric Nielsen
-// Date       :
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_fillet( DLIList<Curve*> &curve_list,
-                             double radius,
-                             DLIList<BodySM*> &new_bodysm_list,
-                             bool keep_old_body,
-                             CubitBoolean preview )
-{
-  int i;
-  outcome result;
-
-  BodySM *body_ptr;
-
-  BODY *BODY_ptr;
-  BODY *copied_BODY_ptr;
-
-  int delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Copy the incoming ref_edge_list since we will be pulling
-  // edges out of it.
-  DLIList<CurveACIS*> copied_ref_edge_list(curve_list.size());
-  CAST_LIST( curve_list, copied_ref_edge_list, CurveACIS );
-  if (curve_list.size() != copied_ref_edge_list.size())
-  {
-    PRINT_ERROR("Non-ACIS Curve encountered\n");
-    return CUBIT_FAILURE;
-  }
-
-  copied_ref_edge_list.reset();
-  while( copied_ref_edge_list.size() )
-  {
-    DLIList<EDGE*> EDGE_list;
-    if( AME->get_copied_EDGES_of_body( copied_ref_edge_list, EDGE_list,
-      copied_BODY_ptr ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Get original Body and BODY
-    body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-    BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-    if( blend_edges( EDGE_list, radius ) == CUBIT_FAILURE )
-    {
-      AQE->ACIS_API_error(result);
-      api_delent(copied_BODY_ptr);
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    if( !preview )
-    {
-      // If we've made it this far, the copied_BODY has been
-      // modified and we can update it in CUBIT
-
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
-
-      BodySM* new_body_ptr = AME->get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr,
-        keep_old_body );
-
-      if (new_body_ptr)
-        new_bodysm_list.append( new_body_ptr );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      ENTITY_LIST face_list;
-      api_get_faces( copied_BODY_ptr, face_list);
-      AcisBridge *ab_face_ptr = NULL;
-      for( i=0; i<face_list.count(); i++ )
-      {
-        ab_face_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( face_list[i] );
-        if( !ab_face_ptr )
-        {
-          // Draw this face
-          AcisDrawTool::instance()->draw_FACE( (FACE*)face_list[i], CUBIT_BLUE );
-        }
-      }
-
-      api_delent(copied_BODY_ptr);
-    }
-  }
-
-  if( preview )
-    GfxPreview::flush();
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_fillet
-// Member Type: PUBLIC
-// Description: Create a round fillet (or blend) at the given curves on a solid
-//              body.  The fillet has a variable radius from the start to the
-//              end of the curve.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_fillet( Curve *curve_ptr,
-                                         double start_radius,
-                                         double end_radius,
-                                         BodySM *&new_bodysm_ptr,
-                                         CubitBoolean keep_old_body,
-                                         CubitBoolean preview )
-{
-  outcome result;
-
-  BodySM *body_ptr;
-
-  BODY *BODY_ptr;
-  BODY *copied_BODY_ptr;
-
-  int delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  DLIList<CurveACIS*> copied_curve_list(1);
-  CurveACIS *curve_acis_ptr = CAST_TO( curve_ptr, CurveACIS );
-  if( curve_acis_ptr == NULL )
-  {
-    PRINT_ERROR("Non-ACIS Curve encountered\n");
-    return CUBIT_FAILURE;
-  }
-  copied_curve_list.append( curve_acis_ptr );
-
-  DLIList<EDGE*> EDGE_list;
-  if( AME->get_copied_EDGES_of_body( copied_curve_list, EDGE_list,
-    copied_BODY_ptr ) == CUBIT_FAILURE )
-  {
-    return CUBIT_FAILURE;
-  }
-
-  // Get original Body and BODY
-  body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-  BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-  EDGE *EDGE_ptr = EDGE_list.get();
-  ENTITY_LIST ENTITY_list;
-  ENTITY_list.add( EDGE_ptr );
-
-  int num_fixes = 2;
-  SPAposition pos_array[2];
-  pos_array[0] = EDGE_ptr->start_pos();
-  pos_array[1] = EDGE_ptr->end_pos();
-
-  double fix_radii[2] = { start_radius, end_radius };
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( copied_BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Now, blend the edges on this body
-  result = api_blend_edges_pos_rad( ENTITY_list, num_fixes, pos_array, fix_radii );
-
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error(result);
-    api_delent(copied_BODY_ptr);
-    return CUBIT_FAILURE;
-  }
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( copied_BODY_ptr, "tweak", 
-    pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove tweak attributes
-  remove_named_attribs( copied_BODY_ptr, "tweak" );
-
-  if( !preview )
-  {
-    // If we've made it this far, the copied_BODY has been
-    // modified and we can update it in CUBIT
-
-    // Now cleanout the owner attributes from the copied BODY, if required
-    if( delete_attribs )
-      AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
-
-    new_bodysm_ptr = AME->get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr,
-      keep_old_body );
-  }
-  else
-  {
+    // Clear any previous previews
     GfxPreview::clear();
 
-    ENTITY_LIST face_list;
-    api_get_faces( copied_BODY_ptr, face_list);
-    AcisBridge *ab_face_ptr = NULL;
-    int i;
-    for( i=0; i<face_list.count(); i++ )
+    position_array regions;
+    for (i = 0; i < num_points; i++)
     {
-      ab_face_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( face_list[i] );
-      if( !ab_face_ptr )
-      {
-        // Draw this face
-        AcisDrawTool::instance()->draw_FACE( (FACE*)face_list[i], CUBIT_BLUE );
-      }
+        CubitVector* vector = bend_regions.get_and_step();
+				SPAposition pos(vector->x(), vector->y(), vector->z());
+        regions.Add(pos);
     }
 
-    api_delent(copied_BODY_ptr);
+    outcome result;
 
-    GfxPreview::flush();
-  }
+    BODY* BODY_ptr;
+    BODY* copied_BODY_ptr;
+    BodySM* body_ptr;
 
-  return CUBIT_SUCCESS;
-}
+    SPAposition acis_neutral_root(neutral_root.x(), neutral_root.y(), neutral_root.z());
+    SPAunit_vector acis_bend_axis(bend_axis.x(), bend_axis.y(), bend_axis.z());
+    SPAunit_vector acis_bend_direction(bend_direction.x(), bend_direction.y(), bend_direction.z());
 
-//=============================================================================
-// Function   : tweak_fillet
-// Member Type: PUBLIC
-// Description: Create a round fillet (or blend) at the given vertices on sheet
-//              bodies.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_fillet( DLIList<Point*> &point_list,
-                                         double radius,
-                                         DLIList<BodySM*> &new_bodysm_list,
-                                         CubitBoolean keep_old_body,
-                                         CubitBoolean preview )
-{
-  return tweak_chamfer_fillet_sheet( point_list, radius, 2, new_bodysm_list,
-    keep_old_body, preview );
-}
-
-//=============================================================================
-// Function   : tweak_move
-// Member Type: PUBLIC
-// Description: Tweak specified faces of a volume or volumes along a vector.
-// Author     : Steve Storm
-// Date       :
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_move( DLIList<Surface*> &surface_list,
-                                       const CubitVector &delta,
-                                       DLIList<BodySM*> &new_bodysm_list,
-                                       CubitBoolean keep_old_body,
-                                       CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for moving\n"
-    "       surfaces.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  int i;
-  int num_faces = 0;
-
-  BodySM* body_ptr;
-
-  BODY* BODY_ptr;
-  BODY* copied_BODY_ptr;
-  outcome result;
-
-  // Setup translation transform
-  SPAtransf tr;
-  SPAvector vec(delta.x(), delta.y(), delta.z() );
-  tr = translate_transf( vec );
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Copy the incoming surface_list since we will be pulling
-  // surfaces out of it.
-  DLIList<SurfaceACIS*> copied_surface_list( surface_list.size() );
-  if (!get_ACIS_surfaces( surface_list, copied_surface_list ))
-    return CUBIT_FAILURE;
-
-  copied_surface_list.reset();
-  while( copied_surface_list.size() )
-  {
-    DLIList<FACE*> FACE_list;
-    if( AME->get_copied_FACES_of_body( copied_surface_list, FACE_list,
-      copied_BODY_ptr ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Get original Body and BODY
-    body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-    BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-    // Store moved FACEs for preview
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview ) get_owner_list( FACE_list, preview_ab_list );
-
-    // Now, move the surfaces on this body
-    num_faces = FACE_list.size();
-    FACE** move_FACES = new FACE*[num_faces];
-    for( i=0; i<num_faces; i++ )
-      move_FACES[i] = FACE_list.get_and_step();
-
-    SPAposition box_l(0,0,0);
-    SPAposition box_h(0,0,0);
-
-    // Setup tweak attributes so we can preserve Cubit owners
-    DLIList<FACE*> pre_FACE_list;
-    DLIList<EDGE*> pre_EDGE_list;
-    DLIList<VERTEX*> pre_VERTEX_list;
-    DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-    // This operation sometimes destroys owner attributes
-    AcisBridge *ab_body_ptr;
-    AcisBridge *ab_lump_ptr;
-    AcisBridge *ab_shell_ptr;
-    if( !delete_attribs )
-    {
-      assign_tweak_attribs( copied_BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-         pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-      get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-    }
-
-    result = api_move_faces( num_faces, move_FACES, tr, box_l, box_h );
-
-    delete [] move_FACES;
-
-    // Replace Cubit owners
-    if( !delete_attribs )
-    {
-      reassign_cubit_owners_from_tweak_attribs( copied_BODY_ptr, "tweak",
-        pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-        ab_VERTEX_list );
-      reset_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
     
-      // Remove tweak attributes
-      remove_named_attribs( copied_BODY_ptr, "tweak" );
-    }
-
-    if( !result.ok() )
+    for (i = 0; i < bend_bodies.size(); i++)
     {
-      AQE->ACIS_API_error(result);
-      api_delent(copied_BODY_ptr);
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
+        body_ptr = bend_bodies.get_and_step();
+        BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
 
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
-
-      // If we've made it this far, the copied_BODY has been
-      // modified and we can update it in CUBIT
-      BodySM* new_body_ptr = 
-        AME->get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr, keep_old_body );
-
-      if( new_body_ptr )
-        new_bodysm_list.append( new_body_ptr );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      // Draw preview EDGEs
-      draw_tweak_preview_omt( copied_BODY_ptr, CUBIT_TRUE, &preview_ab_list );
-      api_delent( copied_BODY_ptr );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_move
-// Member Type: PUBLIC
-// Description: Tweak specified curves of a sheet body along a vector.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_move( DLIList<Curve*> &input_curve_list,
-                                       const CubitVector &delta,
-                                       DLIList<BodySM*> &new_bodysm_list,
-                                       CubitBoolean keep_old_bodies,
-                                       CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for tweaking\n"
-    "       curves.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  int i, j;
-  outcome result;
-
-  // Setup translation transform
-  SPAtransf tr;
-  SPAvector vec(delta.x(), delta.y(), delta.z() );
-  tr = translate_transf( vec );
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_bodies);
-
-  // Get ACIS EDGEs
-  DLIList<EDGE*> input_EDGE_list;
-  if( get_EDGEs( input_curve_list, input_EDGE_list )== CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  input_EDGE_list.reset();
-  while( input_EDGE_list.size() )
-  {
-    BODY *BODY_ptr;
-    DLIList<EDGE*> removed_EDGE_list;
-    DLIList<BODY*> thickened_BODY_list;
-    DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-    DLIList<DLIList<FACE*>*> output_FACE_lists;
-    DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-    if( get_thickened_BODIES_of_EDGES( "tweak", input_EDGE_list,
-      removed_EDGE_list, BODY_ptr, thickened_BODY_list, output_EDGE_lists,
-      output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    BodySM *bodysm_ptr = AQE->get_body_sm_of_ENTITY( BODY_ptr );
-
-    // Remove the surfaces on the output BODIEs
-    // First copy the BODY
-    BODY *copied_BODY_ptr = AME->copy_BODY(BODY_ptr, CUBIT_FALSE);
-
-    // Store moved EDGEs for preview
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview ) get_owner_list( removed_EDGE_list, preview_ab_list );
-
-    int num_faces;
-    BODY *thickened_BODY_ptr;
-    DLIList<FACE*> *output_FACE_list_ptr;
-    DLIList<FACE*> *conjugate_FACE_list_ptr;
-    thickened_BODY_list.reset();
-    output_EDGE_lists.reset();
-    output_FACE_lists.reset();
-    conjugate_FACE_lists.reset();
-    for( i=thickened_BODY_list.size(); i--; )
-    {
-      thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-      output_FACE_list_ptr = output_FACE_lists.get_and_step();
-      conjugate_FACE_list_ptr = conjugate_FACE_lists.get_and_step();
-
-      // Note - the conjugate FACE list can have duplicate entries in
-      // it, as thicken doesn't always create a separate surface for
-      // each curve.
-      DLIList<FACE*> tweak_FACE_list;
-      conjugate_FACE_list_ptr->reset();
-      for( j=conjugate_FACE_list_ptr->size(); j--; )
-        tweak_FACE_list.append_unique( conjugate_FACE_list_ptr->get_and_step() );
-
-      // Keep track of the FACEs of interest, via their Cubit owners, which
-      // will survive throughout the operation
-      DLIList<AcisBridge*> owner_list;
-      get_owner_list( *output_FACE_list_ptr, owner_list );
-
-      num_faces = tweak_FACE_list.size();
-
-      FACE** FACES = new FACE*[num_faces];
-      output_FACE_list_ptr->reset();
-      for( j=0; j<num_faces; j++ )
-        FACES[j] = tweak_FACE_list.get_and_step();
-
-      SPAposition box_l(0,0,0);
-      SPAposition box_h(0,0,0);
-
-      result = api_move_faces( num_faces, FACES, tr, box_l, box_h );
-
-      delete [] FACES;
-
-      if( !result.ok() )
-      {
-        AQE->ACIS_API_error(result);
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Get bodies ready to swap new surfaces for old
-      if( prep_for_surface_swap( thickened_BODY_ptr, copied_BODY_ptr,
-        owner_list ) == CUBIT_FAILURE )
-      {
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-    } // End loop on thickened (separated) BODIES
-
-    // Free memory
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-    while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-    while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-    // Unite the thickened BODIEs back into the copied_BODY_ptr
-    BODY *master;
-    if( unite_BODIES( copied_BODY_ptr, thickened_BODY_list, master ) == CUBIT_FAILURE )
-    {
-      // If failure, the unite_BODIES function cleaned up the memory
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // This BODY is done (whew!)
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( master );
-
-      BodySM *new_body = AME->get_new_Body( bodysm_ptr, BODY_ptr, master,
-        keep_old_bodies );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      // Draw preview EDGEs
-      draw_tweak_preview_omt( copied_BODY_ptr, CUBIT_TRUE, &preview_ab_list );
-      api_delent( master );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_offset
-// Member Type: PUBLIC
-// Description: Tweak specified faces of a volume or volumes by offsetting
-//              those faces by the offset distance.
-// Author     : Steve Storm
-// Date       :
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_offset( DLIList<Surface*> &surface_list,
-                             double offset_distance,
-                             DLIList<BodySM*> &new_bodysm_list,
-                             CubitBoolean keep_old_body,
-                             CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-   PRINT_ERROR( "The ACIS Local Operations Husk is required for offsetting\n"
-      "       surfaces.  It has not been licensed for this installation.\n" );
-   return CUBIT_FAILURE;
-#endif
-
-   int i;
-   outcome result;
-
-   // Copy the incoming surface_list since we will be pulling surfaces out of
-   // it.
-
-   BodySM *body_ptr;
-
-   BODY *BODY_ptr;
-   BODY *copied_BODY_ptr;
-
-   bool delete_attribs =
-      (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-   // Copy the incoming surface_list since we will be pulling surfaces out of
-   // it.
-   DLIList<SurfaceACIS*> copied_surface_list( surface_list.size() );
-   if (!get_ACIS_surfaces( surface_list, copied_surface_list ))
-     return CUBIT_FAILURE;
-
-   copied_surface_list.reset();
-   while( copied_surface_list.size() )
-   {
-     DLIList<FACE*> FACE_list;
-     if( AME->get_copied_FACES_of_body( copied_surface_list, FACE_list,
-       copied_BODY_ptr ) == CUBIT_FAILURE )
-     {
-       // Return success if any bodies were created
-       return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-     }
-
-     // Get original Body and BODY
-     body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-     BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-     // Store offset FACEs for preview
-     DLIList<AcisBridge*> preview_ab_list;
-     if( preview ) get_owner_list( FACE_list, preview_ab_list );
-
-     // Now, offset the surfaces on this body
-     int num_offsets = FACE_list.size();
-     FACE** offset_FACES = new FACE*[num_offsets];
-     for( i=0; i<num_offsets; i++ )
-       offset_FACES[i] = FACE_list.get_and_step();
-
-     SPAposition box_l(0,0,0);
-     SPAposition box_h(0,0,0);
-
-     //This has been added as a temporary fix for bug #5559.
-     //Lump attrib should persist across offset operation, but does not
-     //ENTITY_LIST lump_list;
-     //api_get_lumps(copied_BODY_ptr, lump_list);
-     //AcisBridge *lump_owner_before = ATTRIB_CUBIT_OWNER::cubit_owner(lump_list[0]);
-
-     // Setup tweak attributes so we can preserve Cubit owners
-     DLIList<FACE*> pre_FACE_list;
-     DLIList<EDGE*> pre_EDGE_list;
-     DLIList<VERTEX*> pre_VERTEX_list;
-     DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-     // This operation sometimes destroys owner attributes
-     AcisBridge *ab_body_ptr;
-     AcisBridge *ab_lump_ptr;
-     AcisBridge *ab_shell_ptr;
-     if( !delete_attribs )
-     {
-       assign_tweak_attribs( copied_BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-          pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-       get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-     }
-
-     result = api_offset_faces( num_offsets, offset_FACES, offset_distance,
-                                box_l, box_h );
-     delete [] offset_FACES;
-
-     if( !result.ok() )
-     {
-       AQE->ACIS_API_error(result);
-       api_delent(copied_BODY_ptr);
-       // Return success if any bodies were created
-       return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-     }
-
-     if( !preview )
-     {
-       // Now cleanout the owner attributes from the copied BODY, if required
-       if( delete_attribs )
-         AQE->remove_cubit_owner_attrib_in_BODY( copied_BODY_ptr );
-       else
-       {
-         /*
-         //continued temporary fix for bug #5559
-         lump_list.clear();
-         api_get_lumps(copied_BODY_ptr, lump_list);
-         AcisBridge *lump_owner_after = ATTRIB_CUBIT_OWNER::cubit_owner(lump_list[0]);
-         if( lump_owner_after == NULL )
-           ATTRIB_CUBIT_OWNER::set_cubit_owner( lump_list[0], lump_owner_before );
-           */
-
-         // Replace Cubit owners
-         if( !delete_attribs )
-         {
-           reassign_cubit_owners_from_tweak_attribs( copied_BODY_ptr, "tweak",
-             pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-             ab_VERTEX_list );
-           reset_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-         
-           // Remove tweak attributes
-           remove_named_attribs( copied_BODY_ptr, "tweak" );
-         }
-       }
-
-       BodySM *new_body_ptr = AME->get_new_Body( body_ptr, BODY_ptr,
-         copied_BODY_ptr, keep_old_body );
-
-       if( new_body_ptr )
-         new_bodysm_list.append( new_body_ptr );
-     }
-     else
-     {
-       GfxPreview::clear();
-
-       // Draw preview EDGEs
-       draw_tweak_preview_omt( copied_BODY_ptr, CUBIT_TRUE, &preview_ab_list );
-       api_delent( copied_BODY_ptr );
-     }
-   }
-
-   return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_offset
-// Member Type: PUBLIC
-// Description: Tweak specified curves of a sheet body or bodies by offsetting
-//              those curves by the offset distance.
-// Author     :
-// Date       :
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_offset( DLIList<Curve*> &input_curve_list,
-                                         double offset_distance,
-                                         DLIList<BodySM*> &new_bodysm_list,
-                                         CubitBoolean keep_old_bodies,
-                                         CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for tweaking\n"
-    "       curves.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  int i, j;
-  outcome result;
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_bodies);
-
-  // Get ACIS EDGEs
-  DLIList<EDGE*> input_EDGE_list;
-  if( get_EDGEs( input_curve_list, input_EDGE_list ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  input_EDGE_list.reset();
-  while( input_EDGE_list.size() )
-  {
-    BODY *BODY_ptr;
-    DLIList<EDGE*> removed_EDGE_list;
-    DLIList<BODY*> thickened_BODY_list;
-    DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-    DLIList<DLIList<FACE*>*> output_FACE_lists;
-    DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-    if( get_thickened_BODIES_of_EDGES( "tweak", input_EDGE_list,
-      removed_EDGE_list, BODY_ptr, thickened_BODY_list, output_EDGE_lists,
-      output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Get the BodySM from the BODY
-    BodySM *bodysm_ptr = AQE->get_body_sm_of_ENTITY( BODY_ptr );
-
-    // Remove the surfaces on the output BODIEs
-
-    // Copy the BODY with all owner attributes intact
-    BODY *copied_BODY_ptr = AME->copy_BODY( BODY_ptr, CUBIT_FALSE );
-
-    // Store offset EdGEs for preview
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview ) get_owner_list( removed_EDGE_list, preview_ab_list );
-
-    int num_faces;
-    BODY *thickened_BODY_ptr;
-    DLIList<FACE*> *output_FACE_list_ptr;
-    DLIList<FACE*> *conjugate_FACE_list_ptr;
-    thickened_BODY_list.reset();
-    output_EDGE_lists.reset();
-    output_FACE_lists.reset();
-    conjugate_FACE_lists.reset();
-    for( i=thickened_BODY_list.size(); i--; )
-    {
-      thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-      output_FACE_list_ptr = output_FACE_lists.get_and_step();
-      conjugate_FACE_list_ptr = conjugate_FACE_lists.get_and_step();
-
-      // Note - the conjugate FACE list can have duplicate entries in
-      // it, as thicken doesn't always create a separate surface for
-      // each curve.
-      DLIList<FACE*> tweak_FACE_list;
-      conjugate_FACE_list_ptr->reset();
-      for( j=conjugate_FACE_list_ptr->size(); j--; )
-        tweak_FACE_list.append_unique( conjugate_FACE_list_ptr->get_and_step() );
-
-      // Keep track of the FACEs of interest, via their Cubit owners, which
-      // will survive throughout the operation
-      DLIList<AcisBridge*> owner_list;
-      get_owner_list( *output_FACE_list_ptr, owner_list );
-
-      num_faces = tweak_FACE_list.size();
-
-      FACE** FACES = new FACE*[num_faces];
-      output_FACE_list_ptr->reset();
-      for( j=0; j<num_faces; j++ )
-        FACES[j] = tweak_FACE_list.get_and_step();
-
-      SPAposition box_l(0,0,0);
-      SPAposition box_h(0,0,0);
-
-#ifdef ACIS_LOCAL_OPS
-      result = api_offset_faces( num_faces, FACES, offset_distance,
-       box_l, box_h );
-#endif
-
-      delete [] FACES;
-
-      if( !result.ok() )
-      {
-        AQE->ACIS_API_error(result);
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Get bodies ready to swap new surfaces for old
-      if( prep_for_surface_swap( thickened_BODY_ptr, copied_BODY_ptr,
-        owner_list ) == CUBIT_FAILURE )
-      {
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-    } // End loop on thickened (separated) BODIES
-
-    // Free memory
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-    while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-    while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-    // Unite the thickened BODIEs back into the copied_input_BODY_ptr
-    BODY *master;
-    if( unite_BODIES( copied_BODY_ptr, thickened_BODY_list, master )
-      == CUBIT_FAILURE )
-    {
-      // If failure, the unite_BODIES function cleaned up the memory
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // This BODY is done (whew!)
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( master );
-
-      BodySM *new_body = AME->get_new_Body( bodysm_ptr, BODY_ptr, master,
-        keep_old_bodies );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      // Draw preview EDGEs
-      draw_tweak_preview_omt( master, CUBIT_TRUE, &preview_ab_list );
-      api_delent( master );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_remove
-// Member Type: PUBLIC
-// Description: Function to remove surfaces from a body and then extend the
-//              remaining surfaces to fill the gap or hole.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_remove( DLIList<Surface*> &surface_list,
-                                         DLIList<BodySM*> &new_bodysm_list,
-                                         CubitBoolean extend_adjoining,
-                                         CubitBoolean keep_surface,
-                                         CubitBoolean keep_old_body,
-                                         CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-   if( extend_adjoining )
-   {
-      PRINT_ERROR( "The ACIS Local Operations Husk is required for extending\n"
-            "       adjoining surfaces.  It has not been licensed for this\n"
-            "       installation.\n" );
-      return CUBIT_FAILURE;
-   }
-#endif
-
-   int i;
-   outcome result;
-
-   // Copy the incoming surface_list since we will be pulling
-   // surfaces out of it.
-   DLIList<SurfaceACIS*> copied_surface_list(surface_list.size());
-   if (!get_ACIS_surfaces( surface_list, copied_surface_list ))
-     return CUBIT_FAILURE;
-
-   BodySM *body_ptr;
-
-   BODY *BODY_ptr;
-   BODY *copied_BODY_ptr;
-   FACE *FACE_ptr;
-   ENTITY *copied_entity_ptr;
-   DLIList<FACE*> kept_FACE_list, remove_FACE_list;
-   DLIList<SurfaceACIS*> body_remove_face_list;
-
-   bool delete_attribs =
-     (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-   // Remove sometimes destroys the owner attributes, so we keep track of them
-   AcisBridge *ab_body_ptr;
-   AcisBridge *ab_lump_ptr;
-   AcisBridge *ab_shell_ptr;
-
-   copied_surface_list.reset();
-   while( copied_surface_list.size() )
-   {
-     remove_FACE_list.clean_out();
-     body_remove_face_list.clean_out();
-     if( AME->get_copied_FACES_of_body( copied_surface_list, remove_FACE_list,
-       body_remove_face_list, copied_BODY_ptr ) == CUBIT_FAILURE )
-     {
-       // Return success if any bodies were created
-       return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-     }
-
-     // Get original Body and BODY
-     body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-     BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-     // Now cleanout the owner attributes from the copied BODY, if required
-     if( delete_attribs )
-       AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
-
-     // Keep a copy of the surfaces if required
-     if( keep_surface && !preview )
-     {
-       // Make a copy of the FACES to hold onto
-       for( i=0; i<remove_FACE_list.size(); i++ )
-       {
-         FACE_ptr = remove_FACE_list.get_and_step();
-         copy_single_entity((ENTITY*)FACE_ptr, copied_entity_ptr);
-         kept_FACE_list.append( (FACE*)copied_entity_ptr );
-       }
-     }
-
-     // Finally, remove the faces from this body
-     if( extend_adjoining )
-     {
-       FACE** FACES = new FACE*[remove_FACE_list.size()];
-       for( i=0; i<remove_FACE_list.size(); i++ )
-         FACES[i] = remove_FACE_list.get_and_step();
-
-       // Remove sometimes destroys owner attributes
-       // Setup tweak attributes so we can preserve Cubit owners
-       DLIList<FACE*> pre_FACE_list;
-       DLIList<EDGE*> pre_EDGE_list;
-       DLIList<VERTEX*> pre_VERTEX_list;
-       DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-       if( !delete_attribs )
-       {
-         get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-         assign_tweak_attribs( copied_BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-           pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-       }
-
-       SPAposition box_l(0,0,0);
-       SPAposition box_h(0,0,0);
-
-#ifdef ACIS_LOCAL_OPS
-
-       // Add tweak_preview attributes to adjoining FACEs to remove if needed
-       if( preview )
-         tag_tweak_remove_FACEs_for_preview( copied_BODY_ptr, remove_FACE_list );
-
-#if CUBIT_ACIS_VERSION < 1600
-       // When removing FACEs, we don't want ACIS to regularize the volume.
-       // Here we set the EDGEs not owned by the FACEs being removed as not
-       // mergeable so they persist through the removal operation.
-
-       // Get all the EDGEs on the BODY
-       ENTITY_LIST body_edges;
-       api_get_edges( copied_BODY_ptr, body_edges );
-
-       // Get all the EDGEs on the FACE to remove
-       ENTITY_LIST surf_edges;
-       for( i=0; i<remove_FACE_list.size(); i++ )
-         api_get_edges( remove_FACE_list.get_and_step(), surf_edges );
-
-       // Remove all EDGEs of the FACE to remove
-       body_edges.remove( surf_edges );
-
-       // Set the EDGEs as not mergeable
-       api_set_no_merge_attrib( body_edges );
-#endif
-
-       if( !preview )
-         PRINT_INFO( "Removing %d surface(s) from volume...\n", remove_FACE_list.size() );
-       else
-         PRINT_INFO( "Previewing removal of %d surface(s) from volume...\n", remove_FACE_list.size() );
-
-       result = api_remove_faces( remove_FACE_list.size(), FACES, box_l, box_h );
-
-#if CUBIT_ACIS_VERSION < 1600
-       // Remove the merge attributes
-       body_edges.clear();
-       api_get_edges( copied_BODY_ptr, body_edges );
-       api_remove_no_merge_attrib( body_edges );
-#endif
-
-       delete [] FACES;
-
-       if( !result.ok() )
-       {
-         PRINT_INFO("result was bad....\n");
-         AQE->ACIS_API_error(result);
-         api_delent(copied_BODY_ptr);
-         // Return success if any bodies were created
-         return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-       }
-       else if( !preview )
-         PRINT_INFO( "Successfully removed surfaces from volume\n" );
-       else
-         PRINT_INFO( "Successfully previewed removal of surfaces from volume\n" );
-
-
-       if( !delete_attribs )
-       {
-         reset_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-         
-         // Replace Cubit owners
-         reassign_cubit_owners_from_tweak_attribs( copied_BODY_ptr, "tweak",
-           pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-           ab_VERTEX_list );
-
-         // Remove tweak attributes
-         remove_named_attribs( copied_BODY_ptr, "tweak" );
-       }
-#endif
-     }
-     else
-     {
-       // Just unhook the faces (if previewing do this anyway to check for
-       // errors)
-       for( i=0; i<remove_FACE_list.size(); i++ )
-       {
+        // Copy the BODY 
+        copied_BODY_ptr = AME->copy_BODY(BODY_ptr, CUBIT_FALSE);
         
-         //make sure we're not trying to unhook the last face
-         ENTITY_LIST tmp_face_list;
-         api_get_faces( copied_BODY_ptr, tmp_face_list);
+        result = api_bend_entity(copied_BODY_ptr,
+                        acis_neutral_root,
+                        acis_bend_axis,
+                        acis_bend_direction,
+                        radius,
+                        angle,
+                        width,
+                        center_bend,
+                        num_points,
+                        regions //acis_bend_regions
+                        );
 
-         if( tmp_face_list.count() == 1 )
-         {
-           AcisBridge *tmp_bridge = ATTRIB_CUBIT_OWNER::cubit_owner( copied_BODY_ptr );
-           if( tmp_bridge )
-           {
-             BodyACIS *tmp_acis_body = CAST_TO( tmp_bridge, BodyACIS );
-             Body *tmp_body = CAST_TO(tmp_acis_body->topology_entity(), Body ); 
-             PRINT_WARNING("Will not remove ALL faces from body %d\n", tmp_body->id() ); 
-           }
-           continue;
-         }
-
-         BODY *new_BODY;
-         FACE_ptr = remove_FACE_list.get_and_step();
-
-         result = api_unhook_face( FACE_ptr, new_BODY );
-
-         if( !result.ok() )
-         {
-           AQE->ACIS_API_error(result);
-           api_delent(copied_BODY_ptr);
-           // Return success if any bodies were created
-           return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-         }
-
-         if( preview )
-         {
-           GfxPreview::clear();
-
-           AcisDrawTool::instance()->draw_ENTITY( new_BODY, CUBIT_BLUE,
-           CUBIT_FALSE, CUBIT_TRUE );
-         }
-
-         // This function puts the pulled-off FACE into a sheet
-         // body.  No need to keep this - we copied the surfaces
-         // before if the keep_surface flag is on.
-         api_delent( new_BODY );
-       }
-     }
-
-     // If we are keeping the pulled-off surfaces, just make free RefFaces from
-     // them.
-     if( keep_surface && !preview )
-     {
-       for( i=0; i<kept_FACE_list.size(); i++ )
-       {
-         FACE* kept_FACE = kept_FACE_list.get_and_step();
-         FACE *face_list[1];
-         face_list[0] = kept_FACE;
-         BODY *sheet_BODY_ptr = NULL;
-         result = api_sheet_from_ff( 1, face_list, sheet_BODY_ptr );
-         api_body_to_2d( sheet_BODY_ptr );
-
-         if( !result.ok() )
-         {
-           PRINT_ERROR("Problem with 'keepsurface' option\n" );
-         }
-         else
-         {
-           BodySM *body_ptr = AQE->populate_topology_bridges( sheet_BODY_ptr );
-           DLIList<Surface*> tmp_surfs;
-           body_ptr->surfaces( tmp_surfs );
-           Surface *surface_ptr = tmp_surfs.get();
-           GeometryModifyTool::instance()->make_Body( surface_ptr );
-         }
-       }
-     }
-
-     // If we've made it this far, the copied_BODY has been modified and we can
-     // update it in CUBIT
-     if( !preview )
-     {
-       BodySM *new_body = AME->get_new_Body( body_ptr, BODY_ptr,
-         copied_BODY_ptr, keep_old_body );
-
-       if( new_body )
-         new_bodysm_list.append( new_body );
-     }
-     else if( extend_adjoining ) // Only case we need to preview
-     {
-       GfxPreview::clear();
-
-       draw_tweak_preview_tagged_FACEs( copied_BODY_ptr, CUBIT_TRUE );
-       api_delent( copied_BODY_ptr );
-     }
-   }
-
-   return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_remove
-// Member Type: PUBLIC
-// Description: Function to remove curves from a sheet body and then extend the
-//              remaining curves or fill the gap or hole.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_remove( DLIList<Curve*> &input_curve_list,
-                             DLIList<BodySM*> &new_bodysm_list,
-                             CubitBoolean keep_old_bodies,
-                             CubitBoolean preview )
-{
-  int i, j, k;
-  outcome result;
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_bodies);
-
-  // We have a very efficient way to remove internal loops, so if all curves
-  // being removed on a given body are internal loops, we do that with a
-  // special case first.  We will loop on each set of EDGEs from a common
-  // BODY.
-  DLIList<BODY*> BODY_list;
-  DLIList<DLIList<EDGE*>*> BODY_EDGE_lists;
-  if( get_EDGES_by_BODY( input_curve_list, BODY_list, BODY_EDGE_lists )
-    == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  BODY *BODY_ptr;
-  BodySM *bodysm_ptr;
-  DLIList<EDGE*> *BODY_EDGE_list_ptr;
-  BODY_list.reset();
-  BODY_EDGE_lists.reset();
-  for( i=BODY_EDGE_lists.size(); i--; )
-  {
-    BODY_ptr = BODY_list.get_and_step();
-    BODY_EDGE_list_ptr = BODY_EDGE_lists.get_and_step();
-
-    // Get the BodySM from the BODY
-    bodysm_ptr = AQE->get_body_sm_of_ENTITY( BODY_ptr );
-
-    // Copy the BODY with all owner attributes intact
-    BODY *copied_BODY_ptr = AME->copy_BODY( BODY_ptr, CUBIT_FALSE );
-
-    DLIList<LOOP*> LOOP_list;
-    if( all_complete_internal_loops( *BODY_EDGE_list_ptr, LOOP_list )
-      == CUBIT_SUCCESS )
-    {
-      // Efficiently remove these LOOPS
-
-      // Get the LOOPs to remove on the copied BODY
-      DLIList<AcisBridge*> owner_list;
-      get_owner_list( LOOP_list, owner_list );
-      DLIList<LOOP*> copied_LOOP_list;
-      get_corresponding_LOOP_list( owner_list, copied_BODY_ptr, copied_LOOP_list );
-
-      // Tag EDGEs for preview
-      if( preview )
-      {
-        LOOP *LOOP_ptr;
-        for( j=copied_LOOP_list.size(); j--; )
+        if (!result.ok())
         {
-          LOOP_ptr = copied_LOOP_list.get_and_step();
-          DLIList<EDGE*> LOOP_EDGE_list;
-          AQE->get_EDGEs( LOOP_ptr, LOOP_EDGE_list );
-          tag_tweak_remove_FACEs_for_preview( copied_BODY_ptr, LOOP_EDGE_list );
+            AQE->ACIS_API_error(result);
+            api_delent(copied_BODY_ptr);
+            return CUBIT_FAILURE;
         }
-      }
 
-      if( remove_LOOPs( copied_LOOP_list ) == CUBIT_SUCCESS )
-      {
-        if( !preview )
+        if (!preview)
         {
-          // Now cleanout the owner attributes from the copied BODY, if required
-          if( delete_attribs )
-            AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
+            // Now cleanout the owner attributes from the copied BODY, if required
+            if (delete_attribs)
+                AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
 
-          BodySM *new_body = AME->get_new_Body( bodysm_ptr, BODY_ptr,
-            copied_BODY_ptr, keep_old_bodies );
+            BodySM* new_body_ptr = AME->get_new_Body(body_ptr, BODY_ptr,
+                copied_BODY_ptr, keep_old_body);
 
-          if( new_body )
-            new_bodysm_list.append( new_body );
+            /*BODY* temp_BODY_ptr = dynamic_cast<BodyACIS*>(new_body_ptr)->get_BODY_ptr();
+            AcisDrawTool::instance()->draw_ENTITY( temp_BODY_ptr, CUBIT_BLUE,
+                        CUBIT_TRUE, CUBIT_TRUE );
+            AcisDrawTool::instance()->draw_ENTITY( temp_BODY_ptr, CUBIT_BLUE,
+                        CUBIT_FALSE, CUBIT_TRUE );
+            GfxPreview::flush();//*/
+
+            if (new_body_ptr)
+                new_bodysm_list.append(new_body_ptr);
         }
         else
         {
-          GfxPreview::clear();
+            // draw preview
+            AcisDrawTool::instance()->draw_ENTITY( copied_BODY_ptr, CUBIT_BLUE,
+                        CUBIT_FALSE, CUBIT_TRUE );
 
-          draw_tweak_preview_tagged_FACEs( copied_BODY_ptr, CUBIT_TRUE );
-          api_delent( copied_BODY_ptr );
+            api_delent(copied_BODY_ptr);
         }
-      }
-      else
-      {
-        // Cleanup memory
-        while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
+        
     }
-    // For this BODY, all curves to remove are not complete loops
-    else
-    {
-      // Remove sometimes destroys the owner attributes
-      AcisBridge *ab_body_ptr;
-      AcisBridge *ab_lump_ptr;
-      AcisBridge *ab_shell_ptr;
 
-      BODY *BODY_ptr2;
-      DLIList<EDGE*> removed_EDGE_list;
-      DLIList<BODY*> thickened_BODY_list;
-      DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-      DLIList<DLIList<FACE*>*> output_FACE_lists;
-      DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-      if( get_thickened_BODIES_of_EDGES( "tweak", *BODY_EDGE_list_ptr, 
-        removed_EDGE_list, BODY_ptr2, thickened_BODY_list, output_EDGE_lists,
-        output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-      {
-        // Cleanup memory
-        while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      if( BODY_ptr != BODY_ptr2 )
-      {
-        PRINT_ERROR( "Internal error - please report\n" );
-        // Cleanup memory
-        while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Tag EDGEs for preview
-      if( preview )
-      {
-        thickened_BODY_list.reset();
-        output_EDGE_lists.reset();
-        for( j=output_EDGE_lists.size(); j--; )
-        {
-          DLIList<EDGE*> *EDGE_list_ptr = output_EDGE_lists.get_and_step();
-          BODY *tmp_BODY_ptr = thickened_BODY_list.get_and_step();
-          tag_tweak_remove_FACEs_for_preview( tmp_BODY_ptr, *EDGE_list_ptr );
-        }
-      }
-
-      // Remove the surfaces on the output BODIEs
-
-      int num_faces;
-      BODY *thickened_BODY_ptr;
-      DLIList<FACE*> *output_FACE_list_ptr;
-      DLIList<FACE*> *conjugate_FACE_list_ptr;
-      thickened_BODY_list.reset();
-      output_EDGE_lists.reset();
-      output_FACE_lists.reset();
-      conjugate_FACE_lists.reset();
-      for( j=thickened_BODY_list.size(); j--; )
-      {
-        thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-        output_FACE_list_ptr = output_FACE_lists.get_and_step();
-        conjugate_FACE_list_ptr = conjugate_FACE_lists.get_and_step();
-
-        // Note - the conjugate FACE list can have duplicate entries in
-        // it, as thicken doesn't always create a separate surface for
-        // each curve.
-        DLIList<FACE*> tweak_FACE_list;
-        conjugate_FACE_list_ptr->reset();
-        for( k=conjugate_FACE_list_ptr->size(); k--; )
-          tweak_FACE_list.append_unique( conjugate_FACE_list_ptr->get_and_step() );
-
-        // Keep track of the FACEs of interest, via their Cubit owners, which
-        // will survive throughout the operation
-        DLIList<AcisBridge*> owner_list;
-        get_owner_list( *output_FACE_list_ptr, owner_list );
-
-        num_faces = tweak_FACE_list.size();
-
-        FACE** FACES = new FACE*[num_faces];
-        output_FACE_list_ptr->reset();
-        for( k=0; k<num_faces; k++ )
-          FACES[k] = tweak_FACE_list.get_and_step();
-
-        // Remove sometimes destroys owner attributes
-        get_owner_attribs( thickened_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-        SPAposition box_l(0,0,0);
-        SPAposition box_h(0,0,0);
-
-#ifdef ACIS_LOCAL_OPS
-        result = api_remove_faces( num_faces, FACES, box_l, box_h );
-#endif
-
-        delete [] FACES;
-
-        if( !result.ok() )
-        {
-          AQE->ACIS_API_error(result);
-          while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-          while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-          while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-          while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-          while( thickened_BODY_list.size() )
-            api_delent( thickened_BODY_list.pop() );
-          api_delent( copied_BODY_ptr );
-          // Return success if any bodies were created
-          return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-        }
-
-        // Reset the owner attributes
-        reset_owner_attribs( thickened_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-        // Get bodies ready to swap new surfaces for old
-        if( prep_for_surface_swap( thickened_BODY_ptr, copied_BODY_ptr,
-          owner_list ) == CUBIT_FAILURE )
-        {
-          while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-          while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-          while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-          while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-          while( thickened_BODY_list.size() )
-            api_delent( thickened_BODY_list.pop() );
-          api_delent( copied_BODY_ptr );
-          // Return success if any bodies were created
-          return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-        }
-      } // End loop on thickened (separated) BODIES
-
-      // Free memory
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-      // Unite the thickened BODIEs back into the copied_BODY_ptr
-      BODY *master;
-      if( unite_BODIES( copied_BODY_ptr, thickened_BODY_list, master ) == CUBIT_FAILURE )
-      {
-        // If failure, the unite_BODIES function cleaned up the
-        // thickened_BODY_list memory
-        while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // This BODY is done (whew!)
-
-      if( !preview )
-      {
-        // Now cleanout the owner attributes from the copied BODY, if required
-        if( delete_attribs )
-          AQE->remove_cubit_owner_attrib_in_BODY( master );
-
-        BodySM *new_body = AME->get_new_Body( bodysm_ptr, BODY_ptr, master,
-          keep_old_bodies );
-
-        if( new_body )
-          new_bodysm_list.append( new_body );
-      }
-      else
-      {
-        GfxPreview::clear();
-
-        draw_tweak_preview_tagged_FACEs( master, CUBIT_TRUE );
-        api_delent( master );
-      }
-    }
-  }
-
-  // Free memory
-  while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_target
-// Member Type: PUBLIC
-// Description: Tweak specified faces of a volume or volumes up to a set of
-//              target surfaces.
-// Author     : Steve Storm
-// Date       : 10/27/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_target( DLIList<Surface*> &input_surface_list,
-                                         DLIList<Surface*> &target_surf_list,
-                                         DLIList<BodySM*> &new_bodysm_list,
-                                         CubitBoolean reverse_flg,
-                                         CubitBoolean keep_old_body,
-                                         CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for tweaking\n"
-    "       surfaces to a target.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  if( target_surf_list.size() == 1 )
-  {
-    return tweak_target_single( input_surface_list, target_surf_list.get(),
-      new_bodysm_list, reverse_flg, keep_old_body, preview );
-  }
-  else
-  {
-    return tweak_target_multiple( input_surface_list, target_surf_list,
-      new_bodysm_list, reverse_flg, keep_old_body, preview );
-  }
-}
-
-//=============================================================================
-// Function   : tweak_target_single
-// Member Type: PRIVATE
-// Description: Tweak specified faces of a volume or volumes up to a single
-//              target surface.
-// Author     : Steve Storm
-// Date       :
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_target_single(
-                                         DLIList<Surface*> &input_surface_list,
-                                         Surface *target_surf_ptr,
-                                         DLIList<BodySM*> &new_bodysm_list,
-                                         CubitBoolean reverse_flg,
-                                         CubitBoolean keep_old_body,
-                                         CubitBoolean preview )
-{
-  int i;
-  BODY* copied_BODY_ptr;
-  BODY* BODY_ptr;
-  BodySM* body_ptr;
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Copy the incoming input_surface_list since we will be pulling
-  // surfaces out of it.
-  DLIList<SurfaceACIS*> surface_list( input_surface_list.size() );
-  if (!get_ACIS_surfaces( input_surface_list, surface_list ))
-    return CUBIT_FAILURE;
-
-  // Make sure that the none of the surfaces are sheet bodies (2-sided)
-  for( i=surface_list.size(); i--; )
-  {
-    if( surface_list.get_and_step()->get_FACE_ptr()->sides() == DOUBLE_SIDED )
-    {
-      PRINT_ERROR("Cannot tweak surfaces that do not belong to a closed volume\n");
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Get target FACE
-  Surface *target_surface_ptr = target_surf_ptr;
-  SurfaceACIS *target_surf_acis = dynamic_cast<SurfaceACIS*>( target_surf_ptr );
-  if (!target_surf_acis)
-  {
-    PRINT_ERROR("Target cannot be a non-ACIS Surface.\n");
-    return CUBIT_FAILURE;
-  }
-
-  // Copy the target face (in some cases, the target face can be modified -
-  // if for example it is tweaked to itself, which is sometimes done to
-  // remove unwanted topology or to fix an error).  This preserves the target
-  // in that case.
-  ENTITY *copied_entity_ptr;
-  outcome result = api_copy_entity_contents( target_surf_acis->get_FACE_ptr(),
-    copied_entity_ptr );
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-  FACE *target_FACE_ptr = (FACE *)copied_entity_ptr;
-
-  // This acis api doesn't work exactly as I'd like.  The
-  // only thing that makes sense using it, it seems, is to
-  // tweak multiple surfaces to one surface.
-  DLIList<FACE*> tweak_FACE_list;
-  DLIList<SurfaceACIS*> tweak_surface_list;
-  surface_list.reset();
-  while( surface_list.size() )
-  {
-    // Remove a group of surfaces from surface_list that belong to the same
-    // BODY.  Copy the BODY and put the copied surfaces in tweak_FACE_list.
-    tweak_FACE_list.clean_out();
-    tweak_surface_list.clean_out();
-    if( AME->get_copied_FACES_of_body( surface_list, tweak_FACE_list,
-      tweak_surface_list, copied_BODY_ptr ) == CUBIT_FAILURE )
-    {
-      api_delent( target_FACE_ptr );
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Store source FACEs for preview
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview )
-    {
-      get_owner_list( tweak_FACE_list, preview_ab_list );
-      preview_ab_list.append_unique( 
-        ATTRIB_CUBIT_OWNER::cubit_owner( target_surf_acis->get_FACE_ptr() ) );
-    }
-
-    // Do the tweak
-    if( tweak_FACEs_to_target( tweak_FACE_list, target_FACE_ptr, reverse_flg )
-      == CUBIT_FAILURE )
-    {
-      api_delent( copied_BODY_ptr );
-      api_delent( target_FACE_ptr );
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Get original Body and BODY
-    body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-    BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( copied_BODY_ptr );
-
-      BodySM *new_body = AME->get_new_Body( body_ptr, BODY_ptr,
-        copied_BODY_ptr, keep_old_body );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      // Note the preview_ab_list is used for a special case in the preview -
-      // when the target is a FACE in the BODY itself.
-      draw_tweak_preview_omt( copied_BODY_ptr, CUBIT_TRUE, &preview_ab_list );
-      
-      api_delent( copied_BODY_ptr );
-    }
-  }
-
-  api_delent( target_FACE_ptr );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_target_multiple
-// Member Type: PRIVATE
-// Description: Tweak specified faces of a volume or volumes up to a set of
-//              target surfaces.
-// Author     : Steve Storm
-// Date       : 10/27/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_target_multiple(
-                                         DLIList<Surface*> &input_surface_list,
-                                         DLIList<Surface*> &target_surf_list,
-                                         DLIList<BodySM*> &new_bodysm_list,
-                                         CubitBoolean reverse_flg,
-                                         CubitBoolean keep_old_body,
-                                         CubitBoolean preview )
-{
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Copy the incoming input_surface_list since we will be pulling surfaces out
-  // of it.
-  DLIList<SurfaceACIS*> surface_list( input_surface_list.size() );
-  if (!get_ACIS_surfaces( input_surface_list, surface_list ))
-    return CUBIT_FAILURE;
-
-  // Make sure that the none of the surfaces are sheet bodies (2-sided)
-  int i;
-  for( i=surface_list.size(); i--; )
-  {
-    if( surface_list.get_and_step()->get_FACE_ptr()->sides() == DOUBLE_SIDED )
-    {
-      PRINT_ERROR("Cannot tweak surfaces that do not belong to a solid volume\n");
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Note: target surfaces don't necessarily have to be from same BODY
-
-  // Get target FACEs
-  DLIList<FACE*> target_FACE_list;
-  if( get_FACEs( target_surf_list, target_FACE_list ) == CUBIT_FAILURE )
-  {
-    PRINT_ERROR( "Targets must be ACIS surfaces\n" );
-    return CUBIT_FAILURE;
-  }
-
-  // Get extended target surfaces (in a single sheet BODY)
-  BODY *ext_target_BODY_ptr;
-  if( create_extended_sheet( target_FACE_list, ext_target_BODY_ptr )
-    == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  if( DEBUG_FLAG(168) )
-  {
-    BODY *tmp_BODY = AME->copy_BODY( ext_target_BODY_ptr, CUBIT_TRUE );
-    BodySM *this_bodysm = AcisQueryEngine::instance()->
-      populate_topology_bridges( tmp_BODY );
-    new_bodysm_list.append( this_bodysm );
-  }
-
-  // Tweak the sources to the targets on a per body basis
-  DLIList<FACE*> source_FACE_list;
-  BODY *copied_BODY_ptr;
-  BODY *BODY_ptr;
-  BodySM *body_ptr;
-  surface_list.reset();
-  while( surface_list.size() )
-  {
-    // Remove a group of surfaces from surface_list that belong to the same
-    // BODY. Copy the BODY and put the copied sources in source_FACE_list.
-    source_FACE_list.clean_out();
-    if( AME->get_copied_FACES_of_body( surface_list, source_FACE_list,
-      copied_BODY_ptr ) == CUBIT_FAILURE )
-      break;
-
-    // Get original Body and BODY
-    body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-    BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-    // Store source and target FACEs for preview (necessary especially if
-    // tweaking surfaces on a body to surfaces on the same body)
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview )
-    {
-      get_owner_list( source_FACE_list, preview_ab_list );
-      get_owner_list( target_FACE_list, preview_ab_list );
-    }
-
-    // Tweak the source FACEs up to the target sheet body
-    if( tweak_target_multiple( source_FACE_list, target_FACE_list,
-      ext_target_BODY_ptr, new_bodysm_list, reverse_flg ) == CUBIT_FAILURE )
-    {
-      api_delent( ext_target_BODY_ptr );
-      api_delent( copied_BODY_ptr );
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( copied_BODY_ptr );
-
-      BodySM *new_body = AME->get_new_Body( body_ptr, BODY_ptr,
-        copied_BODY_ptr, keep_old_body );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      // Draw preview EDGEs
-      draw_tweak_preview_omt( copied_BODY_ptr, CUBIT_TRUE, &preview_ab_list );
-      api_delent(copied_BODY_ptr);
-    }
-  }
-
-  api_delent( ext_target_BODY_ptr );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : custom_att_merge_method
-// Member Type: Global
-// Description: Used to mark EDGEs that are merged for tweak_target_multiple
-//              method.  This is a custom merge_owner method for ACIS
-//              generic attributes.
-// Author     : Steve Storm
-// Date       : 3/18/06
-//=============================================================================
-void
-custom_att_merge_method( 
-              ATTRIB_GEN_NAME *att,  // attribute whose owner is being merged 
-              ENTITY *ENTITY_ptr2,   // other entity involved in merge 
-              logical merge_method ) // attribute's owner will be lost?
-{
-  ENTITY *ENTITY_ptr1 = att->entity();
-
-  if( IS_ENTITY_TYPE( ENTITY_ptr1, EDGE ) )
-  {
-    api_add_generic_named_attribute( ENTITY_ptr1, "tweak_merged", 1, SplitCopy );
-    api_add_generic_named_attribute( ENTITY_ptr2, "tweak_merged", 1, SplitCopy );
-  }
-
-  return;
-}
-
-//=============================================================================
-// Function   : tweak_target_multiple
-// Member Type: PRIVATE
-// Description: Tweak specified faces of a volume up to a sheet body
-// Author     : Steve Storm
-// Date       : 10/27/05
-//=============================================================================
-CubitStatus AcisTweakTool::tweak_target_multiple( DLIList<FACE*> &source_FACE_list,
-                                                  DLIList<FACE*> &target_FACE_list,
-                                                  BODY *ext_target_BODY_ptr,
-                                                  DLIList<BodySM*> &debug_BodySM_list,
-                                                  CubitBoolean reverse_flg )
-{
-  // Summary of method:
-  //  1. Check for special case - extended target could contain only one
-  //     surface - if so, use single tweak method.
-  //  2. Assign attributes to side FACEs (FACEs alongside the sources) so that
-  //     we can get back to these FACEs after the tweak.  Since we are cutting
-  //     the body with an extended target, the cutting sheet could cross parts
-  //     of the body we don't want to cut - if it crosses any FACEs without
-  //     these attributes we throw away that portion of the cutting sheet.
-  //  3. Copy the targets into a single sheet BODY.  We will make the surface
-  //     normals consistent in this sheet BODY.  Our method relies on having
-  //     consistent normals on the cutting sheet.  Since when extending the
-  //     target surfaces, cylinders may become full cylinders (i.e., extend
-  //     a planar FACE with one filleted surface adjoining - you will get a
-  //     plane connected to a cylinder), we will ultimately have to remove the
-  //     portions of the cylinder we don't want (remove the "back side" of the
-  //     cylinder).  By computing the average normal of the original target
-  //     surfaces, we will have a good idea as to which side of the extended
-  //     cylinders to keep.
-  //  4. Get weighted average FACE normal of source and target surfaces.
-  //  5. Create a plane just past the targets aligned with the target normal.
-  //     Tweak the source surfaces to this plane (the body is now tweaked past
-  //     the targets).  This is the tweaked BODY.
-  //  6. Make normals in the extended target sheet consistent with the normals
-  //     in #3, since we will need to compare to the extended target sheet
-  //     normals.
-  //  7. Intersect the tweaked BODY (#5) and the extended target sheet - this
-  //     makes a cutting sheet.  Note this cutting sheet may cross parts of the
-  //     BODY where we don't want it to cut.
-  //  8. Imprint so as to score the cutting sheet.
-  //  9. Throw away individual cutting sheet surfaces that don't cross the
-  //     FACEs we want to cut (the side FACEs tracked in #2).
-  // 10. Since the extended target could contain complete cylinders, torii and
-  //     spheres, AND it could cut through other portions of our body, we need
-  //     to do some special handling before just cutting the body with it.  Our
-  //     approach is to trim the extended target body to the desired cutting
-  //     sheet.
-  //     a) Remove periodic surfaces near nonmanifold edges.
-  //     b) Align the normals of the cutting sheet with the extended target
-  //        sheet - again, we need to keep the normals consistent to the
-  //        original targets.
-  //     c) Remove unwanted periodic FACEs on the back of the cutting sheet.
-  //        Since we diligently kept the normals consistent, we can simply
-  //        remove periodic surfaces with normals aligned with the negative
-  //        of the target normal (from #4).
-  // 11. Make sure cutting sheet normal is pointing in opposite direction of
-  //     the source normal.  Note we can tweak forwards or backwards - no
-  //     special handling is needed.
-  // 12. Chopoff the body.
-
-  // Check for special case - if ext_target_BODY_ptr only contains one
-  // FACE, tweak to it and exit.
-  DLIList<FACE*> ext_FACE_list;
-  AQE->get_FACEs( ext_target_BODY_ptr, ext_FACE_list );
-  if( ext_FACE_list.size() == 1 )
-  {
-    FACE *target_FACE_ptr = ext_FACE_list.get();
-    if( tweak_FACEs_to_target( source_FACE_list, target_FACE_ptr, reverse_flg )
-      == CUBIT_FAILURE )
-      return CUBIT_FAILURE;
-
-    return CUBIT_SUCCESS;
-  }
-
-  // Get the BODY the sources are in
-  FACE *FACE_ptr = source_FACE_list.get();
-  BODY *copied_BODY_ptr = AQE->get_BODY_of_ENTITY( FACE_ptr );
-
-  // This operation sometimes destroys owner attributes
-  AcisBridge *ab_body_ptr;
-  AcisBridge *ab_lump_ptr;
-  AcisBridge *ab_shell_ptr;
-  get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // Assign attributes to side FACEs for later use
-  int i, j, k;
-  outcome result;
-  ATTRIB_GEN_NAME *ret_att;
-  for( i=source_FACE_list.size(); i--; )
-  {
-    FACE_ptr = source_FACE_list.get_and_step();
-
-    DLIList<EDGE*> EDGE_list;
-    AQE->get_EDGEs( FACE_ptr, EDGE_list );
-
-    for( j=EDGE_list.size(); j--; )
-    {
-      EDGE *EDGE_ptr = EDGE_list.get_and_step();
-      DLIList<FACE*> attached_FACEs;
-      AQE->get_FACEs( EDGE_ptr, attached_FACEs );
-
-      for( k=attached_FACEs.size(); k--; )
-      {
-        FACE_ptr = attached_FACEs.get_and_step();
-        result = api_find_named_attribute( FACE_ptr, "tweak", ret_att );
-        if( !ret_att )
-        {
-          result = api_add_generic_named_attribute( FACE_ptr, "tweak", 1, SplitCopy );
-          if( !result.ok() )
-          {
-            AQE->ACIS_API_error(result);
-            return CUBIT_FAILURE;
-          }
-        }
-      }
-    }
-  }
-
-  // Remove named attributes from the sources
-  for( i=source_FACE_list.size(); i--; )
-  {
-    FACE_ptr = source_FACE_list.get_and_step();
-    api_remove_generic_named_attribute(FACE_ptr, "tweak");
-  }
-
-  // Store the sources in a sheet - needed for distance calculation and may be
-  // needed later for self-intersecting BODY issue.
-  BODY *source_sheet;
-  if( copy_FACEs_into_sheet( source_FACE_list, source_sheet ) == CUBIT_FAILURE )
-  {
-    PRINT_ERROR( "Unable to tweak to targets\n" );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Make a target sheet with copies of original target FACEs in it.  We will
-  // extract the target normal from this BODY.
-  BODY *target_sheet;
-  if( copy_FACEs_into_sheet( target_FACE_list, target_sheet ) == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Make the surface normals consistent.  Note user could pick a variety of
-  // target surfaces from different bodies, without consistent surface normals.
-  if( make_surf_normals_consistent( target_sheet )== CUBIT_FAILURE )
-  {
-    PRINT_ERROR( "Unable to make target surface normals consistent - invalid target\n" );
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // FYI: Property of dot product:
-  //   * angle between vectors acute (<90) if dot product > 0
-  //   * angle between vectors obtuse (>90) if dot product < 0
-  //   * angle between vectors 90 deg if dot product = 0
-
-  // Get average direction of source normals.
-  CubitVector source_norm = weighted_average_FACE_normal( source_FACE_list );
-  if( source_norm.length() < 1e-12 )
-  {
-    PRINT_ERROR( "Unable to tweak source surfaces that form a loop\n" );
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Get average target normal
-  DLIList<FACE*> target_sheet_FACE_list;
-  AQE->get_FACEs( target_sheet, target_sheet_FACE_list );
-  CubitVector target_norm = weighted_average_FACE_normal( target_sheet_FACE_list );
-  if( target_norm.length() < 1e-12 )
-  {
-    PRINT_ERROR( "Unable to tweak to target surfaces that form a loop\n" );
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Get a plane through one of the source's vertices (with normal aligned with
-  // target normal (but pointing in direction of source normal)
-  source_FACE_list.reset();
-  DLIList<VERTEX*> temp_VERTEX_list;
-  AQE->get_VERTICEs( source_FACE_list.get(), temp_VERTEX_list );
-  VERTEX *VERTEX_ptr = temp_VERTEX_list.get();
-  SPAposition acis_coords = (VERTEX_ptr->geometry())->coords();
-  CubitVector coords( acis_coords.x(), acis_coords.y(), acis_coords.z() );
-  CubitPlane source_plane( target_norm, coords );
-
-  // Have plane's normal point in the general direction of source_norm
-  if( source_norm % source_plane.normal() < 0.0 ) // Dot product
-  {
-    // Obtuse angle - reverse the plane
-    CubitVector neg_norm = -source_plane.normal();
-    source_plane.normal( neg_norm );
-    source_plane.coefficient( -source_plane.coefficient() );
-  }
-
-  // Offset the plane past the targets.  Do this in two steps - in some
-  // cases, our plane is far from the sources and this can cause problems
-  // (if there is a cylindrical surface, the API error "no solution for an
-  // edge" has occurred).
-
-  // Find offset distance for first tweak - just past the sources (this 
-  // will most likely make one planar source)
-  double offset_dist;
-  if( extrema_pln_BODY( source_plane, source_sheet, offset_dist )
-    == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  BODY *planar_target_BODY;
-  if( create_offset_planar_body( source_plane, offset_dist,
-    planar_target_BODY ) == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  if( DEBUG_FLAG(168) )
-  {
-    BODY *tmp_BODY = AME->copy_BODY( planar_target_BODY, CUBIT_TRUE );
-    BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-    debug_BodySM_list.append( this_bodysm );
-  }
-
-  DLIList<FACE*> planar_FACE_list;;
-  AQE->get_FACEs( planar_target_BODY, planar_FACE_list );
-  FACE *planar_target_FACE = planar_FACE_list.get();
-
-  // Mark the sources and other FACEs
-  for( i=source_FACE_list.size(); i--; )
-  {
-    FACE_ptr = source_FACE_list.get_and_step();
-    api_add_generic_named_attribute( FACE_ptr, "tweak_source", 1, SplitCopy );
-  }
-  DLIList<FACE*> copied_BODY_FACE_list;
-  AQE->get_FACEs( copied_BODY_ptr, copied_BODY_FACE_list );
-  for( i=copied_BODY_FACE_list.size(); i--; )
-  {
-    FACE_ptr = copied_BODY_FACE_list.get_and_step();
-    api_find_named_attribute( FACE_ptr, "tweak_source", ret_att );
-    if( !ret_att )
-      api_add_generic_named_attribute( FACE_ptr, "tweak_other", 1 );
-  }
-
-  // Tweak the sources to the first planar target
-  CubitBoolean skip_self_int_check = CUBIT_TRUE;
-
-  if( tweak_FACEs_to_target( source_FACE_list, planar_target_FACE, 
-                             CUBIT_FALSE, skip_self_int_check ) == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    api_delent( planar_target_BODY );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Delete the first planar target
-  api_delent( planar_target_BODY );
-
-  // Get new source list
-  source_FACE_list.clean_out();
-  copied_BODY_FACE_list.clean_out();
-  AQE->get_FACEs( copied_BODY_ptr, copied_BODY_FACE_list );
-  for( i=copied_BODY_FACE_list.size(); i--; )
-  {
-    FACE_ptr = copied_BODY_FACE_list.get_and_step();
-    api_find_named_attribute( FACE_ptr, "tweak_source", ret_att );
-    if( ret_att )
-    {
-      source_FACE_list.append( FACE_ptr );
-      api_remove_generic_named_attribute(FACE_ptr, "tweak_source");
-    }
-    else
-    {
-      api_find_named_attribute( FACE_ptr, "tweak_other", ret_att );
-      if( ret_att )
-        api_remove_generic_named_attribute(FACE_ptr, "tweak_other");
-      else
-      {
-        // No attribute - this must be the new source
-        source_FACE_list.append( FACE_ptr );
-      }
-    }
-  }
-
-  // Get a plane for the second tweak
-  target_FACE_list.reset();
-  temp_VERTEX_list.clean_out();
-  AQE->get_VERTICEs( target_FACE_list.get(), temp_VERTEX_list );
-  VERTEX_ptr = temp_VERTEX_list.get();
-  acis_coords = (VERTEX_ptr->geometry())->coords();
-  coords.set( acis_coords.x(), acis_coords.y(), acis_coords.z() );
-  CubitPlane target_plane( target_norm, coords );
-
-  // Have plane's normal point in the general direction of source_norm
-  if( source_norm % target_plane.normal() < 0.0 ) // Dot product
-  {
-    // Obtuse angle - reverse the plane
-    CubitVector neg_norm = -target_plane.normal();
-    target_plane.normal( neg_norm );
-    target_plane.coefficient( -target_plane.coefficient() );
-  }
-
-  // Find offset distance for second tweak - past the targets.  Calculate the
-  // offset distance as the maximum distance from the plane to any point on the
-  // extended target body, in the direction of the plane's normal.
-  if( extrema_pln_BODY( target_plane, ext_target_BODY_ptr, offset_dist )
-    == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Create a target FACE offset from the plane (arbitrarily 10.0 X 10.0
-  // in size)
-  if( create_offset_planar_body( target_plane, offset_dist,
-    planar_target_BODY ) == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  if( DEBUG_FLAG(168) )
-  {
-    BODY *tmp_BODY = AME->copy_BODY( planar_target_BODY, CUBIT_TRUE );
-    BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-    debug_BodySM_list.append( this_bodysm );
-  }
-
-  planar_FACE_list.clean_out();
-  AQE->get_FACEs( planar_target_BODY, planar_FACE_list );
-  planar_target_FACE = planar_FACE_list.get();
-
-  // Tweak the sources to the planar target
-  if( tweak_FACEs_to_target( source_FACE_list, planar_target_FACE, 
-                             CUBIT_FALSE, skip_self_int_check ) == CUBIT_FAILURE )
-  {
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    api_delent( planar_target_BODY );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // Free the plane since we are done with it
-  api_delent( planar_target_BODY );
-
-  // Copy the ext_target_BODY_ptr so as not to modify it
-  BODY *ext_target_BODY_ptr2 = AME->copy_BODY( ext_target_BODY_ptr, CUBIT_TRUE );
-
-  // Heal the body for good measure
-  heal_BODY( ext_target_BODY_ptr2 );
-
-  // Make the shell normals in the ext_target_BODY_ptr2 consistent with the
-  // target sheet.
-  FACE *seed_FACE_ptr = get_seed_FACE( target_sheet_FACE_list );
-
-  DLIList<FACE*> ext_target_BODY_FACE_list;
-  AQE->get_FACEs( ext_target_BODY_ptr2, ext_target_BODY_FACE_list );
-
-  FACE *overlap_FACE_ptr = find_overlap_FACE( seed_FACE_ptr,
-    ext_target_BODY_FACE_list );
-  if( !overlap_FACE_ptr )
-  {
-    PRINT_ERROR( "Problem creating extended target to tweak to\n" );
-    if( DEBUG_FLAG(168) )
-    {
-      BODY *tmp_BODY = AME->copy_BODY( ext_target_BODY_ptr2, CUBIT_TRUE );
-      BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-      debug_BodySM_list.append( this_bodysm );
-    }
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    api_delent( ext_target_BODY_ptr2 );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  CubitVector norm_loc;
-  CubitVector ext_norm = FACE_normal( overlap_FACE_ptr, norm_loc );
-  CubitVector seed_norm = FACE_normal( seed_FACE_ptr, norm_loc, CUBIT_FALSE );
-
-  if( ext_norm % seed_norm < 0.0 )
-    api_reverse_face( overlap_FACE_ptr );
-
-  if( make_surf_normals_consistent( ext_target_BODY_ptr2, overlap_FACE_ptr )
-    == CUBIT_FAILURE )
-  {
-    PRINT_ERROR( "Unable to make extended target shell normals consistent - invalid target\n" );
-    if( DEBUG_FLAG(168) )
-    {
-      BODY *tmp_BODY = AME->copy_BODY( ext_target_BODY_ptr2, CUBIT_TRUE );
-      BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-      debug_BodySM_list.append( this_bodysm );
-    }
-    api_delent( source_sheet );
-    api_delent( target_sheet );
-    api_delent( ext_target_BODY_ptr2 );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  if( DEBUG_FLAG(168) )
-  {
-    BODY *tmp_BODY = AME->copy_BODY( ext_target_BODY_ptr2, CUBIT_TRUE );
-    BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-    debug_BodySM_list.append( this_bodysm );
-  }
-
-  // We are done with the target_sheet
-  api_delent( target_sheet );
-
-  // Intersect the tweaked body and the ext_target_BODY_ptr2.  We need to then
-  // determine which loops on the resulting body to keep as the cutting
-  // sheet.  Note a NONREG_INTERSECTION sometimes corrupts the cutting_sheet,
-  // so we do a regularized intersection then imprint afterwards.
-  BODY *cutting_sheet = NULL;
-  result = api_boolean( copied_BODY_ptr, ext_target_BODY_ptr2, INTERSECTION,
-    NDBOOL_KEEP_BOTH, cutting_sheet );
-  if( !result.ok() )
-  {
-    // A likely problem is that the BODY intersects with itself - we need to
-    // handle this case.  To fix we will chop off the tweaked part of the BODY
-    // using the original sources; then our booleans will work.  We then have
-    // to reassemble the BODY.
+    if (preview)
+        GfxPreview::flush();
     
-    BODY *copied_BODY_ptr2 = AME->copy_BODY( copied_BODY_ptr, CUBIT_FALSE );
-
-    // Chopoff the copied_BODY_ptr with cutting_sheet
-    if( chop_off_with_sheet( copied_BODY_ptr2, source_sheet ) == CUBIT_FAILURE )
-    {
-      AQE->ACIS_API_error(result);
-      api_delent( source_sheet );
-      api_delent( ext_target_BODY_ptr2 );
-      api_delent( copied_BODY_ptr2 );
-      remove_named_attribs( copied_BODY_ptr, "tweak" );
-      return CUBIT_FAILURE;
-    }
-
-    // Chopoff the copied_BODY_ptr with cutting_sheet the other way
-    api_reverse_body( source_sheet );
-    if( chop_off_with_sheet( copied_BODY_ptr, source_sheet ) == CUBIT_FAILURE )
-    {
-      AQE->ACIS_API_error(result);
-      api_delent( source_sheet );
-      api_delent( ext_target_BODY_ptr2 );
-      api_delent( copied_BODY_ptr2 );
-      remove_named_attribs( copied_BODY_ptr, "tweak" );
-      return CUBIT_FAILURE;
-    }
-
-    // We are done with the source_sheet
-    api_delent( source_sheet );
-
-    // Note copied_BODY_ptr2 is the cutoff tweaked piece - perform steps on
-    // this piece.  The good thing is we won't have to worry about looking for
-    // FACEs crossed by the extended target that we don't want to affect.
-
-    result = api_boolean( copied_BODY_ptr2, ext_target_BODY_ptr2, INTERSECTION,
-      NDBOOL_KEEP_BOTH, cutting_sheet );
-    if( !result.ok() )
-    {
-      api_delent( ext_target_BODY_ptr2 );
-      api_delent( copied_BODY_ptr2 );
-      remove_named_attribs( copied_BODY_ptr, "tweak" );
-      return CUBIT_FAILURE;
-    }
-
-    // Prepare the cutting sheet
-    if( prep_cutting_sheet( cutting_sheet, copied_BODY_ptr2, ext_target_BODY_ptr2,
-      source_norm, target_norm, CUBIT_FALSE ) == CUBIT_FAILURE )
-    {
-      if( DEBUG_FLAG(168) )
-      {
-        BodySM *this_bodysm = AQE->populate_topology_bridges( cutting_sheet );
-        debug_BodySM_list.append( this_bodysm );
-      }
-      else
-        api_delent( cutting_sheet );
-      api_delent( ext_target_BODY_ptr2 );
-      api_delent( copied_BODY_ptr2 );
-      remove_named_attribs( copied_BODY_ptr, "tweak" );
-      return CUBIT_FAILURE;
-    }
-
-    // We are done with the "tweak" attributes (used in prep_cutting_sheet)
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-
-    // We are now done with the copied extended target sheet
-    api_delent( ext_target_BODY_ptr2 );
-
-    // Reverse if forced to
-    if( reverse_flg )
-      api_reverse_body( cutting_sheet );
-
-    if( DEBUG_FLAG(168) )
-    {
-      BODY *tmp_BODY = AME->copy_BODY( cutting_sheet, CUBIT_TRUE );
-      BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-      debug_BodySM_list.append( this_bodysm );
-    }
-
-    // Apply a "tweak2" named attribute as part of a multi-step process we use
-    // to determine which EDGEs to regularize out when we reassemble the BODY.  
-    // The "tweak2" attribute will not exist on the EDGEs that result from the
-    // chopoff operation with the cutting sheet.  We will use a custom function
-    // that gets called during boolean merge operations.
-    DLIList<EDGE*> BODY2_EDGE_list;
-    AQE->get_EDGEs( copied_BODY_ptr2, BODY2_EDGE_list );
-    EDGE *EDGE_ptr;
-    for( i=BODY2_EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = BODY2_EDGE_list.get_and_step();
-      api_add_generic_named_attribute( EDGE_ptr, "tweak2", 1, SplitLose,
-        MergeCustom );
-    }
-
-    // Chopoff the copied_BODY_ptr2 with cutting_sheet
-    if( chop_off_with_sheet( copied_BODY_ptr2, cutting_sheet ) == CUBIT_FAILURE )
-    {
-      api_delent( copied_BODY_ptr2 );
-      api_delent( cutting_sheet );
-      return CUBIT_FAILURE;
-    }
-
-    // We are done with the cutting sheet
-    api_delent( cutting_sheet );
-
-    // This will add a "tweak_merged" attribute to any EDGE containing a
-    // "tweak2" attribute that is merged with another EDGE during the following
-    // unite.  We can then clean these EDGEs out.  Note the EDGEs that were
-    // sliced at the cutting sheet location won't have "tweak2" attributes on
-    // them - thus this method allows us to efficiently find the EDGEs we need
-    // to remove.
-    set_merge_method( "tweak2", custom_att_merge_method );
-
-    // Unite the copied_BODY_ptr2 with copied_BODY_ptr (this deletes
-    // copied_BODY_ptr2)
-    result = api_boolean( copied_BODY_ptr2, copied_BODY_ptr, NONREG_UNION );
-    if( !result.ok() )
-    {
-      if( copied_BODY_ptr2 ) api_delent( copied_BODY_ptr2 );
-      return CUBIT_FAILURE;
-    }
-
-    // The unite can leave double-sided FACEs within the BODY - we need to
-    // to remove those.
-    DLIList<FACE*>  body_FACE_list;
-    AQE->get_FACEs( copied_BODY_ptr, body_FACE_list );
-    for( i=body_FACE_list.size(); i--; )
-    {
-      FACE_ptr = body_FACE_list.get_and_step();
-
-      // If this is an internal FACE remove it
-      if( FACE_ptr->sides() == DOUBLE_SIDED &&
-          FACE_ptr->cont()==BOTH_INSIDE )
-      {
-        BODY *unhooked_BODY_ptr = NULL;
-        api_unhook_face( FACE_ptr, unhooked_BODY_ptr );
-        if( unhooked_BODY_ptr )
-          api_delent( unhooked_BODY_ptr );
-      }
-    }
-
-    // Remove the merged EDGEs
-    DLIList<EDGE*> merged_EDGE_list;
-    DLIList<EDGE*> body_EDGE_list;
-    AQE->get_EDGEs( copied_BODY_ptr, body_EDGE_list );
-    for( i=body_EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = body_EDGE_list.get_and_step();
-      api_find_named_attribute( EDGE_ptr, "tweak_merged", ret_att );
-      if( ret_att )
-      {
-        merged_EDGE_list.append( EDGE_ptr );
-        api_remove_generic_named_attribute(EDGE_ptr, "tweak_merged");
-      }
-    }
-
-    for( i=merged_EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = merged_EDGE_list.get_and_step();
-
-      // Make sure EDGE was not already cleaned out
-      DLIList<EDGE*> tmp_EDGE_list;
-      AQE->get_EDGEs( copied_BODY_ptr, tmp_EDGE_list );
-
-      if( tmp_EDGE_list.is_in_list( EDGE_ptr ) )
-        api_clean_entity( EDGE_ptr );
-    }
-
-    // Cleanout any left-over named attributes
-    remove_named_attribs( copied_BODY_ptr, "tweak2" );
-
-    // Reset the owner attributes
-    reset_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
     return CUBIT_SUCCESS;
-  } // End of workaround for self-intersecting case
-
-  // Since the intersection was successful the source_sheet is not needed
-  api_delent( source_sheet );
-
-  // Prepare the cutting sheet
-  if( prep_cutting_sheet( cutting_sheet, copied_BODY_ptr, ext_target_BODY_ptr2,
-    source_norm, target_norm ) == CUBIT_FAILURE )
-  {
-    if( DEBUG_FLAG(168) )
-    {
-      BodySM *this_bodysm = AQE->populate_topology_bridges( cutting_sheet );
-      debug_BodySM_list.append( this_bodysm );
-    }
-    else
-      api_delent( cutting_sheet );
-    api_delent( ext_target_BODY_ptr2 );
-    remove_named_attribs( copied_BODY_ptr, "tweak" );
-    return CUBIT_FAILURE;
-  }
-
-  // We are done with the "tweak" attributes (used in prep_cutting_sheet)
-  remove_named_attribs( copied_BODY_ptr, "tweak" );
-
-  // We are now done with the copied extended target sheet
-  api_delent( ext_target_BODY_ptr2 );
-
-  // Reverse if forced to
-  if( reverse_flg )
-    api_reverse_body( cutting_sheet );
-
-  if( DEBUG_FLAG(168) )
-  {
-    BODY *tmp_BODY = AME->copy_BODY( cutting_sheet, CUBIT_TRUE );
-    BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-    debug_BodySM_list.append( this_bodysm );
-  }
-
-  // Chopoff the copied_BODY_ptr with cutting_sheet
-  if( chop_off_with_sheet( copied_BODY_ptr, cutting_sheet ) == CUBIT_FAILURE )
-  {
-    api_delent( cutting_sheet );
-    return CUBIT_FAILURE;
-  }
-
-  // Delete the cutting sheet
-  api_delent( cutting_sheet );
-
-  // Reset the owner attributes
-  reset_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  return CUBIT_SUCCESS;
 }
 
-//=============================================================================
-// Function   : FACE_surrounded
-// Member Type: PRIVATE
-// Description: Determine if the given FACE is entirely surrounded by the
-//              other FACEs. The given FACE can exist in FACE_list_in.
-// Author     : Steve Storm
-// Date       : 01/05/06
-//=============================================================================
-CubitBoolean
-AcisTweakTool::FACE_surrounded( FACE *ref_FACE_ptr,
-                                DLIList<FACE*> &FACE_list_in )
-{
-  // Get outer loop curves in ref_FACE_ptr
-  DLIList<EDGE*> ref_FACE_edges;
-  get_outer_EDGEs( ref_FACE_ptr, ref_FACE_edges );
-
-  // Loop through ref_FACE_edges, get all attached FACEs, check if any are in
-  // FACE_list_in.
-
-  int i, j;
-  int num_found = 0;
-  EDGE *ref_EDGE_ptr;
-  for( i=ref_FACE_edges.size(); i--; )
-  {
-    ref_EDGE_ptr = ref_FACE_edges.get_and_step();
-
-    DLIList<FACE *> attached_FACE_list;
-    AQE->get_FACEs( ref_EDGE_ptr, attached_FACE_list );
-
-    if( attached_FACE_list.move_to( ref_FACE_ptr ) == CUBIT_TRUE )
-      attached_FACE_list.extract();
-
-    FACE *FACE_ptr;
-    for( j=attached_FACE_list.size(); j--; )
-    {
-      FACE_ptr = attached_FACE_list.get_and_step();
-      if( FACE_list_in.is_in_list( FACE_ptr ) == CUBIT_TRUE )
-      {
-        num_found++;
-        break;
-      }
-    }
-  }
-
-  if( num_found == ref_FACE_edges.size() )
-    return CUBIT_TRUE;
-
-  return CUBIT_FALSE;
-}
-
-//=============================================================================
-// Function   : get_outer_EDGEs
-// Member Type: PRIVATE
-// Description: Get EDGEs from outer LOOP of FACE
-// Author     : Steve Storm
-// Date       : 01/03/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::get_outer_EDGEs( FACE *FACE_ptr, DLIList<EDGE*> &EDGE_list )
-{
-  // Loop through LOOPs
-  outcome result;
-  logical external;
-
-  LOOP *LOOP_ptr = FACE_ptr->loop();
-  while( LOOP_ptr != NULL )
-  {
-    result = api_loop_external( LOOP_ptr, &external );
-    if( !result.ok() )
-    {
-      AQE->ACIS_API_error(result);
-      return CUBIT_FAILURE;
-    }
-
-    if( external == TRUE )
-    {
-      AQE->get_EDGEs( LOOP_ptr, EDGE_list );
-      return CUBIT_SUCCESS;
-    }
-
-    LOOP_ptr = LOOP_ptr->next();
-  }
-
-  return CUBIT_FAILURE;
-}
-
-//=============================================================================
-// Function   : tweak_target
-// Member Type: PUBLIC
-// Description: Tweak specified edges of a surface or set of surfaces (in sheet
-//              bodies) up to a single target surface or a set of target
-//              surfaces.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target( DLIList<Curve*> &input_curve_list,
-                             DLIList<Surface*> &target_surf_list,
+CubitStatus AcisTweakTool::tweak_chamfer( DLIList<Curve*> &curve_list, 
+                             double left_offset,
                              DLIList<BodySM*> &new_bodysm_list,
-                             CubitBoolean reverse_flg,
-                             CubitBoolean keep_old_bodies,
-                             CubitBoolean preview )
+                             double right_offset /*= -1.0*/,
+                             CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                             CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for tweaking\n"
-    "       surfaces to a target.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  if( target_surf_list.size() == 1 )
-  {
-    return tweak_target_single( input_curve_list, target_surf_list.get(),
-      new_bodysm_list, reverse_flg, keep_old_bodies, preview );
-  }
-  else
-  {
-    return tweak_target_multiple( input_curve_list, target_surf_list,
-      new_bodysm_list, reverse_flg, keep_old_bodies, preview );
-  }
-}
-
-//=============================================================================
-// Function   : tweak_target_single
-// Member Type: PRIVATE
-// Description: Tweak specified edges of a surface or set of surfaces (in sheet
-//              bodies) up to a single target surface.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target_single( DLIList<Curve*> &input_curve_list,
-                                    Surface *target_surf_ptr,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean reverse_flg,
-                                    CubitBoolean keep_old_bodies,
-                                    CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for tweaking\n"
-    "       curves.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  // Get target FACE
-  SurfaceACIS* target_surface = dynamic_cast<SurfaceACIS*>(target_surf_ptr);
-  if( !target_surface )
-  {
-    PRINT_ERROR("Cannot tweak to non-ACIS target surface.\n");
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  // Copy the target face (in some cases, the target face can be modified -
-  // if for example it is tweaked to itself, which is sometimes done to
-  // remove unwanted topology or to fix an error).  This preserves the target
-  // in that case.
-  ENTITY *copied_entity_ptr;
-  outcome result = api_copy_entity_contents( target_surface->get_FACE_ptr(),
-    copied_entity_ptr );
-  if( !result.ok() )
-  {
-    AcisQueryEngine::instance()->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-  FACE *target_FACE_ptr = (FACE *)copied_entity_ptr;
-
-  // Get source EDGEs
-  DLIList<EDGE*> input_EDGE_list( input_curve_list.size() );
-  if( get_EDGEs( input_curve_list, input_EDGE_list ) == CUBIT_FAILURE )
-  {
-    api_delent( target_FACE_ptr );
-    return CUBIT_FAILURE;
-  }
-
-  // Call private function to do the work
-  if( tweak_target_single( input_EDGE_list, target_FACE_ptr, new_bodysm_list,
-    reverse_flg, keep_old_bodies, preview ) == CUBIT_FAILURE )
-  {
-    api_delent( target_FACE_ptr );
-    return CUBIT_FAILURE;
-  }
-
-  api_delent( target_FACE_ptr );
-
-  return CUBIT_SUCCESS;
 }
 
-//=============================================================================
-// Function   : tweak_target_multiple
-// Member Type: PRIVATE
-// Description: Tweak specified edges of a surface or set of surfaces (in sheet
-//              bodies) up to a set of target surfaces.
-// Author     : Steve Storm
-// Date       : 11/03/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target_multiple( DLIList<Curve*> &input_curve_list,
-                                      DLIList<Surface*> &target_surf_list,
-                                      DLIList<BodySM*> &new_bodysm_list,
-                                      CubitBoolean reverse_flg,
-                                      CubitBoolean keep_old_bodies,
-                                      CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for extending\n"
-    "       surfaces.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  // Get source curves
-  DLIList<EDGE*> input_EDGE_list( input_curve_list.size() );
-  if( get_EDGEs( input_curve_list, input_EDGE_list ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  // Get target FACES
-  DLIList<FACE*> target_FACE_list( target_surf_list.size() );
-  if( get_FACEs( target_surf_list, target_FACE_list ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  // Call private function to do the work
-  if( tweak_target_multiple( input_EDGE_list, target_FACE_list,
-    new_bodysm_list, reverse_flg, keep_old_bodies, preview ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_target
-// Member Type: PUBLIC
-// Description: Tweak specified edges of a sheet body or bodies up to a set of
-//              target curves that are part of a sheet body.  The target is a
-//              surface or surfaces created by thickening the owning surfaces
-//              of the target curves.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target( DLIList<Curve*> &input_curve_list,
-                             DLIList<Curve*> &target_curve_list,
+CubitStatus AcisTweakTool::tweak_chamfer( DLIList<Point*> &point_list, 
+                             double offset1, 
                              DLIList<BodySM*> &new_bodysm_list,
-                             CubitBoolean reverse_flg,
-                             CubitBoolean keep_old_bodies,
-                             CubitBoolean preview )
+                             Curve *edge1 /*= NULL*/,
+                             double offset2 /*= -1.0*/,
+                             Curve *edge2 /*= NULL*/,
+                             double offset3 /*= -1.0*/,
+                             Curve *edge3 /*= NULL*/,
+                             CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                             CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for extending\n"
-    "       surfaces.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  if( target_curve_list.size() == 1 )
-  {
-    return tweak_target_single( input_curve_list, target_curve_list.get(),
-      new_bodysm_list, reverse_flg, keep_old_bodies, preview );
-  }
-  else
-  {
-    return tweak_target_multiple( input_curve_list, target_curve_list,
-      new_bodysm_list, reverse_flg, keep_old_bodies, preview );
-  }
-}
-
-//=============================================================================
-// Function   : tweak_target_single
-// Member Type: PRIVATE
-// Description: Tweak specified edges of a sheet body or bodies up to a single
-//              target curve that is part of a sheet body.  The target is a
-//              surface created by thickening the owning surface of the target
-//              curve.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target_single( DLIList<Curve*> &curve_list,
-                                    Curve *target_curve_ptr,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean reverse_flg,
-                                    CubitBoolean keep_old_bodies,
-                                    CubitBoolean preview )
-{
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for extending\n"
-    "       surfaces.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  // We need to build the target FACE by grabbing the associated surfaces and
-  // thickening them.  For convenience, use the get_thickened_BODIES_of_EDGES
-  // function to do this.
-  EDGE *target_EDGE_ptr = AcisQueryEngine::instance()->
-    get_EDGE( target_curve_ptr );
-  if( target_EDGE_ptr == NULL )
-  {
-    PRINT_ERROR( "Target must be an ACIS curve.\n" );
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-  BODY *BODY_ptr;
-  DLIList<EDGE*> removed_EDGE_list;
-  DLIList<EDGE*> target_EDGE_list( 1 );
-  target_EDGE_list.append( target_EDGE_ptr );
-  DLIList<BODY*> thickened_BODY_list;
-  DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-  DLIList<DLIList<FACE*>*> output_FACE_lists;
-  DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-  if( get_thickened_BODIES_of_EDGES( "tweak to", target_EDGE_list,
-    removed_EDGE_list, BODY_ptr, thickened_BODY_list, output_EDGE_lists,
-    output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-  {
-    PRINT_ERROR( "unable to setup target -- aborting\n" );
-    return CUBIT_FAILURE;
-  }
-
-  FACE *target_FACE_ptr = conjugate_FACE_lists.get()->get();
-
-  // Clean up memory allocated for the output lists
-  while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-  while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-  while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-  if( target_FACE_ptr == NULL )
-  {
-    while( thickened_BODY_list.size() ) api_delent( thickened_BODY_list.pop() );
-    PRINT_ERROR( "unable to setup target -- aborting\n" );
-    return CUBIT_FAILURE;
-  }
-
-  // Needed for preview - target might be on BODY we are tweaking and we need
-  // to check for that in the preview.
-  DLIList<AcisBridge*> preview_ab_list;
-  preview_ab_list.append( ATTRIB_CUBIT_OWNER::cubit_owner(target_EDGE_ptr) );
-
-  // Call private function to do the work
-  DLIList<EDGE*> EDGE_list( curve_list.size() );
-  if( get_EDGEs( curve_list, EDGE_list ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  CubitStatus status;
-  status = tweak_target_single( EDGE_list, target_FACE_ptr, new_bodysm_list,
-    reverse_flg, keep_old_bodies, preview, &preview_ab_list );
-
-  // Delete thickened BODY
-  while( thickened_BODY_list.size() ) api_delent( thickened_BODY_list.pop() );
-
-  return status;
 }
 
-//=============================================================================
-// Function   : tweak_target_multiple
-// Member Type: PRIVATE
-// Description: Tweak specified edges of a sheet body or bodies up to a set
-//              of target curves that are part of a sheet body or bodies.  The
-//              target is a set of surfaces created by thickening the owning
-//              surfaces of the target curves.
-// Author     : Steve Storm
-// Date       : 02/13/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target_multiple( DLIList<Curve*> &input_curve_list,
-                                      DLIList<Curve*> &target_curve_list,
-                                      DLIList<BodySM*> &new_bodysm_list,
-                                      CubitBoolean reverse_flg,
-                                      CubitBoolean keep_old_bodies,
-                                      CubitBoolean preview )
+CubitStatus AcisTweakTool::tweak_fillet( DLIList<Curve*> &curve_list, 
+                            double radius,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-#ifndef ACIS_LOCAL_OPS
-  PRINT_ERROR( "The ACIS Local Operations Husk is required for extending\n"
-    "       surfaces.  It has not been licensed for this installation.\n" );
-  return CUBIT_FAILURE;
-#endif
-
-  // Get source curves
-  DLIList<EDGE*> input_EDGE_list( input_curve_list.size() );
-  if( get_EDGEs( input_curve_list, input_EDGE_list ) == CUBIT_FAILURE )
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-
-  // Get target FACES
-  DLIList<EDGE*> target_EDGE_list;
-  if( get_EDGEs( target_curve_list, target_EDGE_list ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  // Build list of FACEs which could be from multiple BODIES
-  DLIList<FACE*> target_FACE_list;
-  DLIList<BODY*> thickened_BODY_list;
-  while( target_EDGE_list.size() )
-  {
-    BODY *BODY_ptr;
-    DLIList<EDGE*> removed_EDGE_list;
-    DLIList<BODY*> tmp_thickened_BODY_list;
-    DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-    DLIList<DLIList<FACE*>*> output_FACE_lists;
-    DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-    if( get_thickened_BODIES_of_EDGES( "tweak to", target_EDGE_list,
-      removed_EDGE_list, BODY_ptr, tmp_thickened_BODY_list, output_EDGE_lists,
-      output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-    {
-      PRINT_ERROR( "unable to setup target -- aborting\n" );
-      return CUBIT_FAILURE;
-    }
-
-    // The conjugate FACEs are what we are after
-    int i, j;
-    conjugate_FACE_lists.reset();
-    for( i=conjugate_FACE_lists.size(); i--; )
-    {
-      DLIList<FACE*> *FACE_list_ptr = conjugate_FACE_lists.get_and_step();
-
-      FACE *FACE_ptr;
-      FACE_list_ptr->reset();
-      for( j=FACE_list_ptr->size(); j--; )
-      {
-        FACE_ptr = FACE_list_ptr->get_and_step();
-        target_FACE_list.append( FACE_ptr );
-      }
-    }
-
-    // Clean up memory allocated for the output lists
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-    while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-    thickened_BODY_list += tmp_thickened_BODY_list;
-  }
-
-  // Needed for preview - targets might be on BODY we are tweaking and we need
-  // to check for that in the preview.
-  DLIList<AcisBridge*> preview_ab_list;
-  if( preview ) get_owner_list( target_EDGE_list, preview_ab_list );
-
-  // Call private function to do the work
-  if( tweak_target_multiple( input_EDGE_list, target_FACE_list,
-    new_bodysm_list, reverse_flg, keep_old_bodies, preview, &preview_ab_list )
-    == CUBIT_FAILURE )
-  {
-    while( thickened_BODY_list.size() ) api_delent( thickened_BODY_list.pop() );
-    return CUBIT_FAILURE;
-  }
-
-  // Delete the thickened target BODIES
-  while( thickened_BODY_list.size() ) api_delent( thickened_BODY_list.pop() );
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisTweakTool::get_ACIS_surfaces( DLIList<Surface*>& surf_list,
-                                              DLIList<SurfaceACIS*>& acis_list )
+CubitStatus AcisTweakTool::tweak_fillet( Curve *curve_ptr, 
+                            double start_radius,
+                            double end_radius,
+                            BodySM *&new_body_ptr,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE */)
 {
-  int i;
-  surf_list.reset();
-  for( i=surf_list.size(); i--; )
-  {
-    Surface* surf = surf_list.get_and_step();
-    if (SurfaceACIS* surf_acis = dynamic_cast<SurfaceACIS*>(surf))
-      acis_list.append(surf_acis);
-  }
-
-  if (surf_list.size() != acis_list.size())
-  {
-    PRINT_ERROR("%d non-ACIS Surfaces.\n", surf_list.size() - acis_list.size());
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisTweakTool::get_FACEs( DLIList<Surface*> &surface_list,
-                                      DLIList<FACE*> &FACE_list )
+CubitStatus AcisTweakTool::tweak_fillet( DLIList<Point*> &point_list, 
+                            double radius,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  int i;
-  FACE *FACE_ptr;
-  surface_list.reset();
-  for( i=surface_list.size(); i--; )
-  {
-    Surface* surface_ptr = surface_list.get_and_step();
-    FACE_ptr = AcisQueryEngine::instance()->get_FACE( surface_ptr );
-    if( FACE_ptr ) FACE_list.append( FACE_ptr );
-  }
-
-  if( surface_list.size() != FACE_list.size() )
-  {
-    PRINT_ERROR("%d non-ACIS surfaces.\n", surface_list.size() - FACE_list.size());
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisTweakTool::get_EDGEs( DLIList<Curve*> &curve_list,
-                                      DLIList<EDGE*> &EDGE_list )
+CubitStatus AcisTweakTool::tweak_move( DLIList<Surface*> &surface_list,
+                          const CubitVector &delta,
+                          DLIList<BodySM*> &new_bodysm_list,
+                          CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                          CubitBoolean preview /*= CUBIT_FALSE */)
 {
-  int i;
-  EDGE *EDGE_ptr;
-  curve_list.reset();
-  for( i=curve_list.size(); i--; )
-  {
-    Curve* curve_ptr = curve_list.get_and_step();
-    EDGE_ptr = AcisQueryEngine::instance()->get_EDGE( curve_ptr );
-    if( EDGE_ptr ) EDGE_list.append( EDGE_ptr );
-  }
-
-  if( curve_list.size() != EDGE_list.size() )
-  {
-    PRINT_ERROR("%d non-ACIS curves.\n", curve_list.size() - EDGE_list.size());
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus AcisTweakTool::get_VERTICEs( DLIList<Point*> &point_list,
-                                         DLIList<VERTEX*> &VERTEX_list )
+CubitStatus AcisTweakTool::tweak_move( DLIList<Curve*> &curve_list,
+                          const CubitVector &delta,
+                          DLIList<BodySM*> &new_bodysm_list,
+                          CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                          CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  int i;
-  VERTEX *VERTEX_ptr;
-  point_list.reset();
-  for( i=point_list.size(); i--; )
-  {
-    Point* point_ptr = point_list.get_and_step();
-    VERTEX_ptr = AcisQueryEngine::instance()->get_VERTEX( point_ptr );
-    if( VERTEX_ptr ) VERTEX_list.append( VERTEX_ptr );
-  }
-
-  if( point_list.size() != VERTEX_list.size() )
-  {
-    PRINT_ERROR("%d non-ACIS vertices.\n", point_list.size() - VERTEX_list.size());
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-//=============================================================================
-// Function   : tweak_target
-// Member Type: PRIVATE
-// Description: Tweak specified EDGES of a surface or set of surfaces (in
-//              sheet bodies) up to a single target FACE.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target_single( DLIList<EDGE*> &input_EDGE_list,
-                                    FACE *target_FACE_ptr,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean reverse_flg,
-                                    CubitBoolean keep_old_bodies,
-                                    CubitBoolean preview,
-                                    DLIList<AcisBridge*> *t_ab_list_ptr )
+CubitStatus AcisTweakTool::tweak_offset( DLIList<Surface*> &surface_list,
+                            double offset_distance,
+                            DLIList<Surface*> *add_surface_list_ptr, 
+                            DLIList<double> *add_offset_list_ptr,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  assert( input_EDGE_list.size() );
-
-  int i, j;
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_bodies);
-
-  // Copy the input EDGE list, since we will be removing EDGEs from it
-  DLIList<EDGE*> copied_EDGE_list = input_EDGE_list;
-
-  copied_EDGE_list.reset();
-  while( copied_EDGE_list.size() )
-  {
-    BODY *BODY_ptr;
-    DLIList<EDGE*> removed_EDGE_list;
-    DLIList<BODY*> thickened_BODY_list;
-    DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-    DLIList<DLIList<FACE*>*> output_FACE_lists;
-    DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-    if( get_thickened_BODIES_of_EDGES( "tweak", copied_EDGE_list, 
-      removed_EDGE_list, BODY_ptr, thickened_BODY_list, output_EDGE_lists,
-      output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    BodySM *bodysm_ptr = AQE->get_body_sm_of_ENTITY( BODY_ptr );
-
-    // Store source and target EDGEs for preview
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview )
-    {
-      get_owner_list( removed_EDGE_list, preview_ab_list );
-      if( t_ab_list_ptr ) preview_ab_list += *t_ab_list_ptr;
-    }
-   
-    // Tweak the surfaces on the output BODIEs, pull the tweaked surfaces off,
-    // and replace them in the original BODY
-    // First copy the BODY
-    BODY *copied_BODY_ptr = AME->copy_BODY(BODY_ptr, CUBIT_FALSE);
-
-    BODY *thickened_BODY_ptr;
-    DLIList<FACE*> *output_FACE_list_ptr;
-    DLIList<FACE*> *conjugate_FACE_list_ptr;
-    thickened_BODY_list.reset();
-    output_EDGE_lists.reset();
-    output_FACE_lists.reset();
-    conjugate_FACE_lists.reset();
-    for( i=thickened_BODY_list.size(); i--; )
-    {
-      thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-      output_FACE_list_ptr = output_FACE_lists.get_and_step();
-      conjugate_FACE_list_ptr = conjugate_FACE_lists.get_and_step();
-
-      // Note - the conjugate FACE list can have duplicate entries in
-      // it, as thicken doesn't always create a separate surface for
-      // each curve.
-      DLIList<FACE*> tweak_FACE_list;
-      conjugate_FACE_list_ptr->reset();
-      for( j=conjugate_FACE_list_ptr->size(); j--; )
-        tweak_FACE_list.append_unique( conjugate_FACE_list_ptr->get_and_step() );
-
-      // Keep track of the FACEs of interest, via their Cubit owners, which
-      // will survive throughout the operation
-      DLIList<AcisBridge*> owner_list;
-      get_owner_list( *output_FACE_list_ptr, owner_list );
-
-      // Do the tweak
-      if( tweak_FACEs_to_target( tweak_FACE_list, target_FACE_ptr, reverse_flg )
-        == CUBIT_FAILURE )
-      {
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Get bodies ready to swap new surfaces for old
-      if( prep_for_surface_swap( thickened_BODY_ptr, copied_BODY_ptr,
-        owner_list ) == CUBIT_FAILURE )
-      {
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-    } // End loop on thickened (separated) BODIES
-
-    // Free memory
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-    while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-    while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-    // Unite the thickened BODIEs back into the copied_input_BODY_ptr
-    BODY *master;
-    if( unite_BODIES( copied_BODY_ptr, thickened_BODY_list, master ) == CUBIT_FAILURE )
-    {
-      // If failure, the unite_BODIES function cleaned up the memory
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // This BODY is done (whew!)
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( master );
-
-      BodySM *new_body = AME->get_new_Body( bodysm_ptr, BODY_ptr, master,
-        keep_old_bodies );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      draw_tweak_preview_omt( master, CUBIT_TRUE, &preview_ab_list );
-      api_delent( master );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_target_multiple
-// Member Type: PRIVATE
-// Description: Tweak specified EDGES of a surface or set of surfaces (in
-//              sheet bodies) up to a multiple target FACEs.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_target_multiple( DLIList<EDGE*> &input_EDGE_list,
-                                      DLIList<FACE*> &target_FACE_list,
-                                      DLIList<BodySM*> &new_bodysm_list,
-                                      CubitBoolean reverse_flg,
-                                      CubitBoolean keep_old_bodies,
-                                      CubitBoolean preview,
-                                      DLIList<AcisBridge*> *preview_ab_list_ptr )
-{
-  assert( input_EDGE_list.size() );
-
-  int i, j;
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_bodies);
-
-  // Get extended target surfaces (in a single sheet BODY)
-  BODY *ext_target_BODY_ptr;
-  if( create_extended_sheet( target_FACE_list, ext_target_BODY_ptr )
-    == CUBIT_FAILURE )
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-
-  if( DEBUG_FLAG(168) )
-  {
-    BODY *tmp_BODY = AME->copy_BODY( ext_target_BODY_ptr, CUBIT_TRUE );
-    BodySM *this_bodysm = AQE->populate_topology_bridges( tmp_BODY );
-    new_bodysm_list.append( this_bodysm );
-  }
-
-  // Copy the input EDGE list, since we will be removing EDGEs from it
-  DLIList<EDGE*> copied_EDGE_list = input_EDGE_list;
-
-  copied_EDGE_list.reset();
-  while( copied_EDGE_list.size() )
-  {
-    BODY *BODY_ptr;
-    DLIList<EDGE*> removed_EDGE_list;
-    DLIList<BODY*> thickened_BODY_list;
-    DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-    DLIList<DLIList<FACE*>*> output_FACE_lists;
-    DLIList<DLIList<FACE*>*> conjugate_FACE_lists;
-    if( get_thickened_BODIES_of_EDGES( "tweak", copied_EDGE_list, 
-      removed_EDGE_list, BODY_ptr, thickened_BODY_list, output_EDGE_lists,
-      output_FACE_lists, conjugate_FACE_lists ) == CUBIT_FAILURE )
-    {
-      api_delent( ext_target_BODY_ptr );
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    BodySM *bodysm_ptr = AQE->get_body_sm_of_ENTITY( BODY_ptr );
-
-    // Tweak the surfaces on the output BODIEs, pull the tweaked surfaces off,
-    // and replace them in the original BODY
-    // First copy the BODY
-    BODY *copied_BODY_ptr = AME->copy_BODY(BODY_ptr, CUBIT_FALSE);
-
-    // Store source and target EDGEs for preview
-    DLIList<AcisBridge*> preview_ab_list;
-    if( preview )
-    {
-      get_owner_list( removed_EDGE_list, preview_ab_list );
-      if( preview_ab_list_ptr ) preview_ab_list += *preview_ab_list_ptr;
-    }
-
-    BODY *thickened_BODY_ptr;
-    DLIList<FACE*> *output_FACE_list_ptr;
-    DLIList<FACE*> *conjugate_FACE_list_ptr;
-    thickened_BODY_list.reset();
-    output_EDGE_lists.reset();
-    output_FACE_lists.reset();
-    conjugate_FACE_lists.reset();
-    for( i=thickened_BODY_list.size(); i--; )
-    {
-      thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-      output_FACE_list_ptr = output_FACE_lists.get_and_step();
-      conjugate_FACE_list_ptr = conjugate_FACE_lists.get_and_step();
-
-      // Note - the conjugate FACE list can have duplicate entries in
-      // it, as thicken doesn't always create a separate surface for
-      // each curve.
-      DLIList<FACE*> tweak_FACE_list;
-      conjugate_FACE_list_ptr->reset();
-      for( j=conjugate_FACE_list_ptr->size(); j--; )
-        tweak_FACE_list.append_unique( conjugate_FACE_list_ptr->get_and_step() );
-
-      // Keep track of the FACEs of interest, via their Cubit owners, which
-      // will survive throughout the operation
-      DLIList<AcisBridge*> owner_list;
-      get_owner_list( *output_FACE_list_ptr, owner_list );
-
-      // Do the tweak
-      if( tweak_target_multiple( tweak_FACE_list, target_FACE_list,
-        ext_target_BODY_ptr, new_bodysm_list, reverse_flg ) 
-        == CUBIT_FAILURE )
-      {
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( ext_target_BODY_ptr );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Get bodies ready to swap new surfaces for old
-      if( prep_for_surface_swap( thickened_BODY_ptr, copied_BODY_ptr,
-        owner_list ) == CUBIT_FAILURE )
-      {
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( ext_target_BODY_ptr );
-        api_delent( copied_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-    } // End loop on thickened (separated) BODIES
-
-    // Free memory
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-    while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-    while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-
-    // Unite the thickened BODIEs back into the copied_input_BODY_ptr
-    BODY *master;
-    if( unite_BODIES( copied_BODY_ptr, thickened_BODY_list, master ) == CUBIT_FAILURE )
-    {
-      api_delent( ext_target_BODY_ptr );
-      // If failure, the unite_BODIES function cleaned up the memory
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // This BODY is done (whew!)
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY( master );
-
-      BodySM *new_body = AME->get_new_Body( bodysm_ptr, BODY_ptr, master,
-        keep_old_bodies );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      // Preview EDGEs
-      draw_tweak_preview_omt( master, CUBIT_TRUE, &preview_ab_list );
-      api_delent( master );
-    }
-  }
-
-  api_delent( ext_target_BODY_ptr );
-
-  return CUBIT_SUCCESS;
 }
 
-//=============================================================================
-// Function   : copy_FACES_from_BODY
-// Member Type: PRIVATE
-// Description: Input FACE list must be in a single BODY.  Copy these FACEs off
-//              into a new BODY, while retaining all the Cubit attributes.  The
-//              input BODY (the parent BODY of the FACE_list) is NOT modified.
-// Author     : Steve Storm
-// Date       : 03/28/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::copy_FACES_from_BODY( DLIList<FACE*> &input_FACE_list,
-                                     BODY *&copied_BODY_ptr)
+CubitStatus AcisTweakTool::make_offset_sheet( DLIList<Surface*> &surface_list,
+                                 double def_offset,
+                                 DLIList<Surface*> *add_surface_list_ptr, 
+                                 DLIList<double> *add_offset_list_ptr,
+                                 DLIList<BodySM*> &new_bodysm_list,
+                                 CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  // Method - copy the body and remove the other faces from the body.  We tried
-  // copying the faces off into a new body using api_unhook_faces, or
-  // copy_single_entity, etc., but the cubit attributes on the copied faces
-  // always seem to disappear.  This method, which may seem like an odd way
-  // to approach the problem, is guaranteed to keep the cubit attributes on
-  // the resultant body.  It also guarantees a single body as a result (note
-  // the resultant body may need to be separated, as it may have disconnected
-  // faces).
-  int i;
-  FACE *FACE_ptr;
-  BODY *input_BODY_ptr;
-
-  // Get owning BODY of the FACE_list
-  input_FACE_list.reset();
-  FACE_ptr = input_FACE_list.get_and_step();
-  input_BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY( FACE_ptr );
-
-  // Error check - make sure remaining FACEs are from same BODY
-  for( i=1; i<input_FACE_list.size(); i++ )
-  {
-    FACE_ptr = input_FACE_list.get_and_step();
-    if( input_BODY_ptr != AcisQueryEngine::instance()->get_BODY_of_ENTITY( FACE_ptr ) )
-      return CUBIT_FAILURE;
-  }
-
-  // Get a list of all the associated Surfaces to the input FACEs
-  AcisBridge *ab_ptr;
-  SurfaceACIS *asurf_ptr;
-  DLIList<SurfaceACIS*> input_asurface_list( input_FACE_list.size() );
-  input_FACE_list.reset();
-  for( i=input_FACE_list.size(); i--; )
-  {
-    FACE_ptr = input_FACE_list.get_and_step();
-    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(FACE_ptr);
-    asurf_ptr = CAST_TO( ab_ptr, SurfaceACIS );
-    if( asurf_ptr == NULL )
-    {
-      PRINT_ERROR( "Internal error -- please report.\n" );
-      return CUBIT_FAILURE;
-    }
-    input_asurface_list.append( asurf_ptr );
-  }
-
-  // Copy the input BODY, keeping all the cubit attributes
-  copied_BODY_ptr = AcisModifyEngine::instance()->copy_BODY(input_BODY_ptr,
-    CUBIT_FALSE);
-
-  DLIList<FACE*> remove_FACE_list;
-
-  // Remove the "unused" FACEs from the copied BODY.  Loop on FACEs in
-  // copied_BODY_ptr
-
-  DLIList<FACE*> FACE_list;
-  AcisQueryEngine::instance()->get_FACEs( copied_BODY_ptr, FACE_list );
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-
-    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(FACE_ptr);
-    asurf_ptr = CAST_TO( ab_ptr, SurfaceACIS );
-
-    // If we don't find a matching asurf_ptr in input_asurface_list remove
-    // this FACE
-    if( !asurf_ptr || (asurf_ptr && !input_asurface_list.is_in_list( asurf_ptr )) )
-      remove_FACE_list.append( FACE_ptr );
-  }
-
-  if( remove_FACES_from_BODY( copied_BODY_ptr, remove_FACE_list ) == CUBIT_FAILURE )
-  {
-    api_delent( copied_BODY_ptr );
-    copied_BODY_ptr = NULL;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::remove_FACES_from_BODY( BODY *BODY_ptr,
-                                       DLIList<FACE*> &remove_FACE_list )
-{
-  if( remove_FACE_list.size() == 0 )
-    return CUBIT_SUCCESS;
-
-  // I'm not sure why, but this operation can cause cubit owner attributes to
-  // disappear from copied_BODY_ptr.  We need to put them back.
-  AcisBridge *ab_body_ptr;
-  AcisBridge *ab_lump_ptr;
-  AcisBridge *ab_shell_ptr;
-  get_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  int i;
-  outcome result;
-  //ENTITY_LIST faces_to_remove;
-  FACE *FACE_ptr;
-  for( i=remove_FACE_list.size(); i--; )
-  {
-    FACE_ptr = remove_FACE_list.get_and_step();
-    //faces_to_remove.add( FACE_ptr );
-    result = api_remove_face( FACE_ptr );
-    if( !result.ok() )
-    {
-      AcisQueryEngine::instance()->ACIS_API_error(result);
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // This doesn't work, because all attributes are removed from the input body.
-  // I think this would be faster than the method we are using.
-  // This must be an acis bug...
-  //ENTITY_LIST unhooked_bodies;
-  //result = api_unhook_faces( faces_to_remove, false, unhooked_bodies );
-  //unhooked_bodies.init();
-  //ENTITY *ENTITY_ptr = NULL;
-  //while( ENTITY_ptr = unhooked_bodies.next() )
-  //  api_delent( ENTITY_ptr );
-  //if( !result.ok() )
-  //{
-  //  AcisQueryEngine::instance()->ACIS_API_error(result);
-  //  return CUBIT_FAILURE;
-  //}
-
-  // Put cubit owner attributes back
-  reset_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // For some reason, removing faces causes the remaining faces to be single sided
-  result = api_body_to_2d( BODY_ptr );
-  if( !result.ok() )
-  {
-    AcisQueryEngine::instance()->ACIS_API_error(result);
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::remove_FACES_from_BODY_except( BODY *BODY_ptr,
-                                              DLIList<FACE*> &keep_FACE_list )
+CubitStatus AcisTweakTool::tweak_offset( DLIList<Curve*> &curve_list,
+                            double offset_distance,
+                            DLIList<Curve*> *add_curve_list_ptr, 
+                            DLIList<double> *add_offset_list_ptr,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  DLIList<FACE*> FACE_list;
-  AcisQueryEngine::instance()->get_FACEs( BODY_ptr, FACE_list );
-
-  DLIList<FACE*> remove_FACE_list;
-  int i;
-  FACE *FACE_ptr;
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    if( !keep_FACE_list.is_in_list( FACE_ptr ) )
-      remove_FACE_list.append( FACE_ptr );
-  }
-
-  return remove_FACES_from_BODY( BODY_ptr, remove_FACE_list );
-}
-
-CubitStatus
-AcisTweakTool::thicken_BODY( BODY *BODY_ptr, double thickness )
-{
-#if CUBIT_ACIS_VERSION >= 1600
-  // ACIS v16 sometimes removes the Cubit owner attributes when thickening -
-  // this workaround puts them back.
-
-  // Setup tweak attributes so we can preserve Cubit owners on vertices,
-  // edges and faces
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( BODY_ptr, "ttweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Also preserve on body, lump and shell
-  AcisBridge *ab_body_ptr;
-  AcisBridge *ab_lump_ptr;
-  AcisBridge *ab_shell_ptr;
-  get_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-#endif
-
-  // Keep track of input VERTICEs, EDGEs and FACEs for later use
-  DLIList<VERTEX*> input_VERTEX_list;
-  AQE->get_VERTICEs( BODY_ptr, input_VERTEX_list );
-
-  DLIList<EDGE*> input_EDGE_list;
-  AQE->get_EDGEs( BODY_ptr, input_EDGE_list );
-
-  DLIList<FACE*> input_FACE_list;
-  AQE->get_FACEs( BODY_ptr, input_FACE_list );
-
-  // Thicken the body
-  SPAposition box_l(0,0,0);
-  SPAposition box_h(0,0,0);
-  outcome result;
-  result = api_sheet_thicken( BODY_ptr, thickness, false, box_l, box_h);
-  if (!result.ok())
-  {
-    AQE->ACIS_API_error(result);
-    // Thicken doesn't give any sort of error.  Sometimes it won't thicken
-    // because of bad geometry, so just give a hint.
-    PRINT_ERROR( "geometry problem encountered - try healing the body first\n" );
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  // Thicken copies the cubit owner attributes from the original entities
-  // to the other side.  Remove those.
-  int i;
-
-  VERTEX *VERTEX_ptr;
-  DLIList<VERTEX*> VERTEX_list;
-  AQE->get_VERTICEs( BODY_ptr, VERTEX_list );
-  for( i=VERTEX_list.size(); i--; )
-  {
-    VERTEX_ptr = VERTEX_list.get_and_step();
-    if( !input_VERTEX_list.is_in_list( VERTEX_ptr ) )
-      ATTRIB_CUBIT_OWNER::remove_cubit_owner(VERTEX_ptr);
-  }
-
-  EDGE *EDGE_ptr;
-  DLIList<EDGE*> EDGE_list;
-  AQE->get_EDGEs( BODY_ptr, EDGE_list );
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    if( !input_EDGE_list.is_in_list( EDGE_ptr ) )
-      ATTRIB_CUBIT_OWNER::remove_cubit_owner(EDGE_ptr);
-  }
-
-  FACE *FACE_ptr;
-  DLIList<FACE*> FACE_list;
-  AQE->get_FACEs( BODY_ptr, FACE_list );
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    if( !input_FACE_list.is_in_list( FACE_ptr ) )
-      ATTRIB_CUBIT_OWNER::remove_cubit_owner(FACE_ptr);
-  }
-
-#if CUBIT_ACIS_VERSION >= 1600
-  // Put cubit owner attributes back on body, lump and shell
-  reset_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // Replace Cubit owners on vertices, edges, and faces
-  reassign_cubit_owners_from_tweak_attribs( BODY_ptr, "ttweak",
-    pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove thicken tweak attributes
-  remove_named_attribs( BODY_ptr, "ttweak" );
-#endif
-
-  return CUBIT_SUCCESS;
 }
 
-VERTEX *
-AcisTweakTool::find_corresponding_VERTEX( VERTEX *ref_VERTEX_ptr,
-                                          DLIList<VERTEX*> &VERTEX_list )
+CubitStatus AcisTweakTool::tweak_remove( DLIList<Surface*> &surface_list,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_adjoining /*= CUBIT_TRUE*/,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  // Get the reference CUBIT owner attribute
-  AcisBridge *ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ref_VERTEX_ptr);
-  if( !ab_ptr )
-    return NULL;
-
-  PointACIS *ref_point_acis_ptr = CAST_TO( ab_ptr, PointACIS );
-  if( !ref_point_acis_ptr )
-    return NULL;
-
-  // Find the point with the same CUBIT owner attribute in the input VERTEX list
-  VERTEX *VERTEX_ptr;
-  PointACIS *point_acis_ptr;
-  int i;
-  for( i=VERTEX_list.size(); i--; )
-  {
-    VERTEX_ptr = VERTEX_list.get_and_step();
-
-    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(VERTEX_ptr);
-    if( !ab_ptr )
-      continue;
-
-    point_acis_ptr = CAST_TO( ab_ptr, PointACIS );
-    if( !point_acis_ptr )
-      continue;
-
-    if( point_acis_ptr == ref_point_acis_ptr )
-      return VERTEX_ptr;
-  }
-
-  // No match found
-  return NULL;
-}
-
-EDGE *
-AcisTweakTool::find_corresponding_EDGE( EDGE *ref_EDGE_ptr,
-                                        DLIList<EDGE*> &EDGE_list )
-{
-  // Get the reference CUBIT owner attribute
-  AcisBridge *ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ref_EDGE_ptr);
-  if( !ab_ptr )
-    return NULL;
-
-  CurveACIS *ref_curve_acis_ptr = CAST_TO( ab_ptr, CurveACIS );
-  if( !ref_curve_acis_ptr )
-    return NULL;
-
-  // Find the curve with the same CUBIT owner attribute in the input EDGE list
-  EDGE *EDGE_ptr;
-  CurveACIS *curve_acis_ptr;
-  int i;
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-
-    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(EDGE_ptr);
-    if( !ab_ptr )
-      continue;
-
-    curve_acis_ptr = CAST_TO( ab_ptr, CurveACIS );
-    if( !curve_acis_ptr )
-      continue;
-
-    if( curve_acis_ptr == ref_curve_acis_ptr )
-      return EDGE_ptr;
-  }
-
-  // No match found
-  return NULL;
-}
-
-
-LOOP *
-AcisTweakTool::find_corresponding_LOOP( LOOP *ref_LOOP_ptr,
-                                        DLIList<LOOP*> &LOOP_list )
-{
-  // Get the reference CUBIT owner attribute
-  AcisBridge *ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ref_LOOP_ptr);
-  if( !ab_ptr )
-    return NULL;
-
-  LoopACIS *ref_loop_acis_ptr = CAST_TO( ab_ptr, LoopACIS );
-  if( !ref_loop_acis_ptr )
-    return NULL;
-
-  // Find the loop with the same CUBIT owner attribute in the input LOOP list
-  LOOP *LOOP_ptr;
-  LoopACIS *loop_acis_ptr;
-  int i;
-  for( i=LOOP_list.size(); i--; )
-  {
-    LOOP_ptr = LOOP_list.get_and_step();
-
-    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(LOOP_ptr);
-    if( !ab_ptr )
-      continue;
-
-    loop_acis_ptr = CAST_TO( ab_ptr, LoopACIS );
-    if( !loop_acis_ptr )
-      continue;
-
-    if( loop_acis_ptr == ref_loop_acis_ptr )
-      return LOOP_ptr;
-  }
-
-  // No match found
-  return NULL;
-}
-
-FACE *
-AcisTweakTool::find_corresponding_FACE( FACE *ref_FACE_ptr,
-                                        DLIList<FACE*> &FACE_list )
-{
-  // Get the reference CUBIT owner attribute
-  AcisBridge *ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(ref_FACE_ptr);
-  if( !ab_ptr )
-    return NULL;
-
-  SurfaceACIS *ref_surf_acis_ptr = CAST_TO( ab_ptr, SurfaceACIS );
-  if( !ref_surf_acis_ptr )
-    return NULL;
-
-  // Find the surface with the same CUBIT owner attribute in the input FACE list
-  FACE *FACE_ptr;
-  SurfaceACIS *surf_acis_ptr;
-  int i;
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-
-    ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner(FACE_ptr);
-    if( !ab_ptr )
-      continue;
-
-    surf_acis_ptr = CAST_TO( ab_ptr, SurfaceACIS );
-    if( !surf_acis_ptr )
-      continue;
-
-    if( surf_acis_ptr == ref_surf_acis_ptr )
-      return FACE_ptr;
-  }
-
-  // No match found
-  return NULL;
-}
-
-FACE *
-AcisTweakTool::find_corresponding_FACE( AcisBridge *ab_ptr, BODY *BODY_ptr)
-{
-  int i;
-  FACE *FACE_ptr;
-
-  DLIList<FACE*> FACE_list;
-  AcisQueryEngine::instance()->get_FACEs( BODY_ptr, FACE_list );
-
-  FACE_list.reset();
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    if( ATTRIB_CUBIT_OWNER::cubit_owner( FACE_ptr ) == ab_ptr )
-      return FACE_ptr;
-  }
-
-  return NULL;
-}
-
-LOOP *
-AcisTweakTool::find_corresponding_LOOP( AcisBridge *ab_ptr, BODY *BODY_ptr)
-{
-  int i;
-  LOOP *LOOP_ptr;
-
-  DLIList<LOOP*> LOOP_list;
-  AcisQueryEngine::instance()->get_LOOPs( BODY_ptr, LOOP_list );
-
-  LOOP_list.reset();
-  for( i=LOOP_list.size(); i--; )
-  {
-    LOOP_ptr = LOOP_list.get_and_step();
-    if( ATTRIB_CUBIT_OWNER::cubit_owner( LOOP_ptr ) == ab_ptr )
-      return LOOP_ptr;
-  }
-
-  return NULL;
-}
-
-CubitStatus
-AcisTweakTool::get_owner_list( DLIList<EDGE*> &EDGE_list,
-                               DLIList<AcisBridge*> &owner_list )
-{
-  int i;
-  EDGE *EDGE_ptr;
-
-  EDGE_list.reset();
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    owner_list.append_unique( ATTRIB_CUBIT_OWNER::cubit_owner( EDGE_ptr ) );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::get_owner_list( DLIList<FACE*> &FACE_list,
-                               DLIList<AcisBridge*> &owner_list )
-{
-  int i;
-  FACE *FACE_ptr;
-
-  FACE_list.reset();
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    owner_list.append_unique( ATTRIB_CUBIT_OWNER::cubit_owner( FACE_ptr ) );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::get_owner_list( DLIList<LOOP*> &LOOP_list,
-                               DLIList<AcisBridge*> &owner_list )
-{
-  int i;
-  LOOP *LOOP_ptr;
-
-  LOOP_list.reset();
-  for( i=LOOP_list.size(); i--; )
-  {
-    LOOP_ptr = LOOP_list.get_and_step();
-    owner_list.append_unique( ATTRIB_CUBIT_OWNER::cubit_owner( LOOP_ptr ) );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::get_corresponding_FACE_list( DLIList<AcisBridge*> &owner_list,
-                                            BODY *BODY_ptr,
-                                            DLIList<FACE*> &corresponding_FACE_list )
-{
-  int i;
-  AcisBridge *ab_ptr;
-
-  owner_list.reset();
-  for( i=owner_list.size(); i--; )
-  {
-    ab_ptr = owner_list.get_and_step();
-    corresponding_FACE_list.append( find_corresponding_FACE( ab_ptr, BODY_ptr ) );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::get_corresponding_LOOP_list( DLIList<AcisBridge*> &owner_list,
-                                            BODY *BODY_ptr,
-                                            DLIList<LOOP*> &corresponding_LOOP_list )
-{
-  int i;
-  AcisBridge *ab_ptr;
-
-  owner_list.reset();
-  for( i=owner_list.size(); i--; )
-  {
-    ab_ptr = owner_list.get_and_step();
-    corresponding_LOOP_list.append( find_corresponding_LOOP( ab_ptr, BODY_ptr ) );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : get_thickened_BODIES_of_EDGES
-// Member Type: PRIVATE
-// Description: Get thickened BODIES from an input list of EDGEs.  This
-//              function can be called multiple times on the same list of EDGEs
-//              - each time, the EDGEs from the common body that is thickened
-//              are removed from the input EDGE list.  The thickened BODIES are
-//              copied from the sheet the EDGEs are attached to (multiple
-//              BODIES can be returned because the returned thickened BODIES
-//              must be nonmanifold).  For each BODY returned, also output a
-//              list of EDGES (corresponding to the original input EDGEs), a
-//              list of FACEs(corresponding to the original FACEs of the input
-//              BODY) and a list of conjugate FACEs (the "side" FACEs of the
-//              thickened BODY - these are the FACEs we can tweak).
-// Author     : Steve Storm
-// Date       : 03/01/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::get_thickened_BODIES_of_EDGES( const char *command_name,
-                                              DLIList<EDGE*> &input_EDGE_list,
-                                              DLIList<EDGE*> &removed_EDGE_list,
-                                              BODY *&common_BODY_ptr,
-                                              DLIList<BODY*> &thickened_BODY_list,
-                                              DLIList<DLIList<EDGE*>*> &output_EDGE_lists,
-                                              DLIList<DLIList<FACE*>*> &output_FACE_lists,
-                                              DLIList<DLIList<FACE*>*> &conjugate_FACE_lists,
-                                              double thickness )
-{
-  assert( thickened_BODY_list.size() == 0 );
-
-  int i, j;
-
-  EDGE *EDGE_ptr;
-  FACE *FACE_ptr;
-  BODY *BODY_ptr;
-  outcome result;
-
-  // Pull EDGEs out of the input EDGE list that are from a common BODY
-  input_EDGE_list.reset();
-  common_BODY_ptr = NULL;
-  for( i=input_EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = input_EDGE_list.get();
-
-    BODY_ptr = AQE->get_BODY_of_ENTITY( EDGE_ptr );
-
-    if( common_BODY_ptr == NULL )
-      common_BODY_ptr = BODY_ptr;
-
-    if( common_BODY_ptr == BODY_ptr )
-    {
-      removed_EDGE_list.append( EDGE_ptr );
-      input_EDGE_list.change_to( NULL );
-    }
-
-    input_EDGE_list.step();
-  }
-  input_EDGE_list.remove_all_with_value( NULL );
-
-  // Get all FACEs attached to the EDGEs
-  DLIList<FACE*> attached_FACE_list;
-  removed_EDGE_list.reset();
-  for( i=removed_EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = removed_EDGE_list.get_and_step();
-    DLIList<FACE*> tmp_FACE_list;
-    AQE->get_FACEs( EDGE_ptr, tmp_FACE_list );
-
-    if( tmp_FACE_list.size() == 0 )
-    {
-      PRINT_ERROR( "Cannot %s curves that are free\n",
-        command_name );
-      return CUBIT_FAILURE;
-    }
-
-    if( tmp_FACE_list.size() != 1 )
-    {
-      PRINT_ERROR( "Can only %s curves attached to one surface\n",
-        command_name );
-      return CUBIT_FAILURE;
-    }
-
-    attached_FACE_list.append( tmp_FACE_list.get() );
-  }
-
-  // Make sure that all of the FACEs are on a sheet body
-  for( i=attached_FACE_list.size(); i--; )
-  {
-    FACE_ptr = attached_FACE_list.get_and_step();
-    if( FACE_ptr->sides() != DOUBLE_SIDED )
-    {
-      PRINT_ERROR("Cannot %s curves that are not on sheet bodies\n",
-        command_name );
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Copy these FACEs off into a new body
-  // Copy the BODY
-  BODY *copied_BODY_ptr;
-  if( copy_FACES_from_BODY( attached_FACE_list, copied_BODY_ptr ) == CUBIT_FAILURE )
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-
-  // Make the BODY nonmanifold, as thicken can't handle manifold bodies.  Note
-  // the api_unstitch_nonmani api will remove the cubit owner from the resultant
-  // BODY, LUMP and SHELL - we manually put them back on, for proper updating
-  // of the Cubit entities (luckily it leaves them on the FACEs, CURVEs, etc..
-  // Also note the api destroys the input BODY.
-  AcisBridge *ab_body_ptr;
-  AcisBridge *ab_lump_ptr;
-  AcisBridge *ab_shell_ptr;
-  get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  BODY* lumps  = NULL;
-  BODY* sheets = NULL;
-  BODY* lamina = NULL;
-  BODY* wires  = NULL;
-  result = api_unstitch_nonmani( copied_BODY_ptr, lumps, sheets, lamina, wires );
-  if (!result.ok())
-  {
-    AQE->ACIS_API_error(result);
-    AQE->delete_ACIS_BODY( copied_BODY_ptr,CUBIT_TRUE );
-    return CUBIT_FAILURE;
-  }
-
-  // Make sure cubit owner attributes remain on resultant BODY, LUMP, SHELL
-  reset_owner_attribs( sheets, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // Separate bodies (thicken won't work if more than one vol per body)
-  BODY **separated_BODY_array = NULL;
-  int n_body = 0;
-
-  // Note first BODY will always be the input BODY
-  result = api_separate_body( sheets, n_body, separated_BODY_array );
-
-  if (!result.ok())
-  {
-    AQE->ACIS_API_error(result);
-    AQE->delete_ACIS_BODY( sheets, CUBIT_TRUE );
-    return CUBIT_FAILURE;
-  }
-
-  // These BODIES can now be thickened
-  for( i=0; i<n_body; i++ )
-    thickened_BODY_list.append(separated_BODY_array[i]);
-
-  // Loop on separated BODIES
-  thickened_BODY_list.reset();
-  for( i=thickened_BODY_list.size(); i--; )
-  {
-    BODY_ptr = thickened_BODY_list.get_and_step();
-
-    // Make sure cubit owner attributes remain on resultant BODY, LUMP, SHELL
-    reset_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-    // The FACEs in this BODY can efficiently be added to the output list here
-    DLIList<FACE*> *FACE_list_ptr = new DLIList<FACE*>;
-    output_FACE_lists.append( FACE_list_ptr );
-    AQE->get_FACEs( BODY_ptr, *FACE_list_ptr );
-
-    // Thicken the BODY
-    if( thicken_BODY( BODY_ptr, thickness ) == CUBIT_FAILURE )
-    {
-      // Delete all BODIEs, since we failed
-      while( thickened_BODY_list.size() )
-        AQE->delete_ACIS_BODY(thickened_BODY_list.pop(),CUBIT_TRUE);
-      // Clean up memory allocated for the output lists
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-      return CUBIT_FAILURE;
-    }
-
-    // Make sure cubit owner attributes remain on resultant BODY, LUMP, SHELL
-    reset_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-    // Now find EDGEs and conjugate FACEs for the thickened BODY
-    DLIList<EDGE*> *EDGE_list_ptr = new DLIList<EDGE*>;
-    output_EDGE_lists.append( EDGE_list_ptr );
-
-    DLIList<EDGE*> tmp_EDGE_list;
-    AQE->get_EDGEs( BODY_ptr, tmp_EDGE_list );
-    EDGE *tmp_EDGE_ptr;
-    for( j=removed_EDGE_list.size(); j--; )
-    {
-      EDGE_ptr = removed_EDGE_list.get_and_step();
-
-      tmp_EDGE_ptr = find_corresponding_EDGE( EDGE_ptr, tmp_EDGE_list );
-      if( tmp_EDGE_ptr )
-        EDGE_list_ptr->append( tmp_EDGE_ptr );
-    }
-
-    if( !EDGE_list_ptr->size() )
-    {
-      PRINT_ERROR( "Internal error - please report.\n" );
-      // Delete all BODIEs, since we failed
-      while( thickened_BODY_list.size() )
-        AQE->delete_ACIS_BODY(thickened_BODY_list.pop(),CUBIT_TRUE);
-      // Clean up memory allocated for the output lists
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-      return CUBIT_FAILURE;
-    }
-
-    // Find the "conjugate" FACEs (the FACEs that will be tweaked or removed
-    // by the calling function).  These are the FACEs that adjoin the original
-    // FACEs - they will be attached to the input EDGEs and won't exist in the
-    // FACE_list_ptr.
-
-    DLIList<FACE*> *conjugate_FACE_list_ptr = new DLIList<FACE*>;
-    conjugate_FACE_lists.append( conjugate_FACE_list_ptr );
-
-    EDGE_list_ptr->reset();
-    for( j=EDGE_list_ptr->size(); j--; )
-    {
-      EDGE_ptr = EDGE_list_ptr->get_and_step();
-
-      DLIList<FACE*> tmp_FACE_list;
-      AQE->get_FACEs( EDGE_ptr, tmp_FACE_list );
-
-      if( tmp_FACE_list.size() != 2 )
-      {
-        PRINT_ERROR( "Unexpected topology during %s curve function\n", command_name );
-        // Delete all BODIEs, since we failed
-        while( thickened_BODY_list.size() )
-          AQE->delete_ACIS_BODY(thickened_BODY_list.pop(),CUBIT_TRUE);
-        // Clean up memory allocated for the output lists
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( conjugate_FACE_lists.size() ) delete conjugate_FACE_lists.pop();
-        return CUBIT_FAILURE;
-      }
-
-      FACE *FACE_ptr1 = tmp_FACE_list.get_and_step();
-      FACE *FACE_ptr2 = tmp_FACE_list.get();
-
-      if( FACE_list_ptr->is_in_list( FACE_ptr1 ) )
-        conjugate_FACE_list_ptr->append( FACE_ptr2 );
-      else
-        conjugate_FACE_list_ptr->append( FACE_ptr1 );
-    }
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-//=============================================================================
-// Function   : get_thickened_BODIES_of_VERTICES
-// Member Type: PRIVATE
-// Description: Get thickened BODIES from an input list of VERTICEs.  This
-//              function can be called multiple times on the same list of
-//              VERTICEs - each time, the VERTICEs from the common body that is
-//              thickened are removed from the input EDGE list.  These
-//              thickened BODIES are copied from the sheets the VERTICEs are
-//              attached to (multiple BODIES can be returned because the
-//              thickened BODIES must be nonmanifold).  For each BODY returned,
-//              also output a list of the FACEs (corresponding to the original
-//              FACEs of the sheet body), the VERTICEs (corresponding to the
-//              original VERTICEs), and a list of EDGEs created by the
-//              thickening process (from sweeping the original VERTEX - note it
-//              is possible that no EDGE was created from a VERTEX, in which
-//              case a NULL value will exist in the list).
-// Author     : Steve Storm
-// Date       : 02/10/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::get_thickened_BODIES_of_VERTICES( const char *command_name,
-                                                 DLIList<VERTEX*> &input_VERTEX_list,
-                                                 BODY *&common_BODY_ptr,
-                                                 DLIList<BODY*> &thickened_BODY_list,
-                                                 DLIList<DLIList<FACE*>*> &output_FACE_lists,
-                                                 DLIList<DLIList<VERTEX*>*> &output_VERTEX_lists,
-                                                 DLIList<DLIList<EDGE*>*> &output_EDGE_lists,
-                                                 double thickness )
+CubitStatus AcisTweakTool::tweak_remove( DLIList<Curve*> &curve_list,
+                            DLIList<BodySM*> &new_bodysm_list, 
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  assert( thickened_BODY_list.size() == 0 );
-
-  int i, j;
-
-  VERTEX *VERTEX_ptr;
-  FACE *FACE_ptr;
-
-  outcome result;
-
-  // Pull VERTICEs out of the input VERTEX list that are from a common BODY
-  DLIList<VERTEX*> common_VERTEX_list;
-  BODY *BODY_ptr;
-  common_BODY_ptr = NULL;
-  input_VERTEX_list.reset();
-  for( i=input_VERTEX_list.size(); i--; )
-  {
-    VERTEX_ptr = input_VERTEX_list.get();
-    BODY_ptr = AQE->get_BODY_of_ENTITY( VERTEX_ptr );
-
-    if( common_BODY_ptr == NULL )
-      common_BODY_ptr = BODY_ptr;
-
-    if( common_BODY_ptr == BODY_ptr )
-    {
-      common_VERTEX_list.append( VERTEX_ptr );
-      input_VERTEX_list.change_to( NULL );
-    }
-
-    input_VERTEX_list.step();
-  }
-  input_VERTEX_list.remove_all_with_value( NULL );
-
-  // Get all FACEs attached to the VERTICEs
-  DLIList<FACE*> attached_FACE_list;
-  common_VERTEX_list.reset();
-  for( i=common_VERTEX_list.size(); i--; )
-  {
-    VERTEX_ptr = common_VERTEX_list.get_and_step();
-    DLIList<FACE*> tmp_FACE_list;
-    AQE->get_FACEs( VERTEX_ptr, tmp_FACE_list );
-
-    if( tmp_FACE_list.size() == 0 )
-    {
-      PRINT_ERROR( "Cannot %s vertices that are free\n",
-        command_name );
-      return CUBIT_FAILURE;
-    }
-
-    if( tmp_FACE_list.size() != 1 )
-    {
-      PRINT_ERROR( "Can only %s vertices attached to one surface for sheet bodies\n",
-        command_name );
-      return CUBIT_FAILURE;
-    }
-
-    attached_FACE_list.append_unique( tmp_FACE_list.get() );
-  }
-
-  // Make sure that all of the FACEs are on a sheet body
-  for( i=attached_FACE_list.size(); i--; )
-  {
-    FACE_ptr = attached_FACE_list.get_and_step();
-    if( FACE_ptr->sides() != DOUBLE_SIDED )
-    {
-      PRINT_ERROR("Cannot %s vertices that are not on sheet bodies\n",
-        command_name );
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Copy these FACEs off into a new body
-  // Copy the BODY
-  BODY *copied_BODY_ptr;
-  if( copy_FACES_from_BODY( attached_FACE_list, copied_BODY_ptr ) == CUBIT_FAILURE )
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-
-  // Make the BODY nonmanifold, as thicken can't handle manifold bodies.  Note
-  // the api_unstitch_nonmani api will remove the cubit owner from the resultant
-  // BODY, LUMP and SHELL - we manually put them back on, for proper updating
-  // of the Cubit entities (luckily it leaves them on the FACEs, CURVEs, etc..
-  // Also note the api destroys the input BODY.
-  AcisBridge *ab_body_ptr;
-  AcisBridge *ab_lump_ptr;
-  AcisBridge *ab_shell_ptr;
-  get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  BODY* lumps  = NULL;
-  BODY* sheets = NULL;
-  BODY* lamina = NULL;
-  BODY* wires  = NULL;
-  result = api_unstitch_nonmani( copied_BODY_ptr, lumps, sheets, lamina, wires );
-  if (!result.ok())
-  {
-    AQE->ACIS_API_error(result);
-    api_delent( copied_BODY_ptr );
-    return CUBIT_FAILURE;
-  }
-
-  // Make sure cubit owner attributes remain on resultant BODY, LUMP, SHELL
-  reset_owner_attribs( sheets, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // Separate bodies (thicken won't work if more than one vol per body)
-  BODY **separated_BODY_array = NULL;
-  int n_body = 0;
-
-  // Note first BODY will always be the input BODY
-  result = api_separate_body( sheets, n_body, separated_BODY_array );
-  if (!result.ok())
-  {
-    AQE->ACIS_API_error(result);
-    api_delent( sheets );
-    return CUBIT_FAILURE;
-  }
-
-  // These BODIES can now be thickened
-  for( i=0; i<n_body; i++ )
-    thickened_BODY_list.append(separated_BODY_array[i]);
-
-  // Loop on separated BODIES
-  thickened_BODY_list.reset();
-  for( i=thickened_BODY_list.size(); i--; )
-  {
-    BODY_ptr = thickened_BODY_list.get_and_step();
-
-    // Make sure cubit owner attributes remain on resultant BODY, LUMP, SHELL
-    reset_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-    // Keep track of the original EDGEs in the sheet body
-    DLIList<EDGE*> original_EDGE_list;
-    AQE->get_EDGEs( BODY_ptr, original_EDGE_list );
-
-    // The FACEs in this BODY can efficiently be added to the output list here
-    DLIList<FACE*> *FACE_list_ptr = new DLIList<FACE*>;
-    output_FACE_lists.append( FACE_list_ptr );
-    AQE->get_FACEs( BODY_ptr, *FACE_list_ptr );
-
-    // Thicken the BODY
-    if( thicken_BODY( BODY_ptr, thickness ) == CUBIT_FAILURE )
-    {
-      // Delete all BODIEs, since we failed
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      // Clean up memory allocated for the output lists
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      return CUBIT_FAILURE;
-    }
-
-    // Make sure cubit owner attributes remain on resultant BODY, LUMP, SHELL
-    reset_owner_attribs( BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-    // Now find VERTICEs and output EDGEs for the thickened BODY
-    DLIList<VERTEX*> *VERTEX_list_ptr = new DLIList<VERTEX*>;
-    output_VERTEX_lists.append( VERTEX_list_ptr );
-
-    DLIList<VERTEX*> tmp_VERTEX_list;
-    AQE->get_VERTICEs( BODY_ptr, tmp_VERTEX_list );
-    VERTEX *tmp_VERTEX_ptr;
-    for( j=common_VERTEX_list.size(); j--; )
-    {
-      VERTEX_ptr = common_VERTEX_list.get_and_step();
-
-      tmp_VERTEX_ptr = find_corresponding_VERTEX( VERTEX_ptr, tmp_VERTEX_list );
-      if( tmp_VERTEX_ptr )
-        VERTEX_list_ptr->append( tmp_VERTEX_ptr );
-    }
-
-    if( !VERTEX_list_ptr->size() )
-    {
-      PRINT_ERROR( "Internal error - please report.\n" );
-      // Delete all BODIEs, since we failed
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      // Clean up memory allocated for the output lists
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      return CUBIT_FAILURE;
-    }
-
-    // Find the "conjugate" EDGEs (the EDGEs that can be chamfered or filleted
-    // by the calling function).  These are the EDGEs that were created by
-    // the sweeping the VERTICEs during the thicken operation.
-
-    DLIList<EDGE*> *EDGE_list_ptr = new DLIList<EDGE*>;
-    output_EDGE_lists.append( EDGE_list_ptr );
-
-    VERTEX_list_ptr->reset();
-    for( j=VERTEX_list_ptr->size(); j--; )
-    {
-      VERTEX_ptr = VERTEX_list_ptr->get_and_step();
-
-      DLIList<EDGE*> tmp_EDGE_list;
-      AQE->get_EDGEs( VERTEX_ptr, tmp_EDGE_list );
-
-      int k;
-      EDGE *tmp_EDGE_ptr;
-      int found = 0;
-      for( k=tmp_EDGE_list.size(); k--; )
-      {
-        tmp_EDGE_ptr = tmp_EDGE_list.get_and_step();
-        if( !original_EDGE_list.is_in_list( tmp_EDGE_ptr ) )
-        {
-          EDGE_list_ptr->append( tmp_EDGE_ptr );
-          found = 1;
-          break;
-        }
-      }
-      if( !found )
-        EDGE_list_ptr->append( NULL );
-    }
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::prep_for_surface_swap( BODY *thickened_BODY_ptr,
-                                      BODY *copied_BODY_ptr,
-                                      DLIList<AcisBridge*> &owner_FACE_list )
+CubitStatus AcisTweakTool::tweak_target( DLIList<Surface*> &surface_list,
+                            DLIList<Surface*> &target_surf_list,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_flg /*= CUBIT_TRUE*/,
+                            CubitPlane *limit_plane /*= NULL*/,
+                            CubitBoolean reverse_flg /*= CUBIT_FALSE*/,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  // Pull original FACEs off and replace with extended FACEs
-
-  // Remove all but the extended FACEs from thickened_BODY_ptr
-  DLIList<FACE*> tweaked_FACE_list;
-  get_corresponding_FACE_list( owner_FACE_list, thickened_BODY_ptr, tweaked_FACE_list );
-  if( remove_FACES_from_BODY_except( thickened_BODY_ptr, tweaked_FACE_list )
-    == CUBIT_FAILURE )
-  {
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  // Now remove the extended surfaces from the copied_input_BODY_ptr,
-  // to be replaced by the output_FACE_list_ptr
-  tweaked_FACE_list.clean_out();
-  get_corresponding_FACE_list( owner_FACE_list, copied_BODY_ptr, tweaked_FACE_list );
-  if( remove_FACES_from_BODY( copied_BODY_ptr, tweaked_FACE_list )
-    == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::unite_BODIES( BODY *copied_input_BODY_ptr,
-                             DLIList<BODY*> &thickened_BODY_list,
-                             BODY *&master )
+CubitStatus AcisTweakTool::tweak_target( DLIList<Curve*> &curve_list,
+                            DLIList<Surface*> &target_surf_list,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_flg /*= CUBIT_TRUE*/,
+                            CubitPlane *limit_plane /*= NULL*/,
+                            CubitBoolean reverse_flg /*= CUBIT_FALSE*/,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/,
+                            double max_area_increase /*= 0*/ )
 {
-  int i;
-
-  // Unite the thickened BODIEs back into the copied_input_BODY_ptr
-  outcome result;
-  thickened_BODY_list.reset();
-  BODY *BODY_ptr;
-  master = copied_input_BODY_ptr;
-  for( i=thickened_BODY_list.size(); i--; )
-  {
-    BODY_ptr = thickened_BODY_list.get();
-
-    // Do the union of the master and the BODY_ptr.
-    // If this is successful, the result is master and
-    //   BODY_ptr will be deleted
-    result = api_boolean( BODY_ptr, master, NONREG_UNION );
-    if( !result.ok() || (!master) )
-    {
-      AQE->ACIS_API_error(result);
-      while( thickened_BODY_list.size() )
-        AQE->delete_ACIS_BODY(thickened_BODY_list.pop(),CUBIT_TRUE);
-      if (master != NULL) AQE->delete_ACIS_BODY(master,CUBIT_TRUE);
-      return CUBIT_FAILURE;
-    }
-
-    thickened_BODY_list.remove();
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::get_owner_attribs( BODY *BODY_ptr, AcisBridge *&ab_body_ptr,
-     AcisBridge *&ab_lump_ptr, AcisBridge *&ab_shell_ptr)
-{
-  ab_body_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( BODY_ptr );
-
-  ENTITY_LIST lump_list;
-  api_get_lumps( BODY_ptr, lump_list);
-  ab_lump_ptr = NULL;
-  if( lump_list.count() == 1 )
-    ab_lump_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( lump_list[0] );
-
-  ENTITY_LIST shell_list;
-  api_get_shells( BODY_ptr, shell_list);
-  ab_shell_ptr = NULL;
-  if( shell_list.count() == 1 )
-    ab_shell_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( shell_list[0] );
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::reset_owner_attribs( BODY *BODY_ptr,
-                                    AcisBridge *ab_body_ptr,
-                                    AcisBridge *ab_lump_ptr,
-                                    AcisBridge *ab_shell_ptr)
-{
-  // Check BODY
-  if( !ATTRIB_CUBIT_OWNER::cubit_owner(BODY_ptr) )
-  {
-    if( ab_body_ptr )
-      ATTRIB_CUBIT_OWNER::set_cubit_owner( BODY_ptr, ab_body_ptr );
-  }
-
-  // Check LUMP
-  ENTITY_LIST lump_list;
-  api_get_lumps( BODY_ptr, lump_list);
-  if( lump_list.count() == 1 )
-  {
-    if( !ATTRIB_CUBIT_OWNER::cubit_owner(lump_list[0]) )
-    {
-      if( ab_lump_ptr )
-        ATTRIB_CUBIT_OWNER::set_cubit_owner( lump_list[0], ab_lump_ptr );
-    }
-  }
-
-  // Check SHELL
-  ENTITY_LIST shell_list;
-  api_get_shells( BODY_ptr, shell_list);
-  if( shell_list.count() == 1 )
-  {
-    if( !ATTRIB_CUBIT_OWNER::cubit_owner(shell_list[0]) )
-    {
-      if( ab_shell_ptr )
-        ATTRIB_CUBIT_OWNER::set_cubit_owner( shell_list[0], ab_shell_ptr );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::sort_points_by_body_type( DLIList<Point*> &point_list,
-                                         DLIList<Point*> &solid_points,
-                                         DLIList<Point*> &sheet_points )
-{
-  int i, j;
-  Point *point_ptr;
-  PointACIS *point_acis_ptr;
-  VERTEX *VERTEX_ptr;
-  FACE *FACE_ptr;
-  CubitBoolean sheet_face, solid_face;
-  point_list.reset();
-  for( i=point_list.size(); i--; )
-  {
-    point_ptr = point_list.get_and_step();
-
-    point_acis_ptr = dynamic_cast<PointACIS*>(point_ptr);
-    if( point_acis_ptr == NULL )
-    {
-      PRINT_ERROR( "Non-ACIS point encountered.\n" );
-      return CUBIT_FAILURE;
-    }
-
-    VERTEX_ptr = point_acis_ptr->get_VERTEX_ptr();
-
-    // Retrieve FACEs attached to this VERTEX
-    DLIList<FACE*> FACE_list;
-    AcisQueryEngine::instance()->get_FACEs( (ENTITY*)VERTEX_ptr, FACE_list );
-
-    if( FACE_list.size() == 0 )
-    {
-      PRINT_ERROR( "Vertex found not attached to any surfaces.\n" );
-      return CUBIT_FAILURE;
-    }
-
-    // Check all FACEs
-    sheet_face = CUBIT_FALSE;
-    solid_face = CUBIT_FALSE;
-
-    for( j=FACE_list.size(); j--; )
-    {
-      FACE_ptr = FACE_list.get_and_step();
-
-      if( FACE_ptr->sides() == DOUBLE_SIDED )
-        sheet_face = CUBIT_TRUE;
-      else
-        solid_face = CUBIT_TRUE;
-    }
-
-    // Error if attached to both solid and sheet
-    if( sheet_face == CUBIT_TRUE && solid_face == CUBIT_TRUE )
-    {
-      PRINT_ERROR( "Encountered vertex attached to both a sheet and a solid.\n" );
-      return CUBIT_FAILURE;
-    }
-
-    if( sheet_face == CUBIT_TRUE )
-      sheet_points.append( point_ptr );
-    else
-      solid_points.append( point_ptr );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::tweak_chamfer_solid( DLIList<Point*> &point_list,
-                                    double radius,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean keep_old_body,
-                                    CubitBoolean preview )
-{
-  if( point_list.size() == 0 )
-    return CUBIT_SUCCESS;
-
-  outcome result;
-
-  BodySM *body_ptr;
-
-  BODY *BODY_ptr;
-  BODY *copied_BODY_ptr;
-
-  int delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Copy the incoming point_list since we will be pulling points out of it.
-  DLIList<PointACIS*> copied_point_list(point_list.size());
-  CAST_LIST( point_list, copied_point_list, PointACIS );
-  if (point_list.size() != copied_point_list.size())
-  {
-    PRINT_ERROR("Non-ACIS vertices encountered\n");
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  copied_point_list.reset();
-  while( copied_point_list.size() )
-  {
-    DLIList<VERTEX*> VERTEX_list;
-    if( AME->get_copied_VERTICES_of_body( copied_point_list, VERTEX_list,
-      copied_BODY_ptr ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // Get original Body and BODY
-    body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-    BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-    // Now, blend the edges on this body
-    if( chamfer_vertices( VERTEX_list, radius ) == CUBIT_FAILURE )
-    {
-      api_delent(copied_BODY_ptr);
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    if( !preview )
-    {
-      // If we've made it this far, the copied_BODY has been
-      // modified and we can update it in CUBIT
-
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
-
-      BodySM* new_body_ptr = AME->get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr,
-        keep_old_body );
-
-      if (new_body_ptr)
-        new_bodysm_list.append( new_body_ptr );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      ENTITY_LIST face_list;
-      api_get_faces( copied_BODY_ptr, face_list);
-      AcisBridge *ab_face_ptr = NULL;
-      int i;
-      for( i=0; i<face_list.count(); i++ )
-      {
-        ab_face_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( face_list[i] );
-        if( !ab_face_ptr )
-        {
-          // Draw this face
-          AcisDrawTool::instance()->draw_FACE( (FACE*)face_list[i], CUBIT_BLUE );
-        }
-      }
-
-      api_delent(copied_BODY_ptr);
-    }
-  }
-
-  if( preview )
-    GfxPreview::flush();
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::tweak_chamfer_fillet_sheet( DLIList<Point*> &input_point_list,
-                                           double radius,
-                                           int type,
-                                           DLIList<BodySM*> &new_bodysm_list,
-                                           CubitBoolean keep_old_bodies,
-                                           CubitBoolean preview )
+CubitStatus AcisTweakTool::tweak_target( DLIList<Curve*> &curve_list,
+                            DLIList<Curve*> &target_curve_list, 
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_flg /*= CUBIT_TRUE*/,
+                            CubitPlane *limit_plane /*= NULL*/,
+                            CubitBoolean reverse_flg /*= CUBIT_FALSE*/,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/,
+                            double max_area_increase /*= 0*/ )
 {
-  if( input_point_list.size() == 0 )
-    return CUBIT_SUCCESS;
-
-  int i, j;
-  EDGE *EDGE_ptr;
-  outcome result;
-
-  bool delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_bodies);
-
-  // Copy the input point list as we will be removing points from it
-  DLIList<Point*> copied_input_point_list = input_point_list;
-
-  char type_name[8];
-  if( type == 1 )
-    strcpy( type_name, "chamfer" );
-  else
-    strcpy( type_name, "fillet" );
-
-  // Get VERTICEs to chamfer or fillet
-  DLIList<VERTEX*> VERTEX_list;
-  if( get_VERTICEs( input_point_list, VERTEX_list ) == CUBIT_FAILURE )
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-
-  while( VERTEX_list.size() )
-  {
-    BODY *input_BODY_ptr;
-    BodySM *input_bodysm_ptr;
-    DLIList<BODY*> thickened_BODY_list;
-    DLIList<DLIList<FACE*>*> output_FACE_lists;
-    DLIList<DLIList<VERTEX*>*> output_VERTEX_lists;
-    DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-
-    // Get thickened BODIES of VERTICES from a common BODY
-    if( get_thickened_BODIES_of_VERTICES( type_name, VERTEX_list,
-      input_BODY_ptr, thickened_BODY_list, output_FACE_lists,
-      output_VERTEX_lists, output_EDGE_lists ) == CUBIT_FAILURE )
-    {
-      // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    input_bodysm_ptr = AQE->get_body_sm_of_ENTITY( input_BODY_ptr );
-
-    // Tweak the surfaces on the output BODIEs, pull the tweaked surfaces off,
-    // and replace them in the original BODY
-    // First copy the BODY
-    BODY *copied_input_BODY_ptr = AME->copy_BODY(input_BODY_ptr, CUBIT_FALSE);
-
-    BODY *thickened_BODY_ptr;
-    DLIList<FACE*> *output_FACE_list_ptr;
-    DLIList<VERTEX*> *output_VERTEX_list_ptr;
-    DLIList<EDGE*> *output_EDGE_list_ptr;
-    thickened_BODY_list.reset();
-    output_FACE_lists.reset();
-    output_VERTEX_lists.reset();
-    output_EDGE_lists.reset();
-    for( i=thickened_BODY_list.size(); i--; )
-    {
-      thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-      output_FACE_list_ptr = output_FACE_lists.get_and_step();
-      output_VERTEX_list_ptr = output_VERTEX_lists.get_and_step();
-      output_EDGE_list_ptr = output_EDGE_lists.get_and_step();
-
-      // Note - the output EDGE list can have NULL entries in it, as thicken
-      // doesn't always create a curve on the side of the thickened body at
-      // each vertex.  If there is a NULL entry, it means that there isn't
-      // a discernable topology change in the body there anyway, which means
-      // we wouldn't be able to chamfer it anyway.  For now just ignore.
-
-      // Keep track of the FACEs of interest, via their Cubit owners, which
-      // will survive throughout the operation
-      DLIList<AcisBridge*> owner_list;
-      get_owner_list( *output_FACE_list_ptr, owner_list );
-
-      // Error check
-      int cnt = 0;
-      for( j=output_EDGE_list_ptr->size(); j--; )
-      {
-        EDGE_ptr = output_EDGE_list_ptr->get_and_step();
-        if( EDGE_ptr )
-          cnt++;
-      }
-
-      if( cnt == 0 )
-      {
-        PRINT_ERROR( "Unable to %s vertices.\n", type_name );
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_input_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Now, blend the edges on this thickened body
-      CubitStatus status;
-      if( type == 1 )
-        status = chamfer_edges( *output_EDGE_list_ptr, radius );
-      else
-        status = blend_edges( *output_EDGE_list_ptr, radius );
-
-
-      if( status == CUBIT_FAILURE )
-      {
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_input_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-      // Get bodies ready to swap new surfaces for old
-      if( prep_for_surface_swap( thickened_BODY_ptr, copied_input_BODY_ptr,
-        owner_list ) == CUBIT_FAILURE )
-      {
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_input_BODY_ptr );
-        // Return success if any bodies were created
-        return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-      }
-
-    } // End loop on thickened (separated) BODIES
-
-    // Free memory
-    while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-    while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-    while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-
-    // Unite the thickened BODIEs back into the copied_input_BODY_ptr
-    BODY *master;
-    if( unite_BODIES( copied_input_BODY_ptr, thickened_BODY_list, master ) == CUBIT_FAILURE )
-    {
-      // If failure, the unite_BODIES function cleaned up the memory
-      // Return success if any bodies were created
-      return new_bodysm_list.size() ? CUBIT_SUCCESS : CUBIT_FAILURE;
-    }
-
-    // This BODY is done (whew!)
-
-    if( !preview )
-    {
-      // Now cleanout the owner attributes from the copied BODY, if required
-      if( delete_attribs )
-        AQE->remove_cubit_owner_attrib_in_BODY(master);
-
-      BodySM *new_body = AME->get_new_Body( input_bodysm_ptr, input_BODY_ptr,
-        master, keep_old_bodies );
-
-      if( new_body )
-        new_bodysm_list.append( new_body );
-    }
-    else
-    {
-      GfxPreview::clear();
-
-      ENTITY_LIST edge_list;
-      api_get_edges( master, edge_list );
-      AcisBridge *ab_edge_ptr = NULL;
-      for( i=0; i<edge_list.count(); i++ )
-      {
-        ab_edge_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( edge_list[i] );
-        if( !ab_edge_ptr )
-        {
-          // Draw this edge
-          AcisDrawTool::instance()->draw_EDGE( (EDGE*)edge_list[i], CUBIT_BLUE );
-        }
-      }
-
-      api_delent(master);
-    }
-  }
-
-  if( preview )
-    GfxPreview::flush();
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::tweak_chamfer_solid( Point* point_ptr,
-                                    double r1,
-                                    Curve *c1,
-                                    double r2,
-                                    Curve *c2,
-                                    double r3,
-                                    Curve *c3,
-                                    BodySM *&new_bodysm_ptr,
-                                    CubitBoolean keep_old_body,
-                                    CubitBoolean preview )
+CubitStatus AcisTweakTool::tweak_target( Point *point_ptr,
+                            DLIList<Surface*> &modify_surface_list,
+                            CubitVector &target_loc,
+                            BodySM *&new_bodysm_ptr,
+                            CubitBoolean keep_old_body /*= CUBIT_FALSE*/,
+                            CubitBoolean preview /*= CUBIT_FALSE*/ )
 {
-  outcome result;
-
-  BodySM *body_ptr;
-  BODY *BODY_ptr;
-  BODY *copied_BODY_ptr;
-
-  int delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Make sure at least curve 1 supplied
-  if( c1 == NULL )
-  {
-    PRINT_ERROR( "Curve not supplied for radius.\n" );
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  // Check for duplicate input curves.  Note c2 and c3 could be NULL, so we
-  // don't want to error in that case.
-  if( c1==c2 || c1==c3 || (c2 && c2==c3) )
-  {
-    PRINT_ERROR( "Same curve cannot be specified for multiple radii.\n" );
-    return CUBIT_FAILURE;
-  }
-
-  PointACIS *point_acis_ptr = CAST_TO( point_ptr, PointACIS );
-  if( point_acis_ptr == NULL )
-  {
-    PRINT_ERROR( "Non-ACIS vertex encountered.\n" );
-    return CUBIT_FAILURE;
-  }
-
-  DLIList<PointACIS*> copied_point_list(1);
-  copied_point_list.append( point_acis_ptr );
-
-  DLIList<VERTEX*> VERTEX_list;
-  if( AME->get_copied_VERTICES_of_body( copied_point_list, VERTEX_list,
-    copied_BODY_ptr ) == CUBIT_FAILURE )
-  {
-    return CUBIT_FAILURE;
-  }
-
-  // Get original Body and BODY
-  body_ptr = AQE->get_body_sm_of_ENTITY( copied_BODY_ptr );
-  BODY_ptr = dynamic_cast<BodyACIS*>(body_ptr)->get_BODY_ptr();
-
-  if( VERTEX_list.size() != 1 )
-  {
-    PRINT_ERROR( "internal error - please report.\n" );
-    api_delent(copied_BODY_ptr);
-    return CUBIT_FAILURE;
-  }
-
-  VERTEX *VERTEX_ptr = VERTEX_list.get();
-
-  // Get EDGEs attached to this vertex
-  DLIList<EDGE*> EDGE_list;
-  AQE->get_EDGEs( VERTEX_ptr, EDGE_list );
-  if( EDGE_list.size() != 3 )
-  {
-    PRINT_ERROR( "found more than 3 curves attached to vertex.\n" );
-    api_delent(copied_BODY_ptr);
-    return CUBIT_FAILURE;
-  }
-
-  EDGE *ref_EDGE_ptr, *EDGE_ptr1, *EDGE_ptr2, *EDGE_ptr3;
-  CurveACIS *curve_acis_ptr = CAST_TO( c1, CurveACIS );
-  ref_EDGE_ptr = curve_acis_ptr->get_EDGE_ptr();
-  EDGE_ptr1 = find_corresponding_EDGE( ref_EDGE_ptr, EDGE_list );
-  if( EDGE_ptr1 == NULL )
-  {
-    PRINT_ERROR( "Supplied curve not found in volume.\n" );
-    api_delent(copied_BODY_ptr);
-    return CUBIT_FAILURE;
-  }
-
-  if( EDGE_list.move_to( EDGE_ptr1 ) == CUBIT_FALSE )
-  {
-    PRINT_ERROR( "First supplied curve not attached to vertex.\n" );
-    api_delent(copied_BODY_ptr);
-    return CUBIT_FAILURE;
-  }
-
-  // Remove this EDGE from the list
-  EDGE_list.remove();
-
-  // Handle cases where not all curves or radii were supplied
-  if( c2 )
-  {
-    curve_acis_ptr = CAST_TO( c2, CurveACIS );
-    ref_EDGE_ptr = curve_acis_ptr->get_EDGE_ptr();
-    EDGE_ptr2 = find_corresponding_EDGE( ref_EDGE_ptr, EDGE_list );
-    if( EDGE_ptr2 == NULL )
-    {
-      PRINT_ERROR( "Supplied curve not found in volume.\n" );
-      api_delent(copied_BODY_ptr);
-      return CUBIT_FAILURE;
-    }
-
-    if( EDGE_list.move_to( EDGE_ptr2 ) == CUBIT_FALSE )
-    {
-      PRINT_ERROR( "Second supplied curve not attached to vertex.\n" );
-      api_delent(copied_BODY_ptr);
-      return CUBIT_FAILURE;
-    }
-
-    EDGE_list.remove();
-
-    if( c3 )
-    {
-      curve_acis_ptr = CAST_TO( c3, CurveACIS );
-      ref_EDGE_ptr = curve_acis_ptr->get_EDGE_ptr();
-      EDGE_ptr3 = find_corresponding_EDGE( ref_EDGE_ptr, EDGE_list );
-      if( EDGE_ptr3 == NULL )
-      {
-        PRINT_ERROR( "Supplied curve not found in volume.\n" );
-        api_delent(copied_BODY_ptr);
-        return CUBIT_FAILURE;
-      }
-
-      if( EDGE_list.move_to( EDGE_ptr3 ) == CUBIT_FALSE )
-      {
-        PRINT_ERROR( "Third supplied curve not attached to vertex.\n" );
-        api_delent(copied_BODY_ptr);
-        return CUBIT_FAILURE;
-      }
-    }
-    else
-      EDGE_ptr3 = EDGE_list.get();
-  }
-  else
-  {
-    // Random results for the user - ok
-    EDGE_ptr2 = EDGE_list.get_and_step();
-    EDGE_ptr3 = EDGE_list.get();
-  }
-
-  if( r2 <= 0.0 )
-    r2 = r1;
-  if( r3 <= 0.0 )
-    r3 = r2;
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( copied_BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Now, blend the edges on this body
-  result = api_chamfer_vertex( VERTEX_ptr, r1, EDGE_ptr1, r2, EDGE_ptr2, r3,
-    EDGE_ptr3 );
-
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error(result);
-    api_delent(copied_BODY_ptr);
-    return CUBIT_FAILURE;
-  }
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( copied_BODY_ptr, "tweak",
-    pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove tweak attributes
-  remove_named_attribs( copied_BODY_ptr, "tweak" );
-
-  if( !preview )
-  {
-
-  // If we've made it this far, the copied_BODY has been
-  // modified and we can update it in CUBIT
-
-  // Now cleanout the owner attributes from the copied BODY, if required
-  if( delete_attribs )
-    AQE->remove_cubit_owner_attrib_in_BODY(copied_BODY_ptr);
-
-  new_bodysm_ptr = AME->get_new_Body( body_ptr, BODY_ptr, copied_BODY_ptr,
-    keep_old_body );
-  }
-  else
-  {
-    GfxPreview::clear();
-
-    ENTITY_LIST face_list;
-    api_get_faces( copied_BODY_ptr, face_list );
-    AcisBridge *ab_face_ptr = NULL;
-    int i;
-    for( i=0; i<face_list.count(); i++ )
-    {
-      ab_face_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( face_list[i] );
-      if( !ab_face_ptr )
-      {
-        // Draw this face
-        AcisDrawTool::instance()->draw_FACE( (FACE*)face_list[i], CUBIT_BLUE );
-      }
-    }
-
-    api_delent(copied_BODY_ptr);
-
-    GfxPreview::flush();
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::tweak_chamfer_sheet( Point* point_ptr,
-                                    double r1,
-                                    Curve *c1,
-                                    double r2,
-                                    Curve *c2,
-                                    BodySM *&new_bodysm_ptr,
-                                    CubitBoolean keep_old_body,
-                                    CubitBoolean preview )
+CubitStatus AcisTweakTool::make_extended_sheet( DLIList<FACE*> &FACE_list, 
+                                   BODY *&ext_BODY_ptr,
+                                   CubitBox *clip_box_ptr /*= NULL*/,
+                                   bool suppress_errors /*= false*/)
 {
-  int i, j;
-  outcome result;
-  EDGE *EDGE_ptr;
-
-  int delete_attribs =
-    (GeometryModifyTool::instance()->get_new_ids() || keep_old_body);
-
-  // Make sure at least curve 1 supplied
-  if( c1 == NULL )
-  {
-    PRINT_ERROR( "Curve not supplied for radius.\n" );
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-  }
-
-  // Check for duplicate input curves.  Note c2 and c3 could be NULL, so we
-  // don't want to error in that case.
-  if( c1==c2 )
-  {
-    PRINT_ERROR( "Same curve cannot be specified for both radii.\n" );
-    return CUBIT_FAILURE;
-  }
-
-  VERTEX *VERTEX_ptr = AQE->get_VERTEX( point_ptr );
-  if( !VERTEX_ptr )
-  {
-    PRINT_ERROR( "Chamfer vertex must be an ACIS vertex.\n" );
-    return CUBIT_FAILURE;
-  }
-
-  DLIList<VERTEX*> copied_input_VERTEX_list(1);
-  copied_input_VERTEX_list.append( VERTEX_ptr );
-
-  BodySM *input_bodysm_ptr;
-  BODY *input_BODY_ptr;
-  DLIList<BODY*> thickened_BODY_list;
-  DLIList<DLIList<FACE*>*> output_FACE_lists;
-  DLIList<DLIList<VERTEX*>*> output_VERTEX_lists;
-  DLIList<DLIList<EDGE*>*> output_EDGE_lists;
-  if( get_thickened_BODIES_of_VERTICES( "chamfer", copied_input_VERTEX_list,
-    input_BODY_ptr, thickened_BODY_list, output_FACE_lists,
-    output_VERTEX_lists, output_EDGE_lists ) == CUBIT_FAILURE )
-  {
-    return CUBIT_FAILURE;
-  }
-
-  input_bodysm_ptr = AQE->get_body_sm_of_ENTITY( input_BODY_ptr );
-
-  // Tweak the surfaces on the output BODIEs, pull the tweaked surfaces off,
-  // and replace them in the original BODY
-  // First copy the BODY
-  BODY *copied_input_BODY_ptr = AME->copy_BODY(input_BODY_ptr, CUBIT_FALSE);
-
-  BODY *thickened_BODY_ptr;
-  DLIList<FACE*> *output_FACE_list_ptr;
-  DLIList<VERTEX*> *output_VERTEX_list_ptr;
-  DLIList<EDGE*> *output_EDGE_list_ptr;
-  thickened_BODY_list.reset();
-  output_FACE_lists.reset();
-  output_VERTEX_lists.reset();
-  output_EDGE_lists.reset();
-  for( i=thickened_BODY_list.size(); i--; )
-  {
-    thickened_BODY_ptr = thickened_BODY_list.get_and_step();
-    output_FACE_list_ptr = output_FACE_lists.get_and_step();
-    output_VERTEX_list_ptr = output_VERTEX_lists.get_and_step();
-    output_EDGE_list_ptr = output_EDGE_lists.get_and_step();
-
-    // Note - the output EDGE list can have NULL entries in it, as thicken
-    // doesn't always create a curve on the side of the thickened body at
-    // each vertex.  If there is a NULL entry, it means that there isn't
-    // a discernable topology change in the body there anyway, which means
-    // we wouldn't be able to chamfer it anyway.  For now just ignore.
-
-    // Keep track of the FACEs of interest, via their Cubit owners, which
-    // will survive throughout the operation
-    DLIList<AcisBridge*> owner_list;
-    get_owner_list( *output_FACE_list_ptr, owner_list );
-
-    // Error check
-    int cnt = 0;
-    for( j=output_EDGE_list_ptr->size(); j--; )
-    {
-      EDGE_ptr = output_EDGE_list_ptr->get_and_step();
-      if( EDGE_ptr )
-        cnt++;
-    }
-
-    if( cnt == 0 )
-    {
-      PRINT_ERROR( "Unable to chamfer the vertex.\n" );
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      api_delent( copied_input_BODY_ptr );
-      return CUBIT_FAILURE;
-    }
-
-    // Check supplied curves
-    VERTEX *ref_VERTEX_ptr = output_VERTEX_list_ptr->get();
-    EDGE *conj_EDGE_ptr = output_EDGE_list_ptr->get();
-
-    // Get EDGEs attached to this vertex
-    DLIList<EDGE*> EDGE_list;
-    AQE->get_EDGEs( ref_VERTEX_ptr, EDGE_list );
-    if( EDGE_list.size() != 3 )
-    {
-      PRINT_ERROR( "found too many curves attached to vertex.\n" );
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      api_delent( copied_input_BODY_ptr );
-      return CUBIT_FAILURE;
-    }
-
-    EDGE *ref_EDGE_ptr, *EDGE_ptr1, *EDGE_ptr2;
-    CurveACIS *curve_acis_ptr = CAST_TO( c1, CurveACIS );
-    ref_EDGE_ptr = curve_acis_ptr->get_EDGE_ptr();
-    EDGE_ptr1 = find_corresponding_EDGE( ref_EDGE_ptr, EDGE_list );
-    if( EDGE_ptr1 == NULL )
-    {
-      PRINT_ERROR( "Supplied curve not found in volume.\n" );
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      api_delent( copied_input_BODY_ptr );
-      return CUBIT_FAILURE;
-    }
-
-    if( EDGE_list.move_to( EDGE_ptr1 ) == CUBIT_FALSE )
-    {
-      PRINT_ERROR( "First curve not attached to vertex.\n" );
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      api_delent( copied_input_BODY_ptr );
-      return CUBIT_FAILURE;
-    }
-
-    // Remove this EDGE from the list
-    EDGE_list.remove();
-
-    // Handle cases where not all curves or radii were supplied
-    if( c2 )
-    {
-      curve_acis_ptr = CAST_TO( c2, CurveACIS );
-      ref_EDGE_ptr = curve_acis_ptr->get_EDGE_ptr();
-      EDGE_ptr2 = find_corresponding_EDGE( ref_EDGE_ptr, EDGE_list );
-      if( EDGE_ptr2 == NULL )
-      {
-        PRINT_ERROR( "Second curve not found in volume.\n" );
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_input_BODY_ptr );
-        return CUBIT_FAILURE;
-      }
-
-      if( EDGE_list.move_to( EDGE_ptr2 ) == CUBIT_FALSE )
-      {
-        PRINT_ERROR( "Second curve not attached to vertex.\n" );
-        while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-        while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-        while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-        while( thickened_BODY_list.size() )
-          api_delent( thickened_BODY_list.pop() );
-        api_delent( copied_input_BODY_ptr );
-        return CUBIT_FAILURE;
-      }
-
-      EDGE_list.remove();
-    }
-    else
-    {
-      EDGE_ptr2 = EDGE_list.get_and_step();
-      if( EDGE_ptr2 == conj_EDGE_ptr )
-        EDGE_ptr2 = EDGE_list.get();
-    }
-
-    // Determine whether r1 and r2 need to be swapped
-
-    // Are we on the end of the conjugate curve?
-    int on_conj_end = 0;
-    if( conj_EDGE_ptr->end() == ref_VERTEX_ptr )
-      on_conj_end = 1;
-
-    FACE *FACE_ptr = output_FACE_list_ptr->get();
-    LOOP *LOOP_ptr = FACE_ptr->loop();
-
-    // Find CoEdge whose end is our vertex
-    COEDGE *COEDGE_ptr = LOOP_ptr->start();
-    VERTEX *end_VERTEX_ptr;
-    while( COEDGE_ptr != NULL )
-    {
-      end_VERTEX_ptr = COEDGE_ptr->end();
-      if( end_VERTEX_ptr == ref_VERTEX_ptr )
-        break;
-
-      COEDGE_ptr = COEDGE_ptr->next();
-      if( COEDGE_ptr == LOOP_ptr->start() )
-        break;
-    }
-
-    double tmp_r;
-    EDGE_ptr = COEDGE_ptr->edge();
-
-    if( (EDGE_ptr == EDGE_ptr2 && on_conj_end) ||
-        (EDGE_ptr == EDGE_ptr1 && !on_conj_end) )
-    {
-      // Swap
-      tmp_r = r1;
-      r1 = r2;
-      r2 = tmp_r;
-    }
-
-    // Now, blend the edges on this thickened body
-    if( chamfer_edges( *output_EDGE_list_ptr, r1, r2 ) == CUBIT_FAILURE )
-    {
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      api_delent( copied_input_BODY_ptr );
-      return CUBIT_FAILURE;
-    }
-
-    // Get bodies ready to swap new surfaces for old
-    if( prep_for_surface_swap( thickened_BODY_ptr, copied_input_BODY_ptr,
-      owner_list ) == CUBIT_FAILURE )
-    {
-      while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-      while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-      while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-      while( thickened_BODY_list.size() )
-        api_delent( thickened_BODY_list.pop() );
-      api_delent( input_BODY_ptr );
-      return CUBIT_FAILURE;
-    }
-
-  } // End loop on thickened (separated) BODIES
-
-  // Free memory
-  while( output_FACE_lists.size() ) delete output_FACE_lists.pop();
-  while( output_VERTEX_lists.size() ) delete output_VERTEX_lists.pop();
-  while( output_EDGE_lists.size() ) delete output_EDGE_lists.pop();
-
-  // Unite the thickened BODIEs back into the input_BODY_ptr
-  BODY *master;
-  if( unite_BODIES( input_BODY_ptr, thickened_BODY_list, master ) == CUBIT_FAILURE )
-  {
-    // If failure, the unite_BODIES function cleaned up the memory
-    return CUBIT_FAILURE;
-  }
-
-  // This BODY is done (whew!)
-
-  if( !preview )
-  {
-    // Now cleanout the owner attributes from the copied BODY, if required
-    if( delete_attribs )
-      AQE->remove_cubit_owner_attrib_in_BODY(master);
-
-    new_bodysm_ptr = AME->get_new_Body( input_bodysm_ptr, input_BODY_ptr,
-      master, keep_old_body );
-  }
-  else
-  {
-    ENTITY_LIST edge_list;
-    api_get_edges( master, edge_list );
-    AcisBridge *ab_edge_ptr = NULL;
-    for( i=0; i<edge_list.count(); i++ )
-    {
-      ab_edge_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( edge_list[i] );
-      if( !ab_edge_ptr )
-      {
-        // Draw this edge
-        AcisDrawTool::instance()->draw_EDGE( (EDGE*)edge_list[i], CUBIT_BLUE );
-      }
-    }
-
-    api_delent(master);
-
-    GfxPreview::flush();
-  }
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::assign_tweak_attribs( BODY *BODY_ptr, const char *att_name,
-     DLIList<FACE*> &FACE_list, DLIList<AcisBridge*> &ab_FACE_list,
-     DLIList<EDGE*> &EDGE_list, DLIList<AcisBridge*> &ab_EDGE_list,
-     DLIList<VERTEX*> &VERTEX_list, DLIList<AcisBridge*> &ab_VERTEX_list )
+CubitStatus AcisTweakTool::remove_topology( DLIList<Curve*> &curve_list,
+                               DLIList<Surface*> &surface_list,
+                               double backoff_distance,
+                               double small_edge_size,
+                               DLIList<BodySM*> &new_bodysm_list,
+                               CubitBoolean preview )
 {
-  // Assign named attribs to faces, edges and vertices so we can get back to
-  // them after a fillet or chamfer.  These operations split these entities
-  // to make room for the new surfaces, thus we can copy the owner att
-  // during the split.
-
-  int i;
-  outcome result;
-
-  // FACEs
-  AQE->get_FACEs( BODY_ptr, FACE_list );
-  FACE *FACE_ptr;
-  FACE_list.reset();
-  for( i=0; i<FACE_list.size(); i++ )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    result = api_add_generic_named_attribute( FACE_ptr, att_name, i, SplitCopy );
-    if( !result.ok() )
-    {
-      ab_FACE_list.append( NULL );
-      continue;
-    }
-    ab_FACE_list.append( ATTRIB_CUBIT_OWNER::cubit_owner( FACE_ptr ) );
-  }
-
-
-  // EDGEs
-  AQE->get_EDGEs( BODY_ptr, EDGE_list );
-  EDGE *EDGE_ptr;
-  EDGE_list.reset();
-  for( i=0; i<EDGE_list.size(); i++ )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    result = api_add_generic_named_attribute( EDGE_ptr, att_name, i, SplitCopy );
-    if( !result.ok() )
-    {
-      ab_EDGE_list.append( NULL );
-      continue;
-    }
-    ab_EDGE_list.append( ATTRIB_CUBIT_OWNER::cubit_owner( EDGE_ptr ) );
-  }
-
-  // VERTICEs
-  AQE->get_VERTICEs( BODY_ptr, VERTEX_list );
-  VERTEX *VERTEX_ptr;
-  VERTEX_list.reset();
-  for( i=0; i<VERTEX_list.size(); i++ )
-  {
-    VERTEX_ptr = VERTEX_list.get_and_step();
-    result = api_add_generic_named_attribute( VERTEX_ptr, att_name, i, SplitCopy );
-    if( !result.ok() )
-    {
-      ab_VERTEX_list.append( NULL );
-      continue;
-    }
-    ab_VERTEX_list.append( ATTRIB_CUBIT_OWNER::cubit_owner( VERTEX_ptr ) );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::find_corresponding_entity_from_tweak_attrib( BODY *BODY_ptr,
-                                                            const char *att_name,
-                                                            const int ent_type,
-                                                            int input_ent_id,
-                                                            ENTITY *&output_ENTITY_ptr )
-{
-  output_ENTITY_ptr = NULL;
-  ATTRIB_GEN_NAME *ret_att;
-
-  outcome result;
-
-  int i, ent_id;
-  int found = 0;
-  if( ent_type == FACE_TYPE )
-  {
-    DLIList<FACE*> FACE_list;
-    AQE->get_FACEs( BODY_ptr, FACE_list );
-    FACE *FACE_ptr;
-    FACE_list.reset();
-    for( i=FACE_list.size(); i--; )
-    {
-      FACE_ptr = FACE_list.get_and_step();
-      result = api_find_named_attribute( FACE_ptr, att_name, ret_att );
-
-      if( !result.ok() || !ret_att )
-        continue;
-
-      ent_id = ((ATTRIB_GEN_INTEGER *) ret_att)->value();
-
-      if( ent_id == input_ent_id )
-      {
-        if( found == 1 )
-        {
-          // More than one entity with same att
-          output_ENTITY_ptr = NULL;
-          return CUBIT_FAILURE;
-        }
-        output_ENTITY_ptr = (ENTITY *)FACE_ptr;
-        found = 1;
-        break;
-      }
-    }
-    if( found )
-      return CUBIT_SUCCESS;
-    else
-      return CUBIT_FAILURE;
-  }
-
-  else if( ent_type == EDGE_TYPE )
-  {
-    DLIList<EDGE*> EDGE_list;
-    AQE->get_EDGEs( BODY_ptr, EDGE_list );
-    EDGE *EDGE_ptr;
-    EDGE_list.reset();
-    for( i=EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = EDGE_list.get_and_step();
-
-      result = api_find_named_attribute( EDGE_ptr, att_name, ret_att );
-
-      if( !result.ok() || !ret_att )
-        continue;
-
-      ent_id = ((ATTRIB_GEN_INTEGER *) ret_att)->value();
-
-      if( ent_id == input_ent_id )
-      {
-        if( found == 1 )
-        {
-          // More than one entity with same att
-          output_ENTITY_ptr = NULL;
-          return CUBIT_FAILURE;
-        }
-        output_ENTITY_ptr = (ENTITY *)EDGE_ptr;
-        found = 1;
-        break;
-      }
-    }
-    if( found )
-      return CUBIT_SUCCESS;
-    else
-      return CUBIT_FAILURE;
-  }
-
-  else if( ent_type == VERTEX_TYPE )
-  {
-    DLIList<VERTEX*> VERTEX_list;
-    AQE->get_VERTICEs( BODY_ptr, VERTEX_list );
-    VERTEX *VERTEX_ptr;
-    VERTEX_list.reset();
-    for( i=VERTEX_list.size(); i--; )
-    {
-      VERTEX_ptr = VERTEX_list.get_and_step();
-
-      result = api_find_named_attribute( VERTEX_ptr, att_name, ret_att );
-
-      if( !result.ok() || !ret_att )
-        continue;
-
-      ent_id = ((ATTRIB_GEN_INTEGER *) ret_att)->value();
-
-      if( ent_id == input_ent_id )
-      {
-        if( found == 1 )
-        {
-          // More than one entity with same att
-          output_ENTITY_ptr = NULL;
-          return CUBIT_FAILURE;
-        }
-        output_ENTITY_ptr = (ENTITY *)VERTEX_ptr;
-        found = 1;
-        break;
-      }
-    }
-    if( found )
-      return CUBIT_SUCCESS;
-    else
-      return CUBIT_FAILURE;
-  }
-
-  return CUBIT_FAILURE;
-}
-
-CubitStatus
-AcisTweakTool::reassign_cubit_owners_from_tweak_attribs( BODY *BODY_ptr,
-     const char *att_name,
-     DLIList<FACE*> &FACE_list, DLIList<AcisBridge*> &ab_FACE_list,
-     DLIList<EDGE*> &EDGE_list, DLIList<AcisBridge*> &ab_EDGE_list,
-     DLIList<VERTEX*> &VERTEX_list, DLIList<AcisBridge*> &ab_VERTEX_list )
-{
-
-  int i;
-  ENTITY *corr_ENT_ptr;
-  AcisBridge *ab_ptr;
-
-  // FACEs
-  FACE *FACE_ptr;
-  FACE_list.reset();
-  ab_FACE_list.reset();
-  for( i=0; i<FACE_list.size(); i++ )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    ab_ptr = ab_FACE_list.get_and_step();
-    if( find_corresponding_entity_from_tweak_attrib(
-      BODY_ptr, att_name, FACE_TYPE, i, corr_ENT_ptr ) == CUBIT_SUCCESS )
-    {
-      if( ab_ptr )
-        ATTRIB_CUBIT_OWNER::set_cubit_owner( (FACE*)corr_ENT_ptr, ab_ptr );
-    }
-  }
-
-  // EDGEs
-  EDGE *EDGE_ptr;
-  EDGE_list.reset();
-  ab_EDGE_list.reset();
-  for( i=0; i<EDGE_list.size(); i++ )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    ab_ptr = ab_EDGE_list.get_and_step();
-    if( find_corresponding_entity_from_tweak_attrib(
-      BODY_ptr, att_name, EDGE_TYPE, i, corr_ENT_ptr ) == CUBIT_SUCCESS )
-    {
-      if( ab_ptr )
-        ATTRIB_CUBIT_OWNER::set_cubit_owner( (EDGE*)corr_ENT_ptr, ab_ptr );
-    }
-  }
-
-  // VERTICEs
-  VERTEX *VERTEX_ptr;
-  VERTEX_list.reset();
-  ab_VERTEX_list.reset();
-  for( i=0; i<VERTEX_list.size(); i++ )
-  {
-    VERTEX_ptr = VERTEX_list.get_and_step();
-    ab_ptr = ab_VERTEX_list.get_and_step();
-    if( find_corresponding_entity_from_tweak_attrib(
-      BODY_ptr, att_name, VERTEX_TYPE, i, corr_ENT_ptr ) == CUBIT_SUCCESS )
-    {
-      if( ab_ptr )
-        ATTRIB_CUBIT_OWNER::set_cubit_owner( (VERTEX*)corr_ENT_ptr, ab_ptr );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::remove_named_attribs( BODY *BODY_ptr, const char *name )
-{
-  DLIList<FACE*> FACE_list;
-  AQE->get_FACEs( BODY_ptr, FACE_list );
-
-  int i;
-  FACE *FACE_ptr;
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    api_remove_generic_named_attribute(FACE_ptr, name);
-  }
-
-  // EDGEs
-  DLIList<EDGE*> EDGE_list;
-  AQE->get_EDGEs( BODY_ptr, EDGE_list );
-
-  EDGE *EDGE_ptr;
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    api_remove_generic_named_attribute( EDGE_ptr, name );
-  }
-
-  // VERTICEs
-  DLIList<VERTEX*> VERTEX_list;
-  AQE->get_VERTICEs( BODY_ptr, VERTEX_list );
-
-  VERTEX *VERTEX_ptr;
-  for( i=VERTEX_list.size(); i--; )
-  {
-    VERTEX_ptr = VERTEX_list.get_and_step();
-    api_remove_generic_named_attribute( VERTEX_ptr, name );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::blend_edges( DLIList<EDGE*> EDGE_list, double radius  )
-{
-  int i;
-  EDGE *EDGE_ptr;
-  ENTITY_LIST ENTITY_list;
-
-  EDGE_list.reset();
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    if( EDGE_ptr )
-      ENTITY_list.add( EDGE_ptr );
-  }
-
-  if( ENTITY_list.count() == 0 )
+    PRINT_ERROR("This feature is not implemented.\n");
     return CUBIT_FAILURE;
-
-  BODY *BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY( ENTITY_list[0] );
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Now, blend the edges on this body
-  outcome result = api_blend_edges( ENTITY_list, radius );
-
-  if( !result.ok() )
-  {
-    AcisQueryEngine::instance()->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-
-  //printout warnings too
-  err_mess_type *warnings;
-  int nwarn = get_warnings( warnings );
-  if( nwarn > 0 )
-  {
-    PRINT_WARNING("API Warning(s):\n");
-    for( i=0; i<nwarn; i++ )
-      PRINT_INFO("%s\n", find_err_mess( warnings[i]));
-  }
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( BODY_ptr, "tweak", pre_FACE_list,
-    ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove tweak attributes
-  remove_named_attribs( BODY_ptr, "tweak" );
-
-  return CUBIT_SUCCESS;
 }
 
-CubitStatus
-AcisTweakTool::chamfer_edges( DLIList<EDGE*> EDGE_list, double r1, double r2  )
-{
-  if( r2 <= 0.0 )
-    r2 = r1;
 
-  int i;
-  EDGE *EDGE_ptr;
-  ENTITY_LIST ENTITY_list;
-
-  EDGE_list.reset();
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-    if( EDGE_ptr )
-      ENTITY_list.add( EDGE_ptr );
-  }
-
-  if( ENTITY_list.count() == 0 )
-    return CUBIT_FAILURE;
-
-  BODY *BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY( ENTITY_list[0] );
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Now, blend the edges on this body
-  outcome result = api_chamfer_edges( ENTITY_list, r1, r2 );
-
-  if( !result.ok() )
-  {
-    AcisQueryEngine::instance()->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-  else
-    PRINT_INFO("Result was okay\n");
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( BODY_ptr, "tweak", pre_FACE_list,
-    ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove tweak attributes
-  remove_named_attribs( BODY_ptr, "tweak" );
-
-  return CUBIT_SUCCESS;
-}
-
-CubitStatus
-AcisTweakTool::chamfer_vertices( DLIList<VERTEX*> VERTEX_list, double radius  )
-{
-  int i;
-  VERTEX *VERTEX_ptr;
-  ENTITY_LIST ENTITY_list;
-
-  VERTEX_list.reset();
-  for( i=VERTEX_list.size(); i--; )
-  {
-    VERTEX_ptr = VERTEX_list.get_and_step();
-    if( VERTEX_ptr )
-      ENTITY_list.add( VERTEX_ptr );
-  }
-
-  if( ENTITY_list.count() == 0 )
-    return CUBIT_FAILURE;
-
-  BODY *BODY_ptr = AcisQueryEngine::instance()->get_BODY_of_ENTITY( ENTITY_list[0] );
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Now, blend the edges on this body
-  outcome result = api_chamfer_vertices( ENTITY_list, radius );
-
-  if( !result.ok() )
-  {
-    AcisQueryEngine::instance()->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( BODY_ptr, "tweak", pre_FACE_list,
-    ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove tweak attributes
-  remove_named_attribs( BODY_ptr, "tweak" );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : get_EDGES_by_BODY
-// Member Type: PRIVATE
-// Description: Get separate lists of EDGEs from the input Curves by common
-//              BODY
-// Author     : Steve Storm
-// Date       : 12/18/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::get_EDGES_by_BODY( DLIList<Curve*> &input_curve_list,
-                                  DLIList<BODY*> &BODY_list,
-                                  DLIList<DLIList<EDGE*>*> &BODY_EDGE_lists )
-{
-  int i;
-  Curve *curve_ptr;
-  EDGE *EDGE_ptr;
-  BODY *BODY_ptr;
-  BODY *curr_BODY_ptr;
-
-  // Copy input curve list since we don't want to modify it
-  DLIList<Curve*> copied_input_curve_list = input_curve_list;
-
-  // Pull curves out of the input curve list that are from a common BODY
-  DLIList<EDGE*> *curr_BODY_EDGE_list_ptr = NULL;
-  while( copied_input_curve_list.size() )
-  {
-    curr_BODY_ptr = NULL;
-    copied_input_curve_list.reset();
-    for( i=copied_input_curve_list.size(); i--; )
-    {
-      curve_ptr = copied_input_curve_list.get();
-      EDGE_ptr = AQE->get_EDGE( curve_ptr );
-      if( EDGE_ptr == NULL )
-      {
-        PRINT_ERROR( "Non-ACIS curve encountered.\n" );
-        BODY_list.clean_out();
-        while( BODY_EDGE_lists.size() ) delete BODY_EDGE_lists.pop();
-        return CUBIT_FAILURE;
-      }
-
-      BODY_ptr = AQE->get_BODY_of_ENTITY( EDGE_ptr );
-      if( curr_BODY_ptr == NULL )
-      {
-        BODY_list.append( BODY_ptr );
-        curr_BODY_ptr = BODY_ptr;
-        curr_BODY_EDGE_list_ptr = new DLIList<EDGE*>;
-        BODY_EDGE_lists.append( curr_BODY_EDGE_list_ptr );
-      }
-
-      if( curr_BODY_ptr == BODY_ptr )
-      {
-        curr_BODY_EDGE_list_ptr->append( EDGE_ptr );
-        copied_input_curve_list.change_to( NULL );
-      }
-
-      copied_input_curve_list.step();
-    }
-
-    copied_input_curve_list.remove_all_with_value( NULL );
-    curr_BODY_ptr = NULL;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : get_EDGES_by_BODY
-// Member Type: PRIVATE
-// Description: Get separate lists of EDGEs from the input Curves by common
-//              BODY
-// Author     : Steve Storm
-// Date       : 12/18/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::get_EDGES_by_BODY( DLIList<EDGE*> &input_EDGE_list,
-                                  DLIList<BODY*> &BODY_list,
-                                  DLIList<DLIList<EDGE*>*> &BODY_EDGE_lists )
-{
-  int i;
-  EDGE *EDGE_ptr;
-  BODY *BODY_ptr;
-  BODY *curr_BODY_ptr;
-
-  // Copy input EDGE list since we don't want to modify it
-  DLIList<EDGE*> copied_input_EDGE_list = input_EDGE_list;
-
-  // Pull EDGEs out of the input EDGE list that are from a common BODY
-  DLIList<EDGE*> *curr_BODY_EDGE_list_ptr = NULL;
-  while( copied_input_EDGE_list.size() )
-  {
-    curr_BODY_ptr = NULL;
-    copied_input_EDGE_list.reset();
-    for( i=copied_input_EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = copied_input_EDGE_list.get();
-
-      BODY_ptr = AQE->get_BODY_of_ENTITY( EDGE_ptr );
-      if( curr_BODY_ptr == NULL )
-      {
-        BODY_list.append( BODY_ptr );
-        curr_BODY_ptr = BODY_ptr;
-        curr_BODY_EDGE_list_ptr = new DLIList<EDGE*>;
-        BODY_EDGE_lists.append( curr_BODY_EDGE_list_ptr );
-      }
-
-      if( curr_BODY_ptr == BODY_ptr )
-      {
-        curr_BODY_EDGE_list_ptr->append( EDGE_ptr );
-        copied_input_EDGE_list.change_to( NULL );
-      }
-
-      copied_input_EDGE_list.step();
-    }
-
-    copied_input_EDGE_list.remove_all_with_value( NULL );
-    curr_BODY_ptr = NULL;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : all_complete_holes
-// Member Type: PRIVATE
-// Description: Determine if given EDGEs form complete internal holes.  LOOPs
-//              must be on a sheet BODY.  Return those LOOPs.  All given EDGEs
-//              must be in the same BODY.
-// Author     : Steve Storm
-// Date       : 12/18/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::all_complete_internal_loops( DLIList<EDGE*> &BODY_EDGE_list,
-                                            DLIList<LOOP*> &LOOP_list )
-{
-  int i;
-  EDGE *EDGE_ptr;
-  LOOP *LOOP_ptr;
-
-  DLIList<EDGE*> copied_EDGE_list = BODY_EDGE_list;
-
-  while( copied_EDGE_list.size() )
-  {
-    copied_EDGE_list.reset();
-    EDGE_ptr = copied_EDGE_list.get();
-
-    DLIList<LOOP*> EDGE_LOOP_list;
-    AQE->get_LOOPs( EDGE_ptr, EDGE_LOOP_list );
-    if( EDGE_LOOP_list.size() == 0 )
-    {
-      LOOP_list.clean_out();
-      return CUBIT_FAILURE;
-    }
-
-    // Should always be just one LOOP per EDGE
-    LOOP_ptr = EDGE_LOOP_list.get();
-
-    loop_type type;
-    outcome result = api_loop_type( LOOP_ptr, type );
-    if( !result.ok() )
-    {
-      AQE->ACIS_API_error(result);
-      LOOP_list.clean_out();
-      return CUBIT_FAILURE;
-    }
-    if( type != loop_hole )
-    {
-      LOOP_list.clean_out();
-      return CUBIT_FAILURE;
-    }
-
-    DLIList<EDGE*> LOOP_EDGE_list;
-    AQE->get_EDGEs( LOOP_ptr, LOOP_EDGE_list );
-
-    LOOP_EDGE_list.reset();
-    for( i=LOOP_EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = LOOP_EDGE_list.get_and_step();
-
-      if( copied_EDGE_list.move_to( EDGE_ptr ) == CUBIT_TRUE )
-      {
-        // Remove from the list
-        copied_EDGE_list.change_to( NULL );
-      }
-      else
-      {
-        // All EDGEs must be in the input EDGE list
-        LOOP_list.clean_out();
-        return CUBIT_FAILURE;
-      }
-    }
-
-    LOOP_list.append( LOOP_ptr );
-
-    copied_EDGE_list.remove_all_with_value( NULL );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : remove_LOOPs
-// Member Type: PRIVATE
-// Description: Remove the given internal LOOPs (from a sheet BODY).
-// Author     : Steve Storm
-// Date       : 12/18/05
-//=============================================================================
-CubitStatus
-AcisTweakTool::remove_LOOPs( DLIList<LOOP*> &LOOP_list )
-{
-  if( LOOP_list.size() == 0 )
-    return CUBIT_SUCCESS;
-
-  int i;
-  FACE *FACE_ptr;
-  LOOP *LOOP_ptr;
-
-  LOOP_list.reset();
-  for( i=LOOP_list.size(); i--; )
-  {
-    LOOP_ptr = LOOP_list.get_and_step();
-
-    FACE_ptr = LOOP_ptr->face();
-    if( FACE_ptr->sides() != DOUBLE_SIDED )
-    {
-      PRINT_ERROR("Cannot remove loops that are not on sheet bodies\n" );
-      return CUBIT_FAILURE;
-    }
-
-    LOOP *tmp_LOOP_ptr = FACE_ptr->loop();
-
-    if( tmp_LOOP_ptr == LOOP_ptr )
-    {
-      // First loop in list is an internal loop we are trying to remove
-      tmp_LOOP_ptr = tmp_LOOP_ptr->next();
-      FACE_ptr->set_loop( tmp_LOOP_ptr );
-    }
-    else
-    {
-      LOOP *prev_LOOP_ptr = NULL;
-      LOOP *next_LOOP_ptr = NULL;
-      while ( tmp_LOOP_ptr != LOOP_ptr )
-      {
-        prev_LOOP_ptr = tmp_LOOP_ptr;
-        tmp_LOOP_ptr = tmp_LOOP_ptr->next();
-      }
-      next_LOOP_ptr = LOOP_ptr->next();
-
-      // Now set the next LOOP pointer of the previous to the next
-      prev_LOOP_ptr->set_next( next_LOOP_ptr );
-    }
-
-    // Now delete this LOOP and all entities below it
-    outcome result = api_delent( LOOP_ptr );
-    if( !result.ok() )
-    {
-      AcisQueryEngine::instance()->ACIS_API_error(result);
-      PRINT_ERROR( "Unable to remove loop - aborting\n" );
-      return CUBIT_FAILURE;
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : remove_holes
-// Member Type: PRIVATE
-// Description: Remove all holes from the given sheet BODY.
-// Author     : Steve Storm
-// Date       : 2/12/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::remove_holes( BODY *sheet_BODY_ptr )
-{
-  // Holes in a sheet body will be internal LOOPs with only 1 coedge on each
-  // curve.
-
-  // Get all LOOPs of the sheet BODY
-  DLIList<LOOP*> LOOP_list;
-  AQE->get_LOOPs( sheet_BODY_ptr, LOOP_list );
-
-  // Put internal LOOPs to remove into a separate list
-  DLIList<LOOP*> hole_LOOP_list;
-  int i;
-  outcome result;
-  loop_type type;
-  ENTITY_LIST COEDGES;
-  LOOP *LOOP_ptr;
-  for( i=LOOP_list.size(); i--; )
-  {
-    LOOP_ptr = LOOP_list.get_and_step();
-
-    result = api_loop_type( LOOP_ptr, type );
-    if( !result.ok() )
-    {
-      AQE->ACIS_API_error(result);
-      return CUBIT_FAILURE;
-    }
-    if( type == loop_hole )
-    {
-      // Check coedges on edges in loop - if more than one it is shared and we
-      // don't want to remove it.
-      DLIList<EDGE*> EDGE_list;
-      AQE->get_EDGEs( LOOP_ptr, EDGE_list );
-      if( EDGE_list.size() )
-      {
-        EDGE *EDGE_ptr = EDGE_list.get();
-
-        result = api_get_coedges( EDGE_ptr, COEDGES);
-        if( !result.ok() )
-        {
-          AQE->ACIS_API_error(result);
-          return CUBIT_FAILURE;
-        }
-
-        ENTITY *COEDGE_ptr;
-        COEDGES.init();
-
-        int good = 1;
-
-        while( (COEDGE_ptr = COEDGES.next() ) != NULL )
-        {
-          if( COEDGES.iteration_count() == 1 )
-            continue;
-           good--;
-        }
-
-        COEDGES.clear();
-
-        if( good > 0 )
-          hole_LOOP_list.append( LOOP_ptr );
-      }
-    }
-  }
-
-  // Remove the internal LOOPs
-  if( remove_LOOPs( hole_LOOP_list ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : extrema_pln_BODY
-// Member Type: PRIVATE
-// Description: Finds the extrema distance from a plane to an ACIS BODY
-//              (perpendicular distance from plane to farthest extent of BODY),
-//              on one side of the plane (by default on the front of the plane
-//              - direction of plane normal).  If the entire BODY lies on the
-//              other side of the plane, the extrema distance is 0.0.
-// Author     : Steve Storm
-// Date       : 1/15/06
-//=============================================================================
-CubitStatus AcisTweakTool::extrema_pln_BODY( CubitPlane &plane, BODY *BODY_ptr,
-                                             double &extrema_dist,
-                                             int back_side )
-{
-  // Method: find EXTREMA point of BODY in direction of plane norm, check
-  // distance to plane.
-  ENTITY_LIST ENTITY_list;
-  ENTITY_list.add( BODY_ptr );
-
-  CubitVector dir =  back_side ? -(plane.normal()) : plane.normal();
-
-  SPAvector acis_dirs[3];
-  acis_dirs[0].set_x( dir.x() );
-  acis_dirs[0].set_y( dir.y() );
-  acis_dirs[0].set_z( dir.z() );
-
-  SPAposition acis_pos;
-	param_info info;
-	outcome result = api_entity_extrema( ENTITY_list, 1, acis_dirs, acis_pos,
-                                       info );
-  if( !result.ok() )
-	{
-    AcisQueryEngine::instance()->ACIS_API_error( result );
-    return CUBIT_FAILURE;
-	}
-
-  CubitVector extrema_pnt( acis_pos.x(), acis_pos.y(), acis_pos.z() );
-
-  // Get intersection point on plane
-  CubitVector int_pnt;
-  int_pnt = plane.intersect( extrema_pnt, dir );
-
-  // Get direction from int_pnt to extrema_pnt
-  CubitVector dir2( int_pnt, extrema_pnt  );
-
-  // Note: angle between vectors acute (<90) if dot product > 0.  In
-  // this case the vectors would be going the same direction and the extrema
-  // point is on the correct side of the plane
-  if( dir % dir2 > 0.0 )
-    extrema_dist = int_pnt.distance_between( extrema_pnt );
-  else
-    extrema_dist = 0.0;
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tweak_FACEs_to_target
-// Member Type: PRIVATE
-// Description: Tweak the given FACEs (which must all be part of the same BODY)
-//              to the given target FACE.
-// Author     : Steve Storm
-// Date       : 1/15/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::tweak_FACEs_to_target( DLIList<FACE*> &source_FACE_list,
-                                      FACE *target_FACE_ptr,
-                                      CubitBoolean reverse_flg,
-                                      CubitBoolean skip_self_int_check )
-{
-  int i;
-  outcome result;
-  int num_faces = source_FACE_list.size();
-
-  // Get normal of tool (target) surface
-  CubitVector location;
-  CubitVector target_normal_vec = surface_normal( target_FACE_ptr, location );
-  if( reverse_flg )
-    target_normal_vec = -target_normal_vec;
-
-  // Save the center point of the bounding box of the target face
-  SPAposition target_surf_bb_center( location.x(), location.y(), location.z() );
-
-  // Create arrays of input FACEs for tweak API.
-  // Note: Apparently the API requires a copy of the tool geometry for each
-  //       tweak surface
-  FACE** source_FACES = new FACE*[num_faces];
-  DLIList<FACE*> target_FACE_list(num_faces);
-  SURFACE** target_SURFACES = new SURFACE*[num_faces];
-  int* target_sense = new int[num_faces];
-  FACE *FACE_ptr;
-  source_FACE_list.reset();
-  for( i=0; i<num_faces; i++ )
-  {
-    // Fill source_FACES array
-    FACE_ptr = source_FACE_list.get_and_step();
-    source_FACES[i] = FACE_ptr;
-
-    // Fill target_SURFACES array
-    ENTITY* copied_entity_ptr = 0;
-    api_copy_entity_contents(target_FACE_ptr, copied_entity_ptr);
-    if( copied_entity_ptr == 0 )
-    {
-      while( target_FACE_list.size() ) api_delent( target_FACE_list.pop() );
-      delete []source_FACES;
-      delete []target_SURFACES;
-      delete []target_sense;
-      PRINT_ERROR( "Invalid ACIS target surface -- aborting\n" );
-      return CUBIT_FAILURE;
-    }
-    target_FACE_list.append( (FACE*)copied_entity_ptr );
-    target_SURFACES[i] = ((FACE*)copied_entity_ptr)->geometry();
-
-    SPAposition dummy;
-    SPAunit_vector tmp_vec;
-    FACE_ptr->geometry()->equation().point_perp( target_surf_bb_center, dummy, tmp_vec );
-    CubitVector tweak_normal_vec( tmp_vec.x(), tmp_vec.y(), tmp_vec.z() );
-
-    // Fill target_sense array
-    target_sense[i] = ((tweak_normal_vec % target_normal_vec) < 0.0);
-  }
-
-  SPAposition box_h(0,0,0);
-  SPAposition box_l(0,0,0);
-
-  // This operation sometimes destroys owner attributes
-  BODY *copied_BODY_ptr = AQE->get_BODY_of_ENTITY( source_FACE_list.get() );
-  AcisBridge *ab_body_ptr;
-  AcisBridge *ab_lump_ptr;
-  AcisBridge *ab_shell_ptr;
-  get_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( copied_BODY_ptr, "tweak", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-#if CUBIT_ACIS_VERSION < 1600
-  result = api_tweak_faces( num_faces, (FACE**)source_FACES,
-                            target_SURFACES, target_sense, box_h, box_l );
-#else
-  if( skip_self_int_check )
-  {
-    lop_options lop_opt = lop_options();
-    lop_opt.set_repair_self_int(FALSE);
-    result = api_tweak_faces( num_faces, (FACE**)source_FACES,
-                              target_SURFACES, target_sense, box_h, box_l, &lop_opt );
-  }
-  else
-  {
-    result = api_tweak_faces( num_faces, (FACE**)source_FACES,
-                              target_SURFACES, target_sense, box_h, box_l );
-  }
-#endif
-
-  // Reset the owner attributes
-  reset_owner_attribs( copied_BODY_ptr, ab_body_ptr, ab_lump_ptr, ab_shell_ptr );
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( copied_BODY_ptr, "tweak",
-    pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  remove_named_attribs( copied_BODY_ptr, "tweak" );
-
-  // Freeup memory
-  while( target_FACE_list.size() ) api_delent( target_FACE_list.pop() );
-  delete []source_FACES;
-  delete []target_SURFACES;
-  delete []target_sense;
-
-  if( !result.ok() )
-  {
-    AcisQueryEngine::instance()->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : surface_normal
-// Member Type: PRIVATE
-// Description: Get normal of underlying surface of given FACE.  The normal is
-//              found at the approximate centroid of the FACE.  Note the normal
-//              is NOT adjusted for the FACE sense.
-// Author     : Steve Storm
-// Date       : 1/15/06
-//=============================================================================
-CubitVector
-AcisTweakTool::surface_normal( FACE *FACE_ptr, CubitVector &location,
-                               CubitBoolean calc_loc )
-{
-  SPAunit_vector acis_normal;
-
-  if( calc_loc )
-  {
-    // Get bounding box of FACE
-    CubitBox box = AQE->bounding_box(AQE->bounding_box( FACE_ptr ));
-
-    // Get center point of bounding box
-    CubitVector center = box.center();
-
-    // Move to the FACE and get the normal at that location
-    SPAposition acis_point ( center.x(), center.y(), center.z() );
-    SPAposition acis_point_on_surf;
-    (FACE_ptr->geometry()->equation()).point_perp( acis_point,
-      acis_point_on_surf, acis_normal );
-
-    location.set( acis_point_on_surf.x(), acis_point_on_surf.y(),
-      acis_point_on_surf.z() );
-  }
-  else
-  {
-    SPAposition acis_point ( location.x(), location.y(), location.z() );
-    SPAposition acis_point_on_surf;
-    (FACE_ptr->geometry()->equation()).point_perp( acis_point,
-      acis_point_on_surf, acis_normal );
-  }
-
-  CubitVector return_vector( acis_normal.x(), acis_normal.y(),
-    acis_normal.z() );
-
-  return return_vector;
-}
-
-//=============================================================================
-// Function   : FACE_normal
-// Member Type: PRIVATE
-// Description: Get normal of given FACE.  The normal is found at the
-//              approximate centroid of the FACE.  Note the normal is adjusted
-//              for the FACE sense.
-// Author     : Steve Storm
-// Date       : 1/28/06
-//=============================================================================
-CubitVector
-AcisTweakTool::FACE_normal( FACE *FACE_ptr, CubitVector &location,
-                            CubitBoolean calc_loc )
-{
-  CubitVector FACE_normal = surface_normal( FACE_ptr, location, calc_loc );
-
-  // Adjust for the FACE sense
-  if( FACE_ptr->sense() == REVERSED )
-    FACE_normal = -FACE_normal;
-
-  return FACE_normal;
-}
-
-//=============================================================================
-// Function   : weighted_average_FACE_normal
-// Member Type: PRIVATE
-// Description: Get weighted average normal of given FACEs.  The normals are
-//              weighted by FACE area utilizing the graphics facets.
-// Author     : Steve Storm
-// Date       : 2/21/06
-//=============================================================================
-CubitVector
-AcisTweakTool::weighted_average_FACE_normal( DLIList<FACE*> &FACE_list )
-{
-  int i;
-  FACE *FACE_ptr;
-  CubitVector total_vec;
-
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    CubitVector FACE_norm;
-    double FACE_weight;
-    weighted_average_FACE_normal( FACE_ptr, FACE_norm, FACE_weight );
-
-    total_vec = total_vec += FACE_weight * FACE_norm;
-  }
-
-  //PRINT_INFO( "Weighted normal vec = %f, %f, %f\n", total_vec.x(), total_vec.y(),
-  //  total_vec.z() );
-
-  total_vec.normalize();
-  //PRINT_INFO( "Weighted normal normalized = %f, %f, %f\n", total_vec.x(), total_vec.y(),
-  //  total_vec.z() );
-
-  return total_vec;
-}
-
-//=============================================================================
-// Function   : weighted_average_FACE_normal
-// Member Type: PRIVATE
-// Description: Get normal (unit vector) and weight (area factor) of a given
-//              FACE.  The graphics facets are utilized in the calculation.
-// Author     : Steve Storm
-// Date       : 2/21/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::weighted_average_FACE_normal( FACE *FACE_ptr,
-                                             CubitVector &normal,
-                                             double &weight )
-{
-  int i;
-  int num_tris, num_pnts, num_facets;
-  GMem g_mem;
-  unsigned short norm_tol = 10;
-  double dist_tol = -1.0;
-  AQE->get_graphics( FACE_ptr, num_tris, num_pnts, num_facets,
-    &g_mem, norm_tol, dist_tol );
-
-  if(num_tris < 1)
-  {
-    // Decrease tolerance and try again (we can get this for small features)
-    norm_tol /= 2;
-    AQE->get_graphics( FACE_ptr, num_tris, num_pnts, num_facets, &g_mem,
-      norm_tol, dist_tol);
-  }
-
-  if(num_tris < 1)
-  {
-    // Lets give up
-    PRINT_ERROR( "Unable to find average normal of a surface\n" );
-    return CUBIT_FAILURE;
-  }
-
-  // Initialize
-  weight = 0.0;
-  normal.set( 0.0, 0.0, 0.0 );
-
-  // Loop through the triangles
-  double tri_weight, A, B, C;
-  GPoint p[3];
-  GPoint* plist = g_mem.point_list();
-  int* facet_list = g_mem.facet_list();
-  int c = 0;
-  for( i=0; i<num_tris; i++ )
-  {
-    p[0] = plist[facet_list[++c]];
-    p[2] = plist[facet_list[++c]];
-    p[1] = plist[facet_list[++c]];
-    c++;
-
-    // Get centroid
-    CubitVector p1( p[0].x, p[0].y, p[0].z );
-    CubitVector p2( p[2].x, p[2].y, p[2].z );
-    CubitVector p3( p[1].x, p[1].y, p[1].z );
-
-    CubitVector center = (p1 + p2 + p3)/3.0;
-
-    // Get normal direction at the point closest to the location on the
-    // surface.  This method usually returns the normal, but if the nearest
-    // point is a singularity (like the apex of a cone), this method still
-    // returns an outward direction. The base class definition returns
-    // point_normal, which is used by default on simple surfaces.
-    SPAposition acis_center( center.x(), center.y(), center.z() );
-    SPAunit_vector acis_normal = (FACE_ptr->geometry()->equation()).
-      point_outdir( acis_center );
-
-    CubitVector norm( acis_normal.x(), acis_normal.y(), acis_normal.z() );
-
-    // Get triangle area
-    A = p1.y() * p2.z() + p1.z() * p3.y() + p2.y() * p3.z() -
-      p2.z() * p3.y() - p1.y() * p3.z() - p1.z() * p2.y();
-
-    B = p1.z() * p2.x() + p1.x() * p3.z() + p2.z() * p3.x() -
-      p2.x() * p3.z() - p1.z() * p3.x() - p1.x() * p2.z();
-
-    C = p1.x() * p2.y() + p1.y() * p3.x() + p2.x() * p3.y() -
-      p2.y() * p3.x() - p1.x() * p3.y() - p1.y() * p2.x();
-
-    //Note: triangle area = 0.5*(sqrt(A*A+B*B+C*C));
-
-    tri_weight = 0.5*(A*A+B*B+C*C);
-
-    normal += tri_weight * norm;
-
-    weight += tri_weight;
-
-  }
-
-  //double FACE_area;
-  //double accur_achieved;
-  //outcome result = api_ent_area( FACE_ptr, .001, FACE_area, accur_achieved );
-  //PRINT_INFO( "\nArea by ACIS = %f\n", FACE_area );
-  //PRINT_INFO( "Area by facets = %f\n", weight );
-
-  normal.normalize();
-
-  if( FACE_ptr->sense() == REVERSED )
-    normal = -normal;
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : create_offset_planar_body
-// Member Type: PRIVATE
-// Description: Create a planar ACIS BODY from the given CubitPlane and offset.
-//              The offset is in the direction of the plane's normal.  The
-//              plane is arbitrarily 10x10x10 in size near the origin.
-// Author     : Steve Storm
-// Date       : 3/19/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::create_offset_planar_body( CubitPlane &plane, double offset,
-                                          BODY *&planar_BODY_ptr )
-{
-  // Get corners of the surface
-  CubitVector normal = plane.normal();
-  CubitVector x, y;
-  normal.orthogonal_vectors( x, y );
-  // There is a bug in the point_on_plane (it needs to check against a small
-  // value instead of an exact 0) - for now, do our own calculation.  This
-  // allows us to check for an invalid plane anyway...
-  //CubitVector p1 = target_plane.point_on_plane();
-  CubitVector p1;
-  double coeff = plane.coefficient();
-  if( fabs( normal.x() ) > 1e-6 )
-    p1.set( -coeff/normal.x(), 0.0, 0.0 );
-  else if( fabs( normal.y() ) > 1e-6 )
-    p1.set( 0.0, -coeff/normal.y(), 0.0 );
-  else if( fabs( normal.z() ) > 1e-6 )
-    p1.set( 0.0, 0.0, -coeff/normal.z() );
-  else
-  {
-    PRINT_ERROR( "Error constructing offset plane past the targets\n" );
-    return CUBIT_FAILURE;
-  }
-
-  p1.next_point( normal, offset, p1 );
-  CubitVector p2, p3, p4;
-  p1.next_point( x, 5.0, p1 );
-  p1.next_point( y, 5.0, p1 );
-  p1.next_point( -x, 10.0, p2 );
-  p2.next_point( -y, 10.0, p3 );
-  p3.next_point( x, 10.0, p4 );
-
-  planar_BODY_ptr = AME->make_planar_quad_BODY( p1, p2, p3, p4 );
-  if( !planar_BODY_ptr )
-  {
-    PRINT_ERROR( "Error constructing offset plane past the targets\n" );
-    return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : create_extended_sheet
-// Member Type: PRIVATE
-// Description: Extend out a set of FACEs and place into a new sheet BODY.
-//              Holes are removed and the BODY is healed for consistent FACE
-//              normals.  The BODY is also regularized.
-// Author     : Steve Storm
-// Date       : 1/15/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::create_extended_sheet( DLIList<FACE*> &FACE_list,
-                                      BODY *&ext_BODY_ptr )
-{
-  // Method:
-  // Copy FACEs into separate sheet bodies
-  // If not entirely surrounded by other FACEs, extend past super bounding box
-  // Clip by a large bounding box so they are same size
-  // Unite them all together
-  // Remove FACEs that don't overlap original FACEs
-  // Make sure FACE normals are consistent (we do this by healing)
-  // Remove any holes
-  // Remove unwanted topology (regularize)
-
-  // It is useful to heal and regularize the surfaces first.  The method we use
-  // has problems with spline surfaces - by healing we hopefully simplify the
-  // splines to analytics.
-  BODY *sheet_body;
-  if( copy_FACEs_into_sheet( FACE_list, sheet_body ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  // Get the new FACEs
-  DLIList<FACE*> new_FACE_list;
-  AQE->get_FACEs( sheet_body, new_FACE_list );
-
-  int i;
-  FACE *FACE_ptr;
-  FACE *new_FACE_ptr;
-  BODY *BODY_ptr;
-  DLIList<BODY*> ext_BODY_list;
-  new_FACE_list.reset();
-  for( i=new_FACE_list.size(); i--; )
-  {
-    FACE_ptr = new_FACE_list.get_and_step();
-
-    // Do not extend if entirely enclosed by the other surfaces
-    CubitBoolean extend = FACE_surrounded( FACE_ptr, new_FACE_list )
-      ? CUBIT_FALSE : CUBIT_TRUE;
-
-    new_FACE_ptr = AME->make_FACE( FACE_ptr, extend );
-    if( new_FACE_ptr == NULL )
-    {
-      PRINT_ERROR( "Problem extending surface - aborting\n" );
-      api_delent( sheet_body );
-      while( ext_BODY_list.size() )
-        api_delent( ext_BODY_list.pop() );
-      return CUBIT_FAILURE;
-    }
-    // Get the BODY this new FACE is in
-    BODY_ptr = AQE->get_BODY_of_ENTITY( new_FACE_ptr );
-    if( BODY_ptr == NULL )
-    {
-      PRINT_ERROR( "Problem extending surface - aborting\n" );
-      api_delent( sheet_body );
-      while( ext_BODY_list.size() )
-        api_delent( ext_BODY_list.pop() );
-      return CUBIT_FAILURE;
-    }
-
-    ext_BODY_list.append( BODY_ptr );
-  }
-
-  // We are done with the sheet_body
-  api_delent( sheet_body );
-
-  // Unite all of the extended BODIES together
-  outcome result;
-  DLIList<BODY*> BODY_list;
-  ext_BODY_list.reset();
-  BODY *master = ext_BODY_list.extract();
-  for( i=ext_BODY_list.size(); i--; )
-  {
-    BODY_ptr = ext_BODY_list.extract();
-
-    // Do the union of the master and the BODY_ptr.
-    // If this is successful, the result is master and
-    //   BODY_ptr will be deleted
-    result = api_boolean( BODY_ptr, master, UNION );
-    if( !result.ok() || (!master) )
-    {
-      AQE->ACIS_API_error(result);
-      while( ext_BODY_list.size() )
-        api_delent( ext_BODY_list.pop() );
-      if (master != NULL) api_delent(master);
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Cut by a bounding box, so all entities are the same extents.  Otherwise,
-  // cylinders won't be handled correctly (they may remain full cylinders
-  // which is undesireable).
-  CubitBox box = GeometryQueryTool::instance()->model_bounding_box();
-
-  // Check the box for zero dimensions, which can definitely occur if we are
-  // working with 2D sheet bodies.  If those exist, add a factor in that
-  // direction.  Here we pick 0.25 since when we thicken bodies we do it by
-  // 0.2 - thus this should be safe to overlap those thickened bodies
-  // completely.
-  CubitVector box_min = box.minimum();
-  CubitVector box_max = box.maximum();
-
-  double f = .25;
-
-  if( box_max.x() - box_min.x() < 1e-6 )
-  {
-    box_min.set( box_min.x()-f, box_min.y(), box_min.z() );
-    box_max.set( box_max.x()+f, box_min.y(), box_min.z() );
-  }
-  if( box_max.y() - box_min.y() < 1e-6 )
-  {
-    box_min.set( box_min.x(), box_min.y()-f, box_min.z() );
-    box_max.set( box_max.x(), box_max.y()+f, box_max.z() );
-  }
-  if( box_max.z() - box_min.z() < 1e-6 )
-  {
-    box_min.set( box_min.x(), box_min.y(), box_min.z()-f );
-    box_max.set( box_max.x(), box_max.y(), box_max.z()+f );
-  }
-
-  CubitBox temp_box( box_min, box_max );
-  box |= temp_box;
-
-  // Scale the box up overall by a factor as well
-  box *= 1.25;
-
-  // Create sheet bodies (6) at box sides
-  CubitVector c[8];
-  box.get_corners( c );
-
-  //     3+----------+2
-  //     /|         /|
-  //    / |        / |
-  //   /  |       /  |      Y
-  // 7+----------+6  |      ^
-  //  |   |      |   |      |
-  //  |  0+------|---+1     |
-  //  |  /       |  /       +---->X
-  //  | /        | /       /
-  //  |/         |/       /
-  // 4+----------+5      Z
-
-  SPAposition min( box.minimum().x(), box.minimum().y(), box.minimum().z() );
-  SPAposition max( box.maximum().x(), box.maximum().y(), box.maximum().z() );
-  SPAbox super_box( min, max );
-
-  // Note - infinite plane is swept in the opposite direction from the normal
-  // of the passed in points
-  // Create infinite plane object at the FRONT of the box
-  BODY_ptr = AME->create_infinite_plane_cutting_tool( c[6], c[5],
-    c[4], super_box, false );
-  // Subtract this object from the master (BODY_ptr is deleted)
-  result = api_boolean( BODY_ptr, master, SUBTRACTION );
-  // Do this for the other 5 sides of the box
-  // RIGHT SIDE
-  BODY_ptr = AME->create_infinite_plane_cutting_tool( c[6], c[2],
-    c[1], super_box, false );
-  result = api_boolean( BODY_ptr, master, SUBTRACTION );
-  // BACK SIDE
-  BODY_ptr = AME->create_infinite_plane_cutting_tool( c[1], c[2],
-    c[3], super_box, false );
-  result = api_boolean( BODY_ptr, master, SUBTRACTION );
-  // LEFT SIDE
-  BODY_ptr = AME->create_infinite_plane_cutting_tool( c[0], c[3],
-    c[7], super_box, false );
-  result = api_boolean( BODY_ptr, master, SUBTRACTION );
-  // BOTTOM
-  BODY_ptr = AME->create_infinite_plane_cutting_tool( c[0], c[4],
-    c[5], super_box, false );
-  result = api_boolean( BODY_ptr, master, SUBTRACTION );
-  // TOP
-  BODY_ptr = AME->create_infinite_plane_cutting_tool( c[3], c[2],
-    c[6], super_box, false );
-  result = api_boolean( BODY_ptr, master, SUBTRACTION );
-
-  // Put original FACEs into a single sheet BODY
-  BODY *orig_sheet;
-  if( copy_FACEs_into_sheet( FACE_list, orig_sheet )
-    == CUBIT_FAILURE )
-  {
-    api_delent( master );
-    return CUBIT_FAILURE;
-  }
-
-  // Remove FACEs that don't overlap with the original target FACEs
-  double overlap_area;
-  DLIList<FACE*> master_FACE_list;
-  AQE->get_FACEs( master, master_FACE_list );
-  master_FACE_list.reset();
-  for( i=master_FACE_list.size(); i--; )
-  {
-    FACE_ptr = master_FACE_list.get_and_step();
-
-    // Make a copy of the FACE into a new BODY
-    FACE *temp_FACE_ptr = AME->make_FACE( FACE_ptr, CUBIT_FALSE );
-    if( temp_FACE_ptr == NULL )
-    {
-      api_delent( master );
-      return CUBIT_FAILURE;
-    }
-    BODY *temp_BODY_ptr = AQE->get_BODY_of_ENTITY( temp_FACE_ptr );
-
-    if( get_overlap_area( temp_BODY_ptr, orig_sheet, overlap_area )
-      == CUBIT_FAILURE )
-    {
-      api_delent( temp_BODY_ptr );
-      api_delent( master );
-      return CUBIT_FAILURE;
-    }
-
-    api_delent( temp_BODY_ptr );
-
-    if( overlap_area > 1e-5 )
-      continue;
-    else
-      api_remove_face( FACE_ptr );
-  }
-
-  // Remove any internal holes in the body
-  remove_holes( master );
-
-  // Clean (regularize) to remove unwanted topology
-  api_clean_entity( master );
-
-  // Make sure FACE normals are consistent (api_body_to_1d could be used for
-  // this, then convert back to double sided).  Healing will also work.
-  // Ignore return status as this is not fatal.
-  heal_BODY( master );
-
-  // Set output BODY
-  ext_BODY_ptr = master;
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : prep_cutting_sheet
-// Member Type: PRIVATE
-// Description: Prepare the cutting sheet for chopping off the BODY in a 
-//              tweak_target_multiple operation.
-// Author     : Steve Storm
-// Date       : 3/18/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::prep_cutting_sheet( BODY *&cutting_sheet,
-                                   BODY *tweaked_BODY_ptr,
-                                   BODY *ext_target_BODY_ptr,
-                                   CubitVector &source_norm,
-                                   CubitVector &target_norm,
-                                   CubitBoolean check_crossing )
-{
-  int i, j;
-  outcome result;
-
-  // Imprint, so as to score the cutting sheet.  We have to do this with a
-  // copied BODY, since the extended target could cross FACEs we don't want
-  // to affect.
-  BODY *tweaked_BODY_ptr2 = AME->copy_BODY( tweaked_BODY_ptr, CUBIT_TRUE );
-  result = api_imprint( cutting_sheet, tweaked_BODY_ptr2 );
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error(result);
-    api_delent( tweaked_BODY_ptr2 );
-    return CUBIT_FAILURE;
-  }
-  api_delent( tweaked_BODY_ptr2 );
-
-  if( check_crossing == CUBIT_TRUE )
-  {
-    // Throw away individual cutting sheet patches that don't cross the FACEs we
-    // want to cut.
-    DLIList<FACE*> cut_FACE_list;
-    DLIList<FACE*> temp_FACE_list;
-    AQE->get_FACEs( tweaked_BODY_ptr, temp_FACE_list );
-    FACE *FACE_ptr;
-    ATTRIB_GEN_NAME *ret_att;
-    for( i=temp_FACE_list.size(); i--; )
-    {
-      FACE_ptr = temp_FACE_list.get_and_step();
-      api_find_named_attribute( FACE_ptr, "tweak", ret_att );
-      if( ret_att )
-        cut_FACE_list.append( FACE_ptr );
-    }
-    BODY *cut_FACE_sheet;
-    // Note: healing a .2 thick sheet here will collapse the side FACEs out,
-    // so we skip healing.
-    copy_FACEs_into_sheet( cut_FACE_list, cut_FACE_sheet, CUBIT_FALSE );
-
-    // Intersect this sheet with each cutting sheet. NULL or incomplete wires
-    // will indicate an invalid crossing.
-    BODY **sheets = NULL;
-    int n_body = 0;
-    result = api_separate_body( cutting_sheet, n_body, sheets );
-    if (!result.ok())
-    {
-      AQE->ACIS_API_error(result);
-      api_delent( cut_FACE_sheet );
-      return CUBIT_FAILURE;
-    }
-
-    CubitBoolean good_crossing = CUBIT_FALSE;
-    for( i=0; i<n_body; i++ )
-    {
-      BODY* slice = NULL;
-
-      // Create the intersection graph between the given bodies
-      result = api_slice( sheets[i], cut_FACE_sheet,
-        *(SPAunit_vector *)NULL_REF, slice);
-
-      if (!result.ok() || slice == NULL )
-        good_crossing = CUBIT_FALSE;
-      else
-      {
-        api_clean_wire( slice );
-        int num = 0;
-        BODY **wires = NULL;
-        result = api_separate_body( slice, num, wires );
-        if (!result.ok())
-        {
-          AQE->ACIS_API_error(result);
-          api_delent( slice );
-          for( j=0; j<n_body; j++ )
-            if( sheets[j] ) api_delent(sheets[j]);
-          api_delent( cut_FACE_sheet );
-          return CUBIT_FAILURE;
-        }
-        if( num == 1 )
-          good_crossing = CUBIT_TRUE;
-        else
-          good_crossing = CUBIT_FALSE;
-
-        for( j=0; j<num; j++ )
-          api_delent( wires[j] );
-      }
-
-      if( good_crossing == CUBIT_FALSE )
-      {
-        // Delete this BODY
-        api_delent( sheets[i] );
-        sheets[i] = NULL;
-      }
-    }
-
-    // Delete the cut_FACE_sheet since we are done with it
-    api_delent( cut_FACE_sheet );
-
-    // Unite the remaining sheets back into cutting_sheet
-    BODY *first_BODY_ptr = NULL;
-    DLIList<BODY*> unite_BODY_list;
-    for( i=0; i<n_body; i++ )
-    {
-      if( sheets[i] )
-      {
-        if( !first_BODY_ptr )
-          first_BODY_ptr = sheets[i];
-        else
-          unite_BODY_list.append( sheets[i] );
-      }
-    }
-    if( !first_BODY_ptr )
-    {
-      PRINT_ERROR( "Problem intersecting extended surface(s) with target\n" );
-      return CUBIT_FAILURE;
-    }
-    if( unite_BODIES( first_BODY_ptr, unite_BODY_list, cutting_sheet )
-      == CUBIT_FAILURE )
-    {
-      for( i=0; i<n_body; i++ )
-        if( sheets[i] ) api_delent( sheets[i] );
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Remove periodic surfaces near nonmanifold EDGEs. Note if any remaining
-  // nonmanifold EDGEs exist, this function will return failure (a nonmanifold
-  // surface won't work as a cutting sheet).  See picture in the function
-  // for an example.
-  if( remove_per_nonmanifold_FACEs( cutting_sheet ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
-
-  // We need to check the normals on the cutting_sheet now against the normals
-  // on the ext_target_BODY_ptr, since we can't be sure what the intersection
-  // did with the normals.  Unfortunately, we can't use the
-  // make_surf_normals_consistent function because we might have disconnected
-  // FACEs that are part of the back side of cylinders in the cutting_sheet.
-  // If we were to use make_surf_normals_consistent it would align those FACEs
-  // normals with the front FACE, and the cutting sheet would be invalid,
-  // because the remove_aligned_periodic_FACEs will fail to remove those FACEs.
-  // We use a computationally intense method instead.
-  if( align_normals( cutting_sheet, ext_target_BODY_ptr ) == CUBIT_FAILURE )
-  {
-    PRINT_ERROR( "Unable to make target shell normals consistent - invalid target\n" );
-    return CUBIT_FAILURE;
-  }
-
-  // Now remove unwanted periodic FACEs on the back of the cutting sheet.  We
-  // use the target normal as the basis.  Since we worked very hard to keep the
-  // normals consisent in relation to the target surfaces the user picked, this
-  // will be fairly robust for most cases.
-  CubitVector tmp_vec = -target_norm;
-  remove_aligned_periodic_FACEs( cutting_sheet, tmp_vec );
-
-  // Make sure there are still some FACEs left!
-  DLIList<FACE*> cutting_sheet_FACE_list;
-  AQE->get_FACEs( cutting_sheet, cutting_sheet_FACE_list );
-  if( cutting_sheet_FACE_list.size() == 0 )
-  {
-    PRINT_ERROR( "Unable to tweak to targets\n" );
-    return CUBIT_FAILURE;
-  }
-
-  // Clean the cutting sheet before using it - remove unnecessary topology -
-  // this makes booleans more robust.  Ignore result since not fatal.
-  result = api_clean_entity( cutting_sheet );
-
-  // Also remove any internal holes
-  remove_holes( cutting_sheet );
-
-  // Sheet direction should ALWAYS be pointing in the opposite direction as the
-  // source_norm
-  cutting_sheet_FACE_list.clean_out();
-  AQE->get_FACEs( cutting_sheet, cutting_sheet_FACE_list );
-  CubitVector sheet_norm = weighted_average_FACE_normal( cutting_sheet_FACE_list );
-  if( sheet_norm.length() < 1e-12 )
-  {
-    PRINT_ERROR( "Unable to tweak to given surfaces\n" );
-    return CUBIT_FAILURE;
-  }
-  if( sheet_norm % source_norm > 0.0 )
-    api_reverse_body( cutting_sheet );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : chop_off_with_sheet
-// Member Type: PRIVATE
-// Description: Chop off all the material in a BODY to one side of a sheet
-//              body.  The material is removed on the side of the sheet body
-//              according to the surface normals of the sheet body (material
-//              removed in the opposite direction of the surface normals of the
-//              sheet body, which must be consistent).
-// Author     : Steve Storm
-// Date       : 1/29/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::chop_off_with_sheet( BODY *BODY_ptr, BODY *sheet_BODY_ptr )
-{
-  outcome result;
-
-  // First test to see if these intersect.  If they don't nothing will be done.
-  if ( !AME->BODYs_interfering( BODY_ptr, sheet_BODY_ptr ) )
-  {
-    // BODIES don't intersect.  Clean up and exit.
-    PRINT_WARNING("Cutting sheet does not intersect the original volume.\n");
-    return CUBIT_FAILURE;
-  }
-
-  BODY *copied_sheet_BODY = AME->copy_BODY( sheet_BODY_ptr );
-
-  // Set all faces to one sided
-  result = api_body_to_1d( copied_sheet_BODY, false );
-  if( !result.ok() )
-  {
-    api_delent( copied_sheet_BODY );
-    AQE->ACIS_API_error( result );
-    return CUBIT_FAILURE;
-  }
-
-  // Setup tweak attributes so we can preserve Cubit owners
-  DLIList<FACE*> pre_FACE_list;
-  DLIList<EDGE*> pre_EDGE_list;
-  DLIList<VERTEX*> pre_VERTEX_list;
-  DLIList<AcisBridge*> ab_FACE_list, ab_EDGE_list, ab_VERTEX_list;
-  assign_tweak_attribs( BODY_ptr, "tweak_own", pre_FACE_list, ab_FACE_list,
-    pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list, ab_VERTEX_list );
-
-  // Now we simply have to subtract the copied_sheet_BODY from BODY_ptr
-  result = api_boolean( copied_sheet_BODY, BODY_ptr, NONREG_SUBTRACTION );
-
-  // Replace Cubit owners
-  reassign_cubit_owners_from_tweak_attribs( BODY_ptr, "tweak_own",
-    pre_FACE_list, ab_FACE_list, pre_EDGE_list, ab_EDGE_list, pre_VERTEX_list,
-    ab_VERTEX_list );
-
-  // Remove tweak attributes
-  remove_named_attribs( BODY_ptr, "tweak_own" );
-
-  if( !result.ok() || BODY_ptr->lump() == NULL ||
-      !is_closed_solid_body( BODY_ptr ) )
-  {
-    CubitBoolean is_error = CUBIT_TRUE;
-    if( result.ok() &&
-      ( BODY_ptr->lump() == NULL ||
-      !is_closed_solid_body( BODY_ptr )))
-    {
-      // This is where the sheet just intersects with the shell
-      // of the outside body.  Should do nothing here.
-      is_error = CUBIT_FALSE;
-    }
-    if( !result.ok() )  //was already deleted if api_subtract was successfull
-      api_delent( copied_sheet_BODY );
-
-    if ( is_error )
-    {
-      if( !result.ok() )
-        AQE->ACIS_API_error( result );
-      else
-        PRINT_ERROR( "problem trimming body\n" );
-    }
-    else
-    {
-      // Cutting surfaces graze volume
-      PRINT_ERROR( "problem trimming body\n" );
-    }
-    return CUBIT_FAILURE;
-  }
-
-  AQE->clear_bounding_box( BODY_ptr );
-  AQE->bounding_box( BODY_ptr );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : get_overlap_area
-// Member Type: PRIVATE
-// Description: Determine the area of overlap of two BODIES.  Uses an ACIS
-//              intersection boolean so is quite expensive.
-// Author     : Steve Storm
-// Date       : 2/10/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::get_overlap_area( BODY *BODY_ptr1, BODY *BODY_ptr2,
-                                 double &overlap_area, double accuracy )
-{
-  overlap_area = 0.0;
-
-  BODY *int_sheet;
-  outcome result = api_boolean( BODY_ptr1, BODY_ptr2, INTERSECTION,
-    NDBOOL_KEEP_BOTH, int_sheet );
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-
-  // Get surface area of int_sheet
-  double accur_achieved;
-  result = api_ent_area( int_sheet, accuracy, overlap_area, accur_achieved );
-  api_delent( int_sheet );
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error(result);
-    return CUBIT_FAILURE;
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : copy_FACEs_into_sheet
-// Member Type: PRIVATE
-// Description: Copies the given FACEs
-// Author     : Steve Storm
-// Date       : 2/10/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::copy_FACEs_into_sheet( DLIList<FACE*> &FACE_list,
-                                      BODY *&sheet_ptr,
-                                      CubitBoolean heal )
-{
-  DLIList<BODY*> temp_BODY_list;
-  FACE *FACE_ptr;
-  FACE *temp_FACE_ptr;
-  BODY *temp_BODY_ptr;
-  int i;
-  FACE_list.reset();
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-
-    temp_FACE_ptr = AME->make_FACE( FACE_ptr, CUBIT_FALSE );
-    if( temp_FACE_ptr == NULL )
-    {
-      while( temp_BODY_list.size() ) api_delent( temp_BODY_list.pop() );
-      return CUBIT_FAILURE;
-    }
-
-    // Get the BODY this new FACE is in
-    temp_BODY_ptr = AQE->get_BODY_of_ENTITY( temp_FACE_ptr );
-    if( temp_BODY_ptr == NULL )
-    {
-      while( temp_BODY_list.size() ) api_delent( temp_BODY_list.pop() );
-      return CUBIT_FAILURE;
-    }
-
-    temp_BODY_list.append( temp_BODY_ptr );
-  }
-
-  // Unite all of the temp BODIES together
-  temp_BODY_list.reset();
-  outcome result;
-  BODY *master = temp_BODY_list.extract();
-  for( i=temp_BODY_list.size(); i--; )
-  {
-    temp_BODY_ptr = temp_BODY_list.extract();
-
-    // Do the union of the master and the BODY_ptr.
-    // If this is successful, the result is master and
-    //   temp_BODY_ptr will be deleted
-    result = api_boolean( temp_BODY_ptr, master, UNION );
-    if( !result.ok() || (!master) )
-    {
-      AQE->ACIS_API_error(result);
-      api_delent( temp_BODY_ptr );
-      while( temp_BODY_list.size() ) api_delent( temp_BODY_list.pop() );
-      if (master != NULL) api_delent(master);
-      return CUBIT_FAILURE;
-    }
-  }
-
-  // Heal the BODY if required
-  if( heal )
-    heal_BODY( master );
-
-  // Clean (regularize) to remove unwanted topology
-  api_clean_entity( master );
-
-  sheet_ptr = master;
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : remove_per_nonmanifold_FACEs
-// Member Type: PRIVATE
-// Description: Removes cone, sphere or torus FACEs that are attached to a
-//              nonmanifold EDGE.  The portion of the periodic that is tangent
-//              to the attached FACE is kept.
-// Author     : Steve Storm
-// Date       : 2/2/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::remove_per_nonmanifold_FACEs( BODY *cutting_tool )
-{
-  outcome result;
-
-  // List to store FACEs to remove
-  DLIList<FACE*> remove_FACE_list;
-
-  // Find nonmanifold edges, remove attached periodic surface on side we
-  // don't want to keep.  We for sure want to remove these faces.
-  //
-  // Example: Diagram is an end view of a full cylinder with a plane attached.
-  // The nonmanifold EDGE is on the right side.  In this example we would
-  // remove the short portion of the cylinder between the periods.
-  //     _____
-  //   /       \
-  //  /         \
-  // |           |
-  // |           . <-- nonmanifold EDGE (runs along cylinder length here)
-  // |           |
-  //  \         /|
-  //   \ __.__ / |
-  //             |
-  //             |
-  //             |
-  //             |
-
-  // Loop through EDGEs
-  DLIList<EDGE*> EDGE_list;
-  AQE->get_EDGEs( cutting_tool, EDGE_list );
-
-  int i, j;
-  EDGE *EDGE_ptr;
-  EDGE_list.reset();
-  for( i=EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-
-    DLIList<FACE*> FACE_list;
-    AQE->get_FACEs( EDGE_ptr, FACE_list );
-
-    if( FACE_list.size() < 3 )
-      continue;
-
-    // EDGE is nonmanifold - it has 3 FACEs attached to it.  If two of the
-    // FACEs are periodic types and one is not, then we will mark one of the
-    // periodic types for deletion.
-
-    // We can't handle this case
-    if( FACE_list.size() > 3 )
-    {
-      PRINT_ERROR( "Ill-formed extended target encountered\n" );
-      return CUBIT_FAILURE;
-    }
-
-    // Find the attached periodic surfaces
-    FACE *per_FACE_ptr1 = NULL;
-    FACE *per_FACE_ptr2 = NULL;
-    FACE *other_FACE_ptr = NULL;
-    FACE_list.reset();
-    for( j=FACE_list.size(); j--; )
-    {
-      FACE *FACE_ptr = FACE_list.get_and_step();
-      SURFACE *SURFACE_ptr = FACE_ptr->geometry();
-      int type = SURFACE_ptr->identity();
-      if( type==CONE_TYPE || type==SPHERE_TYPE || type== TORUS_TYPE )
-      {
-        if( per_FACE_ptr1 == NULL ){
-          per_FACE_ptr1 = FACE_ptr;
-          continue;
-        }
-
-        if( per_FACE_ptr2 == NULL )
-        {
-          per_FACE_ptr2 = FACE_ptr;
-          continue;
-        }
-
-        if( per_FACE_ptr1 && per_FACE_ptr2 )
-        {
-          PRINT_ERROR( "Ill-formed extended target encountered\n" );
-          return CUBIT_FAILURE;
-        }
-      }
-      else if( other_FACE_ptr == NULL )
-        other_FACE_ptr = FACE_ptr;
-    }
-
-    if( !(per_FACE_ptr1 && per_FACE_ptr2 && other_FACE_ptr) )
-    {
-      PRINT_ERROR( "Ill-formed extended target encountered\n" );
-      return CUBIT_FAILURE;
-    }
-
-    // Figure out which periodic to remove.  Compare vectors tangent to and
-    // pointing away from the FACEs at the middle of the EDGE.
-
-    // Get mid position
-    SPAposition acis_mid_pnt = EDGE_ptr->mid_pos();
-    CubitVector mid_pnt( acis_mid_pnt.x(), acis_mid_pnt.y(), acis_mid_pnt.z() );
-
-    CubitVector vec1, vec2, vec3;
-    tangent_outdir( per_FACE_ptr1, EDGE_ptr, mid_pnt, vec1 );
-    tangent_outdir( per_FACE_ptr2, EDGE_ptr, mid_pnt, vec2 );
-    tangent_outdir( other_FACE_ptr, EDGE_ptr, mid_pnt, vec3 );
-
-    // FACE that is in same direction as other_FACE gets removed.  If angle
-    // between vectors is acute (dot product > 0) flag that FACE
-    if( vec1 % vec3 > 0.0 )
-      remove_FACE_list.append_unique( per_FACE_ptr1 );
-    else if( vec2 % vec3 > 0.0 )
-      remove_FACE_list.append_unique( per_FACE_ptr2 );
-  }
-
-  // Remove these FACEs
-  for( i=remove_FACE_list.size(); i--; )
-    api_remove_face( remove_FACE_list.get_and_step() );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tangent_outdir
-// Member Type: PRIVATE
-// Description: Given a FACE, EDGE and position, find the direction that is
-//              normal to the EDGE and tangent to the FACE, pointing away from
-//              the FACE boundary.
-// Author     : Steve Storm
-// Date       : 2/18/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::tangent_outdir( FACE *FACE_ptr, EDGE *EDGE_ptr,
-                               CubitVector &pos, CubitVector &tangent_outvec )
-{
-  // Get the normal to the FACE at the position
-  SPAposition acis_pos( pos.x(), pos.y(), pos.z() );
-  SPAposition acis_pos_on_surf;
-  SPAunit_vector acis_face_norm;
-  (FACE_ptr->geometry()->equation()).point_perp( acis_pos,
-    acis_pos_on_surf, acis_face_norm );
-
-  // Adjust for the FACE sense
-  if( FACE_ptr->sense() == REVERSED )
-    acis_face_norm = -acis_face_norm;
-
-  // Get a vector tangent to the EDGE, adjusted for the EDGE sense on the FACE
-  SPAunit_vector acis_tangent_vec = (EDGE_ptr->geometry()->equation()).
-    point_direction( acis_pos );
-  if( EDGE_ptr->sense() == REVERSED )
-    acis_tangent_vec = -acis_tangent_vec;
-
-  COEDGE *COEDGE_ptr = EDGE_ptr->coedge( FACE_ptr );
-  if( COEDGE_ptr->sense() == REVERSED )
-    acis_tangent_vec = -acis_tangent_vec;
-
-  // Cross edge tangent with face normal to find desired direction
-  CubitVector face_norm( acis_face_norm.x(), acis_face_norm.y(),
-    acis_face_norm.z() );
-  CubitVector tangent_vec( acis_tangent_vec.x(), acis_tangent_vec.y(),
-    acis_tangent_vec.z() );
-
-  tangent_outvec = tangent_vec * face_norm;
-
-  tangent_outvec.normalize();
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : remove_aligned_periodic_FACEs
-// Member Type: PRIVATE
-// Description: Removes cone, sphere or torus FACEs that have normals aligned
-//              with the given basis vector.
-// Author     : Steve Storm
-// Date       : 2/2/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::remove_aligned_periodic_FACEs( BODY *cutting_tool,
-                                              CubitVector &basis_vec )
-{
-  outcome result;
-  int i;
-  CubitVector location;
-  DLIList<FACE*> FACE_list;
-  AQE->get_FACEs( cutting_tool, FACE_list );
-  FACE_list.reset();
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE *FACE_ptr = FACE_list.get_and_step();
-
-    SURFACE *SURFACE_ptr = FACE_ptr->geometry();
-    int type = SURFACE_ptr->identity();
-    if( type==CONE_TYPE || type==SPHERE_TYPE || type== TORUS_TYPE )
-    {
-      CubitVector FACE_norm = FACE_normal( FACE_ptr, location );
-
-      // If dot product greater than zero, angle is acute
-      if( FACE_norm % basis_vec > 0.0 )
-      {
-        result = api_remove_face( FACE_ptr );
-        if( !result.ok() )
-        {
-          AQE->ACIS_API_error( result );
-          return CUBIT_FAILURE;
-        }
-      }
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : heal_BODY
-// Member Type: PRIVATE
-// Description: Convenience function to use the ACIS healer to heal a BODY
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::heal_BODY( BODY *BODY_ptr )
-{
-  outcome result;
-  result = api_hh_init_body_for_healing( BODY_ptr );
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error( result );
-    return CUBIT_FAILURE;
-  }
-
-  result = api_hh_auto_heal( BODY_ptr );
-  if( !result.ok() )
-  {
-    AQE->ACIS_API_error( result );
-    api_hh_end_body_for_healing( BODY_ptr );
-    return CUBIT_FAILURE;
-  }
-
-  api_hh_end_body_for_healing( BODY_ptr );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : align_normals
-// Member Type: PRIVATE
-// Description: Align the normals of the child's FACEs to the master FACEs.  It
-//              is assumed the child is a subset of the master (i.e., the
-//              master is an extended BODY).
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::align_normals( BODY *child, BODY *master )
-{
-  DLIList<FACE*> child_FACE_list;
-  AQE->get_FACEs( child, child_FACE_list );
-
-  DLIList<FACE*> master_FACE_list;
-  AQE->get_FACEs( master, master_FACE_list );
-
-  int i;
-  CubitVector loc;
-  FACE *child_FACE_ptr = NULL;
-  for( i=child_FACE_list.size(); i--; )
-  {
-    child_FACE_ptr = child_FACE_list.get_and_step();
-
-    CubitVector child_norm = FACE_normal( child_FACE_ptr, loc );
-
-    FACE *master_FACE_ptr = find_overlap_FACE( child_FACE_ptr, master_FACE_list );
-
-    if( !master_FACE_ptr )
-      return CUBIT_FAILURE;
-
-    // Align the normals
-    CubitVector master_norm = FACE_normal( master_FACE_ptr, loc, CUBIT_FALSE );
-    if( child_norm % master_norm < 0.0 )
-      api_reverse_face( child_FACE_ptr );
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : find_overlap_FACE
-// Member Type: PRIVATE
-// Description: Find the FACE in FACE_list that overlaps with FACE_ptr.
-//              Returns NULL if no overlap FACE found.
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-FACE *
-AcisTweakTool::find_overlap_FACE( FACE *FACE_ptr, DLIList<FACE*> &FACE_list )
-{
-  int i;
-  BODY *tmp_BODY_ptr1;
-  FACE *face_list[1];
-  face_list[0] = FACE_ptr;
-  api_sheet_from_ff( 1, face_list, tmp_BODY_ptr1 );
-  api_body_to_2d( tmp_BODY_ptr1 );
-
-  FACE *FACE_ptr2;
-  FACE *match_FACE_ptr = NULL;
-  double overlap_area;
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr2 = FACE_list.get_and_step();
-    if( !FACE_ptr2 )
-      continue;
-    BODY *tmp_BODY_ptr2;
-    face_list[0] = FACE_ptr2;
-    api_sheet_from_ff( 1, face_list, tmp_BODY_ptr2 );
-    api_body_to_2d( tmp_BODY_ptr2 );
-    get_overlap_area( tmp_BODY_ptr1, tmp_BODY_ptr2, overlap_area );
-    api_delent( tmp_BODY_ptr2 );
-    if( overlap_area > 1e-5 )
-    {
-      match_FACE_ptr = FACE_ptr2;
-      break;
-    }
-  }
-
-  api_delent( tmp_BODY_ptr1 );
-
-  return match_FACE_ptr;
-}
-
-//=============================================================================
-// Function   : make_surf_normals_consistent
-// Member Type: PRIVATE
-// Description: Make the surface normals in the given sheet BODY consistent.
-//              The optional seed FACE must be part of the BODY.  If none is
-//              given, a random FACE is selected.
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::make_surf_normals_consistent( BODY *BODY_ptr,
-                                             FACE *seed_FACE_ptr )
-{
-  int i;
-  DLIList<FACE*> patch_list;
-  DLIList<FACE*> FACE_list;
-  AQE->get_FACEs( BODY_ptr, FACE_list );
-
-  if( seed_FACE_ptr == NULL )
-    seed_FACE_ptr = get_seed_FACE( FACE_list );
-
-  api_add_generic_named_attribute( seed_FACE_ptr, "tweak_seed", 1, SplitCopy );
-  patch_list.append( seed_FACE_ptr );
-
-  int c = 0;
-
-  while( patch_list.size() < FACE_list.size() )
-  {
-    // Find all neighbors.  Note patch_list will change size within the loop.
-    for( i=c; i<patch_list.size(); i++ )
-    {
-      if( append_neighbors( patch_list ) == CUBIT_FAILURE )
-      {
-        remove_named_attribs( BODY_ptr, "tweak_seed" );
-        return CUBIT_FAILURE;
-      }
-
-      patch_list.step();
-    }
-
-    // Include disconnected FACE patches
-    if( patch_list.size() < FACE_list.size() )
-    {
-      c = patch_list.size();
-      ATTRIB_GEN_NAME *ret_att;
-      FACE *FACE_ptr;
-      DLIList<FACE*> processed_FACE_list;
-
-      FACE_list.reset();
-      for( i=FACE_list.size(); i--; )
-      {
-        FACE_ptr = FACE_list.get_and_step();
-
-        api_find_named_attribute( FACE_ptr, "tweak_seed", ret_att );
-        if( ret_att )
-          processed_FACE_list.append( FACE_ptr );
-      }
-
-      CubitVector avg_norm = weighted_average_FACE_normal( processed_FACE_list );
-
-      seed_FACE_ptr = get_seed_FACE( FACE_list );
-      api_add_generic_named_attribute( seed_FACE_ptr, "tweak_seed", 1, SplitCopy );
-      patch_list.append( seed_FACE_ptr );
-
-      CubitVector loc;
-      CubitVector seed_norm = FACE_normal( seed_FACE_ptr, loc );
-
-      if( seed_norm % avg_norm < 0.0 )
-        api_reverse_face( seed_FACE_ptr );
-    }
-  }
-
-  remove_named_attribs( BODY_ptr, "tweak_seed" );
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : append_neighbors
-// Member Type: PRIVATE
-// Description: Helper function for make_surf_normals_consistent
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::append_neighbors( DLIList<FACE*> &FACE_list )
-{
-  int i, j;
-  ATTRIB_GEN_NAME *ret_att;
-
-  FACE *seed_FACE_ptr = FACE_list.get();
-
-  // Get the edges
-  DLIList<EDGE*> EDGE_list;
-  AQE->get_EDGEs( seed_FACE_ptr, EDGE_list );
-
-  EDGE *EDGE_ptr;
-  FACE *FACE_ptr;
-  COEDGE *seed_COEDGE_ptr;
-  for( i=0; i<EDGE_list.size(); i++ )
-  {
-    EDGE_ptr = EDGE_list.get_and_step();
-
-    seed_COEDGE_ptr = EDGE_ptr->coedge( seed_FACE_ptr );
-
-    ENTITY_LIST COEDGES;
-    api_get_coedges( EDGE_ptr, COEDGES );
-    DLIList<COEDGE*> COEDGE_list;
-    ENTITY *ENTITY_ptr;
-    COEDGES.init();
-    while( (ENTITY_ptr = COEDGES.next() ) != NULL )
-      COEDGE_list.append( (COEDGE *)ENTITY_ptr );
-    COEDGES.clear();
-
-    if( COEDGE_list.size() == 1 )
-      continue;
-    if( COEDGE_list.size() == 2 )
-    {
-      // Normal case
-      COEDGE *COEDGE_ptr2 = COEDGE_list.get_and_step();
-      if( COEDGE_ptr2 == seed_COEDGE_ptr )
-        COEDGE_ptr2 = COEDGE_list.get();
-
-      DLIList<FACE*> temp_FACE_list;
-      AQE->get_FACEs( COEDGE_ptr2, temp_FACE_list );
-      if( temp_FACE_list.size() > 1 )
-      {
-        PRINT_ERROR( "Found more than one FACE attached to a COEDGE\n" );
-        return CUBIT_FAILURE;
-      }
-      FACE_ptr = temp_FACE_list.get();
-
-      // Don't consider FACEs that are already in the list
-      api_find_named_attribute( FACE_ptr, "tweak_seed", ret_att );
-      if( ret_att )
-        continue;
-
-      // If the sense's are the same, the FACE needs to be reversed
-      if( seed_COEDGE_ptr->sense() == COEDGE_ptr2->sense() )
-        api_reverse_face( FACE_ptr );
-
-      FACE_list.append( FACE_ptr );
-      api_add_generic_named_attribute( FACE_ptr, "tweak_seed", 1, SplitCopy );
-    }
-    else if( COEDGE_list.size() == 3 )
-    {
-      // Nonmanifold.  Check for special case - periodic surface intersecting
-      // (usually tangent) another surface.  For now don't allow any other
-      // special cases.
-
-      // Find the attached periodic surfaces
-      FACE *FACE_ptr2 = NULL;
-      int num_per = 0;
-      DLIList<FACE*> attached_FACE_list;
-      AQE->get_FACEs( EDGE_ptr, attached_FACE_list );
-      attached_FACE_list.reset();
-      for( j=attached_FACE_list.size(); j--; )
-      {
-        FACE_ptr = attached_FACE_list.get_and_step();
-        SURFACE *SURFACE_ptr = FACE_ptr->geometry();
-        int type = SURFACE_ptr->identity();
-        if( type==CONE_TYPE || type==SPHERE_TYPE || type== TORUS_TYPE )
-          num_per++;
-
-        if( FACE_ptr == seed_FACE_ptr )
-          continue;
-
-        api_find_named_attribute( FACE_ptr, "tweak_seed", ret_att );
-        if( ret_att )
-          continue;
-
-        FACE_ptr2 = FACE_ptr;
-      }
-
-      if( FACE_ptr2 == NULL )
-        continue;
-      else if( attached_FACE_list.size() == 2 && num_per != 1 )
-      {
-        PRINT_ERROR( "Extended target cannot contain nonmanifold geometry\n" );
-        return CUBIT_FAILURE;
-      }
-      else if( attached_FACE_list.size() == 3 && num_per != 2 )
-      {
-        PRINT_ERROR( "Extended target cannot contain nonmanifold geometry\n" );
-        return CUBIT_FAILURE;
-      }
-
-      // Compare normal vectors at the mid position of the EDGE
-
-      // Get mid position
-      SPAposition acis_mid_pnt = EDGE_ptr->mid_pos();
-      CubitVector mid_pnt( acis_mid_pnt.x(), acis_mid_pnt.y(), acis_mid_pnt.z() );
-
-      CubitVector vec_seed, vec2;
-      vec_seed = FACE_normal( seed_FACE_ptr, mid_pnt, CUBIT_FALSE );
-      vec2 = FACE_normal( FACE_ptr2, mid_pnt, CUBIT_FALSE );
-
-      // Check angle between FACEs
-      if( vec_seed % vec2 < 0.0 )
-        api_reverse_face( FACE_ptr2 );
-
-      FACE_list.append( FACE_ptr2 );
-      api_add_generic_named_attribute( FACE_ptr2, "tweak_seed", 1, SplitCopy );
-    }
-    else if( COEDGE_list.size() > 3 )
-    {
-      PRINT_ERROR( "Extended target cannot contain nonmanifold geometry\n" );
-      return CUBIT_FAILURE;
-    }
-    else
-    {
-      PRINT_ERROR( "Targets appear to be ill-formed\n" );
-      return CUBIT_FAILURE;
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : get_seed_FACE
-// Member Type: PRIVATE
-// Description: Get a seed FACE from the given list of FACEs.  Only a seed FACE
-//              without a named "tweak_seed" attribute on it will be returned.
-//              Also, it may not be of advantage, but we try to find a FACE that
-//              is not of type CONE, TORUS or SPHERE.  If that is not possible,
-//              we just return the first FACE in the list with no "tweak_seed"
-//              attribute on it.
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-FACE *
-AcisTweakTool::get_seed_FACE( DLIList<FACE*> &FACE_list )
-{
-  int i;
-  FACE *seed_FACE_ptr = NULL;
-  ATTRIB_GEN_NAME *ret_att;
-
-  // Attempt to get a non-periodic seed FACE first
-  FACE *FACE_ptr;
-  FACE_list.reset();
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    SURFACE *SURFACE_ptr = FACE_ptr->geometry();
-    int type = SURFACE_ptr->identity();
-    if( type==CONE_TYPE || type==SPHERE_TYPE || type== TORUS_TYPE )
-      continue;
-
-    api_find_named_attribute( FACE_ptr, "tweak_seed", ret_att );
-
-    if( ret_att )
-      continue;
-
-    seed_FACE_ptr = FACE_ptr;
-    break;
-  }
-
-  if( seed_FACE_ptr == NULL )
-  {
-    FACE_list.reset();
-    for( i=FACE_list.size(); i--; )
-    {
-      FACE_ptr = FACE_list.get_and_step();
-
-      api_find_named_attribute( FACE_ptr, "tweak_seed", ret_att );
-
-      if( ret_att )
-        continue;
-
-      seed_FACE_ptr = FACE_ptr;
-      break;
-    }
-  }
-
-  return seed_FACE_ptr;
-}
-
-//=============================================================================
-// Function   : draw_tweak_preview_omt
-// Member Type: PRIVATE
-// Description: Draw the preview EDGEs for tweak offset, move and target.  The
-//              method is to draw:
-//              For sheet bodies:
-//              -----------------
-//               - EDGEs without owners and EDGEs attached to them
-//               - EDGEs attached to given (by owner attribute) EDGEs 
-//              For solids:
-//              -----------
-//               - EDGEs on FACEs without owners and EDGEs attached to them
-//               - EDGEs attached to given (by owner attribute) FACEs
-//                 
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::draw_tweak_preview_omt( BODY *BODY_ptr,
-                                       CubitBoolean flush,
-                                       DLIList<AcisBridge*> *ab_list )
-{
-  DLIList<FACE*> FACE_list;
-  AQE->get_FACEs( BODY_ptr, FACE_list );
-  if( !FACE_list.size() )
-    return CUBIT_FAILURE;
-
-  int i, j, k;
-  DLIList<EDGE*> draw_EDGE_list;
-  AcisBridge *ab_ptr = NULL;
-  EDGE *EDGE_ptr;
-
-  FACE *FACE_ptr = FACE_list.get_and_step();
-  if( FACE_ptr->sides() == DOUBLE_SIDED )
-  {
-    // Sheet BODY
-    // Draw EDGEs attached to EDGEs without Cubit owner attributes on them -
-    // - this will draw the targets and "side" EDGEs too.
-    // Note special case where we need to check if source and/or target still
-    // exists - source could be tweaked to an existing EDGE on the same BODY.
-    // For some reason the resulting EDGE at the target location inherits the
-    // owner attributes of the target EDGE.
-    DLIList<EDGE*> EDGE_list;
-    AQE->get_EDGEs( BODY_ptr, EDGE_list );
-
-    for( i=EDGE_list.size(); i--; )
-    {
-      EDGE_ptr = EDGE_list.get_and_step();
-      ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( EDGE_ptr );
-      if( !ab_ptr || (ab_list && ab_list->is_in_list( ab_ptr )) )
-      {
-        // Get VERTICEs on this EDGE
-        DLIList<VERTEX*> VERTEX_list;
-        AQE->get_VERTICEs( EDGE_ptr, VERTEX_list );
-
-        VERTEX *VERTEX_ptr;
-        for( j=VERTEX_list.size(); j--; )
-        {
-          VERTEX_ptr = VERTEX_list.get_and_step();
-          DLIList<EDGE*> att_EDGE_list;
-          AQE->get_EDGEs( VERTEX_ptr, att_EDGE_list );
-
-          for( k=att_EDGE_list.size(); k--; )
-          {
-            EDGE_ptr = att_EDGE_list.get_and_step();
-            draw_EDGE_list.append_unique( EDGE_ptr );
-          }
-        }
-      }
-    }
-  }
-  else
-  {
-    // Solid BODY
-    // Draw EDGEs attached to FACEs without Cubit owner attributes on them -
-    // - this will draw the targets and "side" EDGEs too.  
-    // Note special case where we need to check if source still exists - source
-    // could be tweaked to an existing FACE on the same BODY.  For some reason
-    // the resulting FACE at the target location inherits the owner attributes
-    // of one of the source FACEs.
-    for( i=FACE_list.size(); i--; )
-    {
-      FACE_ptr = FACE_list.get_and_step();
-      ab_ptr = ATTRIB_CUBIT_OWNER::cubit_owner( FACE_ptr );
-      if( !ab_ptr || (ab_list && ab_list->is_in_list( ab_ptr )) )
-      {
-        // Get VERTICEs on this FACE
-        DLIList<VERTEX*> VERTEX_list;
-        AQE->get_VERTICEs( FACE_ptr, VERTEX_list );
-
-        VERTEX *VERTEX_ptr;
-        for( j=VERTEX_list.size(); j--; )
-        {
-          VERTEX_ptr = VERTEX_list.get_and_step();
-          DLIList<EDGE*> EDGE_list;
-          AQE->get_EDGEs( VERTEX_ptr, EDGE_list );
-
-          for( k=EDGE_list.size(); k--; )
-          {
-            EDGE_ptr = EDGE_list.get_and_step();
-            draw_EDGE_list.append_unique( EDGE_ptr );
-          }
-        }
-      }
-    }
-  }
-
-  for( i=draw_EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = draw_EDGE_list.get_and_step();
-    AcisDrawTool::instance()->draw_EDGE( EDGE_ptr, CUBIT_BLUE );
-  }
-
-  if( flush )
-    GfxPreview::flush();
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tag_tweak_remove_faces_for_preview
-// Member Type: PRIVATE
-// Description: Add an attribute ("tweak_preview") to the required FACEs for a 
-//              tweak remove.  For the preview we draw the EDGEs on the
-//              surviving FACEs adjoining those that are removed.  Input is the
-//              copied BODY, along with the FACEs being removed.
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::tag_tweak_remove_FACEs_for_preview( BODY *BODY_ptr, 
-                                             DLIList<FACE*> &remove_FACE_list )
-{
-  // Add an attribute to adjoining FACEs we are removing.  Then we can
-  // draw these FACEs for the preview.  Don't worry about putting
-  // attributes on the FACEs we are removing since these FACEs won't exist
-  // when we are done anyway.
-  int i, j, k;
-  FACE *FACE_ptr;
-  ATTRIB_GEN_NAME *ret_att;
-  for( i=remove_FACE_list.size(); i--; )
-  {
-    FACE_ptr = remove_FACE_list.get_and_step();
-    DLIList<EDGE*> EDGE_list;
-    AQE->get_EDGEs( FACE_ptr, EDGE_list );
-
-    EDGE *EDGE_ptr;
-    for( j=EDGE_list.size(); j--; )
-    {
-      EDGE_ptr = EDGE_list.get_and_step();
-      DLIList<FACE*> att_FACE_list;
-      AQE->get_FACEs( EDGE_ptr, att_FACE_list );
-
-      for( k=att_FACE_list.size(); k--; )
-      {
-        FACE_ptr = att_FACE_list.get_and_step();
-
-        api_find_named_attribute( FACE_ptr, "tweak_preview", ret_att );
-        if( !ret_att )
-          api_add_generic_named_attribute( FACE_ptr, "tweak_preview", 1, SplitCopy );
-      }
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : tag_tweak_remove_faces_for_preview
-// Member Type: PRIVATE
-// Description: Add an attribute ("tweak_preview") to the required FACEs for a 
-//              tweak remove.  For the preview we draw the EDGEs on the
-//              surviving FACEs adjoining those that are removed.  Input is the
-//              copied BODY, along with the FACEs being removed.
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::tag_tweak_remove_FACEs_for_preview( BODY *BODY_ptr, 
-                                             DLIList<EDGE*> &remove_EDGE_list )
-{
-  // Add an attribute to adjoining FACEs we are removing.  Then we can
-  // draw these FACEs for the preview.
-  int i, j;
-  EDGE *EDGE_ptr;
-  FACE *FACE_ptr;
-  ATTRIB_GEN_NAME *ret_att;
-  for( i=remove_EDGE_list.size(); i--; )
-  {
-    EDGE_ptr = remove_EDGE_list.get_and_step();
-    DLIList<FACE*> att_FACE_list;
-    AQE->get_FACEs( EDGE_ptr, att_FACE_list );
-
-    for( j=att_FACE_list.size(); j--; )
-    {
-      FACE_ptr = att_FACE_list.get_and_step();
-
-      api_find_named_attribute( FACE_ptr, "tweak_preview", ret_att );
-      if( !ret_att )
-        api_add_generic_named_attribute( FACE_ptr, "tweak_preview", 1, SplitCopy );
-    }
-  }
-
-  return CUBIT_SUCCESS;
-}
-
-//=============================================================================
-// Function   : draw_tweak_preview_tagged_FACEs
-// Member Type: PRIVATE
-// Description: Draw EDGEs on FACEs with the "tweak_preview" attribute on them.
-// Author     : Steve Storm
-// Date       : 2/20/06
-//=============================================================================
-CubitStatus
-AcisTweakTool::draw_tweak_preview_tagged_FACEs( BODY *BODY_ptr, 
-                                                CubitBoolean flush )
-{
-  int i, j;
-  FACE *FACE_ptr;
-  ATTRIB_GEN_NAME *ret_att;
-  DLIList<EDGE*> draw_EDGE_list;
-  DLIList<FACE*> FACE_list;
-  AQE->get_FACEs( BODY_ptr, FACE_list );
-  for( i=FACE_list.size(); i--; )
-  {
-    FACE_ptr = FACE_list.get_and_step();
-    api_find_named_attribute( FACE_ptr, "tweak_preview", ret_att );
-    if( ret_att )
-    {
-      api_remove_generic_named_attribute( FACE_ptr, "tweak_preview" );
-
-      DLIList<EDGE*> EDGE_list;
-      AQE->get_EDGEs( FACE_ptr, EDGE_list );
-
-      for( j=EDGE_list.size(); j--; )
-        draw_EDGE_list.append_unique( EDGE_list.get_and_step() );
-    }
-  }
-
-  for( i=draw_EDGE_list.size(); i--; )
-    AcisDrawTool::instance()->draw_EDGE( draw_EDGE_list.get_and_step(),
-    CUBIT_BLUE );
-
-  if( flush )
-    GfxPreview::flush();
-
-  return CUBIT_SUCCESS;
-}
-
-

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/AcisTweakTool.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -11,9 +11,13 @@
 class Surface;
 class SurfaceACIS;
 class BodySM;
+class EDGE;
+class FACE;
 class BODY;
 class AcisBridge;
 class CubitPlane;
+class CubitString;
+class CubitBox;
 class AcisQueryEngine;
 class AcisModifyEngine;
 template <class X> class DLIList;
@@ -30,28 +34,44 @@
   static AcisTweakTool* instance();
   //- Gives access to the singleton object of this class
 
+  virtual CubitStatus tweak_bend( DLIList<BodySM*> &bend_bodies,
+	                      DLIList<BodySM*> &new_bodysm_list,
+	                      CubitVector& neutral_root,
+	                      CubitVector& bend_axis,
+	                      CubitVector& bend_direction,
+                          double radius,
+                          double angle,
+                          DLIList<CubitVector*> bend_regions,
+                          double width = -1,
+                          CubitBoolean center_bend = CUBIT_FALSE,
+                          int num_points = 0,
+                          CubitBoolean keep_old_body = CUBIT_FALSE,
+                          CubitBoolean preview = CUBIT_FALSE);
+  /**<  Bend solid bodies based on a bend radius and angle.
+    */
+
   virtual CubitStatus tweak_chamfer( DLIList<Curve*> &curve_list, 
-                                     double left_offset,
-                                     DLIList<BodySM*> &new_bodysm_list,
-                                     double right_offset = -1.0,
-                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                     CubitBoolean preview = CUBIT_FALSE );
-  /**<  Chamfer curves on solid bodies.  The left and right offsets are with 
-    *   respect to the curve direction.  If the given right offset is negative,
-    *   the left offset is used.  Users can preview to clarify the meaning of
-    *   left and right.
+                             double left_offset,
+                             DLIList<BodySM*> &new_bodysm_list,
+                             double right_offset = -1.0,
+                             CubitBoolean keep_old_body = CUBIT_FALSE,
+                             CubitBoolean preview = CUBIT_FALSE );
+  /**<  Chamfer curves on solid or sheet bodies.  The left and right offsets
+    *   are with respect to the curve direction.  If the given right offset is
+    *   negative, the left offset is used.  Users can preview to clarify the
+    *   meaning of left and right.
     */
 
   virtual CubitStatus tweak_chamfer( DLIList<Point*> &point_list, 
-                                     double offset1, 
-                                     DLIList<BodySM*> &new_bodysm_list,
-                                     Curve *edge1 = NULL,
-                                     double offset2 = -1.0,
-                                     Curve *edge2 = NULL,
-                                     double offset3 = -1.0,
-                                     Curve *edge3 = NULL,
-                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                     CubitBoolean preview = CUBIT_FALSE );
+                             double offset1, 
+                             DLIList<BodySM*> &new_bodysm_list,
+                             Curve *edge1 = NULL,
+                             double offset2 = -1.0,
+                             Curve *edge2 = NULL,
+                             double offset3 = -1.0,
+                             Curve *edge3 = NULL,
+                             CubitBoolean keep_old_body = CUBIT_FALSE,
+                             CubitBoolean preview = CUBIT_FALSE );
   /**<  Chamfer vertices on solid or sheet bodies.  On a solid body there can
     *   be up to 3 offsets; on a sheet body up to 2 offsets.  The offsets are
     *   in the direction of the supplied edges.  If multiple vertices are 
@@ -59,72 +79,91 @@
     */
 
   virtual CubitStatus tweak_fillet( DLIList<Curve*> &curve_list, 
-                                    double radius,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
-  /**<  Create a round fillet (or blend) at the given curves on solid bodies.
+                            double radius,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
+  /**<  Create a round fillet (or blend) at the given curves on solid or sheet
+    *   bodies.
     */
 
   virtual CubitStatus tweak_fillet( Curve *curve_ptr, 
-                                    double start_radius,
-                                    double end_radius,
-                                    BodySM *&new_body_ptr,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
-  /**<  Create a round fillet (or blend) at the given curve on a solid body.
-    *   The fillet has a variable radius from the start to the end of the curve.
+                            double start_radius,
+                            double end_radius,
+                            BodySM *&new_body_ptr,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
+  /**<  Create a round fillet (or blend) at the given curve on a solid or sheet
+    *   body.  The fillet has a variable radius from the start to the end of
+    *   the curve.
     */
 
   virtual CubitStatus tweak_fillet( DLIList<Point*> &point_list, 
-                                    double radius,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            double radius,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
   /**<  Create a round fillet (or blend) at the given vertices on sheet bodies.
     */
 
   virtual CubitStatus tweak_move( DLIList<Surface*> &surface_list,
-                                  const CubitVector &delta,
-                                  DLIList<BodySM*> &new_bodysm_list,
-                                  CubitBoolean keep_old_body = CUBIT_FALSE,
-                                  CubitBoolean preview = CUBIT_FALSE );
+                          const CubitVector &delta,
+                          DLIList<BodySM*> &new_bodysm_list,
+                          CubitBoolean keep_old_body = CUBIT_FALSE,
+                          CubitBoolean preview = CUBIT_FALSE );
   /**<  Tweak specified faces of a volume or volumes along a vector.
     */
 
   virtual CubitStatus tweak_move( DLIList<Curve*> &curve_list,
-                                  const CubitVector &delta,
-                                  DLIList<BodySM*> &new_bodysm_list,
-                                  CubitBoolean keep_old_body = CUBIT_FALSE,
-                                  CubitBoolean preview = CUBIT_FALSE );
+                          const CubitVector &delta,
+                          DLIList<BodySM*> &new_bodysm_list,
+                          CubitBoolean keep_old_body = CUBIT_FALSE,
+                          CubitBoolean preview = CUBIT_FALSE );
   /**<  Tweak specified curves of a sheet body along a vector.
     */
 
   virtual CubitStatus tweak_offset( DLIList<Surface*> &surface_list,
-                                    double offset_distance,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            double offset_distance,
+                            DLIList<Surface*> *add_surface_list_ptr, 
+                            DLIList<double> *add_offset_list_ptr,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
   /**<  Tweak specified faces of a volume or volumes by offsetting those faces
-    *   by the offset distance.
+    *   by the offset distance(s).
     */
 
+  virtual CubitStatus make_offset_sheet( DLIList<Surface*> &surface_list,
+                                 double def_offset,
+                                 DLIList<Surface*> *add_surface_list_ptr, 
+                                 DLIList<double> *add_offset_list_ptr,
+                                 DLIList<BodySM*> &new_bodysm_list,
+                                 CubitBoolean preview = CUBIT_FALSE );
+  /**< Create a sheet body (or bodies) by offsetting the given surfaces.
+    *  Different surfaces can have different offsets. Adjoining surfaces are
+    *  extended or trimmed to remain joined in the new sheet body. Radial
+    *  surfaces that cannot be so offset are removed and the resulting wound
+    *  healed by the surrounding surfaces. The input surfaces can be from
+    *  different bodies. Newly created sheet bodies are separated.
+    */
+
   virtual CubitStatus tweak_offset( DLIList<Curve*> &curve_list,
-                                    double offset_distance,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            double offset_distance,
+                            DLIList<Curve*> *add_curve_list_ptr, 
+                            DLIList<double> *add_offset_list_ptr,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
   /**<  Tweak specified curves of a sheet body or bodies by offsetting those
-    *   curves by the offset distance.
+    *   curves by the offset distance(s).
     */
 
   virtual CubitStatus tweak_remove( DLIList<Surface*> &surface_list,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean extend_adjoining = CUBIT_TRUE,
-                                    CubitBoolean keep_surface = CUBIT_FALSE,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
-  /**<  Remove surfaces from a body or bodies and then by default extend
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_adjoining = CUBIT_TRUE,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
+  /**<  Remove surfaces from solid or sheet bodies and then by default extend
     *   the adjoining surfaces to fill the gap or remove the hole.  This
     *   requires functionality from the ACIS local operations husk.  This
     *   capability can usually successfully remove fillets, chamfers, blind
@@ -132,50 +171,112 @@
     */
 
   virtual CubitStatus tweak_remove( DLIList<Curve*> &curve_list,
-                                    DLIList<BodySM*> &new_bodysm_list, 
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            DLIList<BodySM*> &new_bodysm_list, 
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
   /**<  Remove curves from a sheet body or bodies and then extend the remaining
     *   curves to fill the gap.  If an internal loop of curves is removed the
     *   hole is removed.
     */
 
   virtual CubitStatus tweak_target( DLIList<Surface*> &surface_list,
-                                    DLIList<Surface*> &target_surf_list,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean reverse_flg = CUBIT_FALSE,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            DLIList<Surface*> &target_surf_list,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_flg = CUBIT_TRUE,
+                            CubitPlane *limit_plane = NULL,
+                            CubitBoolean reverse_flg = CUBIT_FALSE,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
   /**<  Tweak specified faces of a volume or volumes up to a set of target
     *   surfaces.  Topology is tweaked to the target surfaces.  Think of this
     *   as extending/trimming the body up past the target surfaces, then
     *   webcutting it off with the extended target surfaces and throwing away
-    *   the excess.  The reverse flag should never be needed - if it is, there
-    *   may be a bug or a bad normal on a body (i.e., negative volume body).
+    *   the excess.  If extend flag is true, extend out the targets before 
+    *   tweaking to them (only valid for multiple targets).  The optional limit
+    *   plane is only valid if extend_flg is TRUE; it will limit the tweak to
+    *   not go past this plane in the case where the tweaked body would only
+    *   partially intersect the extended targets.  The reverse flag should
+    *   never be needed - if it is, there may be a bug or a bad normal on a
+    *   body (i.e., negative volume body), and is only retained for
+    *   debugging.
     */
 
   virtual CubitStatus tweak_target( DLIList<Curve*> &curve_list,
-                                    DLIList<Surface*> &target_surf_list,
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean reverse_flg = CUBIT_FALSE,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            DLIList<Surface*> &target_surf_list,
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_flg = CUBIT_TRUE,
+                            CubitPlane *limit_plane = NULL,
+                            CubitBoolean reverse_flg = CUBIT_FALSE,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE,
+                            double max_area_increase = 0 );
   /**<  Tweak specified edges of a surface or set of surfaces (in sheet bodies)
     *   up to a set of target surfaces.  This essentially extends or trims the
-    *   attached surfaces of the sheet body.
+    *   attached surfaces of the sheet body.  If extend flag is true, extend
+    *   out the targets before tweaking to them (only valid for multiple
+    *   targets).  The optional limit plane is only valid if extend_flg is
+    *   TRUE; it will limit the tweak to not go past this plane in the case
+    *   where the tweaked body would only partially intersect the extended
+    *   targets.  The reverse flag should never be needed - if it is, there may
+    *   be a bug or a bad normal on a body (i.e., negative volume body), and is
+    *   only retained for debugging.
     */
 
   virtual CubitStatus tweak_target( DLIList<Curve*> &curve_list,
-                                    DLIList<Curve*> &target_curve_list, 
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean reverse_flg = CUBIT_FALSE,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
+                            DLIList<Curve*> &target_curve_list, 
+                            DLIList<BodySM*> &new_bodysm_list,
+                            CubitBoolean extend_flg = CUBIT_TRUE,
+                            CubitPlane *limit_plane = NULL,
+                            CubitBoolean reverse_flg = CUBIT_FALSE,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE,
+                            double max_area_increase = 0 );
   /**<  Tweak specified edges of a sheet body or bodies up to a set of target
     *   curves that are part of a sheet body.  The target is a set of surfaces
-    *   created by thickening the owning surfaces of the target curves.
+    *   created by thickening the owning surfaces of the target curves.  If
+    *   extend flag is true, extend out the targets before tweaking to them 
+    *   (only valid for multiple targets).  The optional limit plane is only
+    *   valid if extend_flg is TRUE; it will limit the tweak to not go past
+    *   this plane in the case where the tweaked body would only partially
+    *   intersect the extended targets.  The reverse flag should never be
+    *   needed - if it is, there may be a bug or a bad normal on a body (i.e.,
+    *   negative volume body), and is only retained for debugging.
     */
 
+  virtual CubitStatus tweak_target( Point *point_ptr,
+                            DLIList<Surface*> &modify_surface_list,
+                            CubitVector &target_loc,
+                            BodySM *&new_bodysm_ptr,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
+  /**<  Tweak specified vertex of a sheet body to a given location.  The
+    *   given vertex must be part of a planar surface or surfaces attached to
+    *   linear curves only.  The user specified which of those surfaces to
+    *   actually modify.  The given location will be projected to be on the
+    *   given planar surface(s) before being used - this projected location
+    *   must be the same on all surfaces.
+    */
+
+  virtual CubitStatus make_extended_sheet( DLIList<FACE*> &FACE_list, 
+                                   BODY *&ext_BODY_ptr,
+                                   CubitBox *clip_box_ptr = NULL,
+                                   bool suppress_errors = false);
+  /**< Extend out a set of FACEs and place into a new sheet BODY.  Holes are 
+    * removed and the BODY is healed for consistent FACE  normals.  The BODY
+    * is also regularized.  Note this can result in a nonmanifold sheet,
+    * especially if it contains cylindrical FACEs as they turn into full
+    * cylinders.  The resultant BODY can be optionally clipped by the given
+    * bounding box.  NOTE: this function should be moved to AME, but it was
+    * easy to expose here, so this is left for the future.
+    */
+
+  virtual CubitStatus remove_topology( DLIList<Curve*> &curve_list,
+                               DLIList<Surface*> &surface_list,
+                               double backoff_distance,
+                               double small_edge_size,
+                               DLIList<BodySM*> &new_bodysm_list,
+                               CubitBoolean preview );
+
 protected:
    AcisTweakTool();
    //- Class Constructor. (Not callable by user code. Class is constructed
@@ -183,555 +284,37 @@
 
 private:
 
-  CubitStatus tweak_target_single( DLIList<Surface*> &surface_list,
-                                   Surface *target_surf_ptr,
-                                   DLIList<BodySM*> &new_bodysm_list,
-                                   CubitBoolean reverse_flg = CUBIT_FALSE,
-                                   CubitBoolean keep_old_body = CUBIT_FALSE,
-                                   CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified faces of a volume or volumes up to a single target
-    *   surface.  Topology is tweaked to the target surface.  Think of this
-    *   as extending/trimming the body up past the target surface, then
-    *   webcutting it off with the extended target surface and throwing away
-    *   the excess.  The reverse flag should never be needed - if it is, there
-    *   may be a bug or a bad normal on a body (i.e., negative volume body).
-    */
+   virtual CubitBoolean set_silent( CubitBoolean flg );
+   //- Set the silent flag for certain messages, so that a thicken can be
+   //- retried and a tweak-target-multiple can be retried without printing
+   //- messages or incrementing the error count for the first try.  This 
+   //- was implemented in this manner in the hopes that a global silence
+   //- method will someday be implemented in UserInterface or CubitMessage.
+   //- Functions using this method will precede their messages with the 
+   //- MSG macro, for a somewhat nonintrusive way to implement.  Here are 
+   //- the functions that use this:  align_normals, append_neighbors
+   //-  chop_off_with_sheet, copy_FACEs_into_sheet, create_offset_planar_body,
+   //-  extrema_pln_BODY, find_overlap_FACE, get_overlap_area, get_seed_FACE,
+   //-  heal_BODY, make_surf_normals_consistent, prep_cutting_sheet,
+   //-  prep_for_surface_swap, remove_aligned_periodic_FACEs,
+   //-  remove_per_nonmanifold_FACEs, thicken_BODY, tweak_FACEs_to_target,
+   //-  tweak_target_multiple, weighted_average_FACE_normal
 
-  CubitStatus tweak_target_multiple( DLIList<Surface*> &surface_list,
-                                     DLIList<Surface*> &target_surf_list,
-                                     DLIList<BodySM*> &new_bodysm_list,
-                                     CubitBoolean reverse_flg = CUBIT_FALSE,
-                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                     CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified faces of a volume or volumes up to a set of target
-    *   surfaces.  Topology is tweaked to the target surfaces.  Think of this
-    *   as extending/trimming the body up past the target surfaces, then
-    *   webcutting it off with the extended target surfaces and throwing away
-    *   the excess.  The reverse flag should never be needed - if it is, there
-    *   may be a bug or a bad normal on a body (i.e., negative volume body).
-    */
 
-  CubitStatus tweak_target_single( DLIList<Curve*> &curve_list,
-                                   Surface *target_surf_ptr,
-                                   DLIList<BodySM*> &new_bodysm_list,
-                                   CubitBoolean reverse_flg = CUBIT_FALSE,
-                                   CubitBoolean keep_old_body = CUBIT_FALSE,
-                                   CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified edges of a surface or set of surfaces (in sheet bodies)
-    *   up to a single target surface.  This essentially extends or trims the
-    *   attached surfaces of the sheet body.
-    */
 
-  CubitStatus tweak_target_multiple( DLIList<Curve*> &curve_list,
-                                     DLIList<Surface*> &target_surf_list,
-                                     DLIList<BodySM*> &new_bodysm_list, 
-                                     CubitBoolean reverse_flg = CUBIT_FALSE,
-                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                     CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified edges of a surface or set of surfaces (in sheet bodies)
-    *   up to a set of target surfaces.  This essentially extends or trims the
-    *   attached surfaces of the sheet body.
-    */
-
-  CubitStatus tweak_target_single( DLIList<Curve*> &curve_list,
-                                   Curve *target_curve_ptr, 
-                                   DLIList<BodySM*> &new_bodysm_list,
-                                   CubitBoolean reverse_flg = CUBIT_FALSE,
-                                   CubitBoolean keep_old_body = CUBIT_FALSE,
-                                   CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified edges of a sheet body or bodies up to a single target
-    *   curve that is part of a sheet body.  The target is a surface created
-    *   by thickening the owning surface of the target curve.
-    */
-
-  CubitStatus tweak_target_multiple( DLIList<Curve*> &curve_list,
-                                     DLIList<Curve*> &target_curve_list, 
-                                     DLIList<BodySM*> &new_bodysm_list,
-                                     CubitBoolean reverse_flg = CUBIT_FALSE,
-                                     CubitBoolean keep_old_body = CUBIT_FALSE,
-                                     CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified edges of a sheet body or bodies up to a set of target
-    *   curves that are part of a sheet body.  The target is a set of surfaces
-    *   created by thickening the owning surfaces of the target curves.
-    */
-
-  CubitStatus tweak_target_multiple( DLIList<FACE*> &source_FACE_list,
-                                     DLIList<FACE*> &target_FACE_list,
-                                     BODY *ext_target_BODY_ptr,
-                                     DLIList<BodySM*> &debug_BodySM_list,
-                                     CubitBoolean reverse_flg = CUBIT_FALSE );
-  //- Tweak target multiple workhorse function.  The source FACE list must be
-  //- from a single BODY.  The target FACE list can be from multiple BODIES. 
-  //- The ext_target_BODY_ptr is passed in - you can create it from the targets
-  //- by using the function "create_extended_sheet" (it is passed in instead of
-  //- created in this function for efficiency since this function is likely
-  //- called inside of a loop for multiple source BODIEs). The debug_BodySM_list
-  //- is populated with debug BODIES if the debug flag 167 is turned on.
-
-  CubitStatus get_ACIS_surfaces( DLIList<Surface*> &surface_list,
-                                 DLIList<SurfaceACIS*> &acis_list );
-   //- Get SurfaceACISs from Surfaces
-
-   CubitStatus get_FACEs( DLIList<Surface*> &surface_list,
-                          DLIList<FACE*> &FACE_list );
-   //- Get FACEs from Surfaces
-
-   CubitStatus get_EDGEs( DLIList<Curve*> &curve_list,
-                          DLIList<EDGE*> &EDGE_list );
-   //- Get EDGEs from Curves
-
-   CubitStatus get_VERTICEs( DLIList<Point*> &point_list,
-                             DLIList<VERTEX*> &VERTEX_list );
-   //- Get VERTICEs from Points 
-
-   CubitStatus tweak_target_single( DLIList<EDGE*> &input_EDGE_list,
-                                    FACE *target_FACE_ptr, 
-                                    DLIList<BodySM*> &new_body_list,
-                                    CubitBoolean reverse_flg = CUBIT_FALSE,
-                                    CubitBoolean keep_old_bodies = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE,
-                                    DLIList<AcisBridge*> *t_ab_list = NULL );
-   //- Tweak EDGES workhorse function.  Note this function will return SUCCESS
-   //- if any new bodies were created (i.e., it could fail on some and still
-   //- return SUCCESS).  Last argument is needed for preview - if target was
-   //- derived from an EDGE send in the AcisBridge of that EDGE - preview 
-   //- needs to know about this EDGE if it exists on the input BODY itself.
-
-   CubitStatus tweak_target_multiple( DLIList<EDGE*> &input_EDGE_list,
-                                      DLIList<FACE*> &target_FACE_list, 
-                                      DLIList<BodySM*> &new_bodysm_list,
-                                      CubitBoolean reverse_flg = CUBIT_FALSE,
-                                      CubitBoolean keep_old_bodies = CUBIT_FALSE,
-                                      CubitBoolean preview = CUBIT_FALSE,
-                                      DLIList<AcisBridge*> *t_ab_list = NULL );
-   //- Tweak EDGES to multiple FACEs workhorse function.  Note this function
-   //- will return SUCCESS if any new bodies were created (i.e., it could fail
-   //- on some and still return SUCCESS).  Last argument is needed for preview -
-   //- if targets were derived from an EDGE list send in the AcisBridges of
-   //- those EDGEs - it is possible (unlikely though) that these EDGEs (if
-   //- part of the BODY itself) could exist in the final result and are needed
-   //- for the preview.
-
-   CubitStatus get_thickened_BODIES_of_EDGES( const char *command_name,
-                                              DLIList<EDGE*> &EDGE_list,
-                                              DLIList<EDGE*> &removed_EDGE_list,
-                                              BODY *&common_BODY_ptr,
-                                              DLIList<BODY*> &thickened_BODY_list,
-                                              DLIList<DLIList<EDGE*>*> &output_EDGE_lists,
-                                              DLIList<DLIList<FACE*>*> &output_FACE_lists,
-                                              DLIList<DLIList<FACE*>*> &conjugate_FACE_lists,
-                                              double thickness = 0.2 );
-   //- Get thickened BODIES from an input list of EDGEs.  This function can be
-   //- called multiple times on the same list of EDGEs - each time, the EDGEs 
-   //- from the common body that is thickened are removed from the input EDGE
-   //- list.  The thickened BODIES are copied from the sheet the EDGEs are
-   //- attached to (multiple BODIES can be returned because the returned
-   //- thickened BODIES must be nonmanifold).  For each BODY returned, also
-   //- output a list of EDGES (corresponding to the original input EDGEs), a
-   //- list of FACEs (corresponding to the original FACEs of the input BODY)
-   //- and a list of conjugate FACEs (the "side" FACEs of the thickened BODY -
-   //- these are the FACEs we can tweak).
-
-   CubitStatus get_thickened_BODIES_of_VERTICES( const char *command_name,
-                                                 DLIList<VERTEX*> &input_VERTEX_list,
-                                                 BODY *&common_BODY_ptr,
-                                                 DLIList<BODY*> &thickened_BODY_list,
-                                                 DLIList<DLIList<FACE*>*> &output_FACE_lists,
-                                                 DLIList<DLIList<VERTEX*>*> &output_VERTEX_lists,
-                                                 DLIList<DLIList<EDGE*>*> &output_EDGE_lists,
-                                                 double thickness = 0.2 );
-   //- Get thickened BODIES from an input list of VERTICEs.  This function can
-   //- be called multiple times on the same list of VERTICEs - each time, the
-   //- VERTICEs from the common body that is thickened are removed from the
-   //- input EDGE list.  These thickened BODIES are copied from the sheets the
-   //- VERTICEs are attached to (multiple BODIES can be returned because the 
-   //- thickened BODIES must be nonmanifold).  For each BODY returned, also
-   //- output a list of the FACEs (corresponding to the original FACEs of the
-   //- sheet body), the VERTICEs (corresponding to the original VERTICEs), and
-   //- a list of EDGEs created by the thickening process (from sweeping the
-   //- original VERTEX - note it is possible that no EDGE was created, in which
-   //- case a NULL value will exist in the list).
-
-   CubitStatus copy_FACES_from_BODY( DLIList<FACE*> &FACE_list, 
-                                     BODY *&copied_BODY_ptr);
-   //- Input FACE list must be in a single BODY.  Copy these FACEs off into
-   //- a new BODY, while retaining all the Cubit attributes.  The input
-   //- BODY (the parent BODY of the FACE_list) is NOT modified.
-
-   CubitStatus remove_FACES_from_BODY( BODY *BODY_ptr, 
-                                       DLIList<FACE*> &remove_FACE_list );
-   //- Remove the given FACEs from the BODY (modifying the input BODY).
-
-   CubitStatus remove_FACES_from_BODY_except( BODY *BODY_ptr, 
-                                              DLIList<FACE*> &keep_FACE_list );
-   //- Remove all FACEs from the BODY except those in the keep_FACE_list
-   //- (modifying the input BODY).
-
-   CubitStatus thicken_BODY( BODY *BODY_ptr, double thickness );
-   //- Thicken a BODY.  Remove CUBIT owner attributes from all VERTICEs, EDGEs,
-   //- and FACEs except the original VERTICEs, EDGEs and FACEs.
-
-   VERTEX *find_corresponding_VERTEX( VERTEX *ref_VERTEX_ptr, DLIList<VERTEX*> &VERTEX_list );
-   //- Find the corresponding VERTEX in the input VERTEX_list to the ref_VERTEX_ptr
-   //- using CUBIT owner attributes.  For example, copy a BODY then use this
-   //- function to find a corresponding VERTEX from the parent BODY on the copied
-   //- BODY.
-
-   EDGE *find_corresponding_EDGE( EDGE *ref_EDGE_ptr, DLIList<EDGE*> &EDGE_list );
-   //- Find the corresponding EDGE in the input EDGE_list to the ref_EDGE_ptr
-   //- using CUBIT owner attributes.  For example, copy a BODY then use this
-   //- function to find a corresponding EDGE from the parent BODY on the copied
-   //- BODY.
-
-   LOOP *find_corresponding_LOOP( LOOP *ref_LOOP_ptr, DLIList<LOOP*> &LOOP_list );
-   //- Find the corresponding LOOP in the input LOOP_list to the ref_LOOP_ptr
-   //- using CUBIT owner attributes.  For example, copy a BODY then use this
-   //- function to find a corresponding LOOP from the parent BODY on the copied
-   //- BODY.
-
-   FACE *find_corresponding_FACE( FACE *ref_FACE_ptr, DLIList<FACE*> &FACE_list );
-   //- Find the corresponding FACE in the input FACE_list to the ref_FACE_ptr
-   //- using CUBIT owner attributes.  For example, copy a BODY then use this
-   //- function to find a corresponding FACE from the parent BODY on the copied
-   //- BODY.
-
-   FACE *find_corresponding_FACE( AcisBridge *ab_ptr, BODY *BODY_ptr);
-   //- Find FACE with given owner in the BODY_ptr
-
-   LOOP *find_corresponding_LOOP( AcisBridge *ab_ptr, BODY *BODY_ptr);
-   //- Find LOOP with given owner in the BODY_ptr
-
-   CubitStatus get_owner_list( DLIList<EDGE*> &EDGE_list, 
-                               DLIList<AcisBridge*> &owner_list );
-   //- Get a list of Cubit owners corresponding to the input EDGE list.
-   //- Appends (unique) to the input list.
-
-   CubitStatus get_owner_list( DLIList<FACE*> &FACE_list, 
-                               DLIList<AcisBridge*> &owner_list );
-   //- Get a list of Cubit owners corresponding to the input FACE list.
-   //- Appends (unique) to the input list.
-
-   CubitStatus get_owner_list( DLIList<LOOP*> &LOOP_list, 
-                               DLIList<AcisBridge*> &owner_list );
-   //- Get a list of Cubit owners corresponding to the input LOOP list.
-   //- Appends (unique) to the input list.
-
-   CubitStatus get_corresponding_FACE_list( DLIList<AcisBridge*> &owner_list,
-                                            BODY *BODY_ptr,
-                                            DLIList<FACE*> &corresponding_FACE_list );
-   //- Find the FACEs in BODY_ptr corresponding to the given owners
-
-   CubitStatus get_corresponding_LOOP_list( DLIList<AcisBridge*> &owner_list,
-                                            BODY *BODY_ptr,
-                                            DLIList<LOOP*> &corresponding_LOOP_list );
-   //- Find the LOOPs in BODY_ptr corresponding to the given owners
-
-   CubitStatus prep_for_surface_swap( BODY *thickened_BODY_ptr,
-                                      BODY *copied_input_BODY_ptr,
-                                      DLIList<AcisBridge*> &owner_FACE_list );
-   //- Prepare to swap the non-extended surfaces in the (original)
-   //- copied_input_BODY_ptr with the extended surfaces in the
-   //- thickened_BODY_ptr.  This function removes ALL BUT the input
-   //- FACEs from the thickend_BODY_ptr (so we just have the extended or
-   //- trimmed FACEs left), and removes the input FACEs from the 
-   //- copied_input_BODY_ptr.  These two BODIEs can be united later for the
-   //- end result - the sheet BODY surfaces have been extended/trimmed/etc.!
-
-   CubitStatus unite_BODIES( BODY *copied_input_BODY_ptr,
-                             DLIList<BODY*> &thickened_BODY_list,
-                             BODY *&output_BODY_ptr );
-   //- Unite all the given BODIES.
-
-   CubitStatus get_owner_attribs( BODY *BODY_ptr, AcisBridge *&ab_body_ptr,
-     AcisBridge *&ab_lump_ptr, AcisBridge *&ab_shell_ptr);
-   //- Get owner attributes on the BODY, LUMP, SHELL
-
-   CubitStatus reset_owner_attribs( BODY *BODY_ptr, AcisBridge *ab_body_ptr,
-     AcisBridge *ab_lump_ptr, AcisBridge *ab_shell_ptr);
-   //- Reset owner attributes on the BODY, LUMP, SHELL, since some operations
-   //- remove them.
-
-   CubitStatus sort_points_by_body_type( DLIList<Point*> &point_list, 
-     DLIList<Point*> &solid_points, DLIList<Point*> &sheet_points );
-   //- Sort the incoming point list by the type of owning body of the points -
-   //- solids or sheet bodies.
-
-   CubitStatus tweak_chamfer_solid( DLIList<Point*> &point_list, 
-                                    double radius, 
-                                    DLIList<BodySM*> &new_bodysm_list,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
-  //- Chamfer vertices on solid bodies
-
-   CubitStatus tweak_chamfer_fillet_sheet( DLIList<Point*> &point_list, 
-                                           double radius, 
-                                           int type,
-                                           DLIList<BodySM*> &new_bodysm_list,
-                                           CubitBoolean keep_old_body = CUBIT_FALSE,
-                                           CubitBoolean preview = CUBIT_FALSE );
-   //- Chamfer or fillet vertices on sheet bodies.
-   //- Type = 1=chamfer
-   //-        2=fillet
-
-   CubitStatus tweak_chamfer_solid( Point* point_ptr, 
-                                    double r1,                                      
-                                    Curve *c1,
-                                    double r2,
-                                    Curve *c2,
-                                    double r3,
-                                    Curve *c3,
-                                    BodySM *&new_bodysm_ptr,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
-   //- Chamfer a vertex on a solid body with variable radii.  Radii correspond
-   //- to given curves.
-
-   CubitStatus tweak_chamfer_sheet( Point* point_ptr, 
-                                    double r1,                                      
-                                    Curve *c1,
-                                    double r2,
-                                    Curve *c2,
-                                    BodySM *&new_bodysm_ptr,
-                                    CubitBoolean keep_old_body = CUBIT_FALSE,
-                                    CubitBoolean preview = CUBIT_FALSE );
-   //- Chamfer a vertex on a sheet body with variable radii.  Radii correspond
-   //- to given curves.
-
-   CubitStatus assign_tweak_attribs( BODY *BODY_ptr, const char *att_name,
-     DLIList<FACE*> &FACE_list, DLIList<AcisBridge*> &ab_FACE_list, 
-     DLIList<EDGE*> &EDGE_list, DLIList<AcisBridge*> &ab_EDGE_list,
-     DLIList<VERTEX*> &VERTEX_list, DLIList<AcisBridge*> &ab_VERTEX_list );
-   //- Assign named attribs to faces, edges and vertices so we can get back to
-   //- them after a fillet or chamfer.  These operations split these entities
-   //- to make room for the new surfaces, and the original entities (and
-   //- owner atributes) are lost. Thus we copy the owner atts during the split.
-   //- This ultimately will allow us to preserve Cubit owners through a chamfer
-   //- or fillet operation
-
-   CubitStatus find_corresponding_entity_from_tweak_attrib( BODY *BODY_ptr, 
-                                                            const char *att_name,
-                                                            const int ent_type, 
-                                                            int ent_integer,
-                                                            ENTITY *&output_ENTITY_ptr );
-   //- Find a corresponding entity to the input ENTITY_ptr using the tweak
-   //- attributes assigned by assign_tweak_attribs.
-   //- Input is of type ent_type, either FACE_TYPE, EDGE_TYPE, VERTEX_TYPE
-
-   CubitStatus reassign_cubit_owners_from_tweak_attribs( BODY *BODY_ptr,
-     const char *att_name,
-     DLIList<FACE*> &FACE_list, DLIList<AcisBridge*> &ab_FACE_list, 
-     DLIList<EDGE*> &EDGE_list, DLIList<AcisBridge*> &ab_EDGE_list,
-     DLIList<VERTEX*> &VERTEX_list, DLIList<AcisBridge*> &ab_VERTEX_list );
-   //- Using the tweak attributes assigned by assign_tweak_attribs, reset
-   //- the Cubit owners back on the proper entities.
-
-   CubitStatus remove_named_attribs( BODY *BODY_ptr, const char *name );
-   //- Remove the named attributes from FACEs, EDGEs and VERTICEs
-
-   CubitStatus blend_edges( DLIList<EDGE*> EDGE_list, double radius );
-   //- Perform a blend operation.  This maintains Cubit owners where
-   //- possible through the operation.
-
-   CubitStatus chamfer_edges( DLIList<EDGE*> EDGE_list, double r1, double r2 = -1.0 );
-   //- Perform a chamfer operation.  This maintains Cubit owners where
-   //- possible through the operation.
-
-   CubitStatus chamfer_vertices( DLIList<VERTEX*> VERTEX_list, double radius );
-   //- Perform a chamfer operation.  This maintains Cubit owners where
-   //- possible through the operation.
-
-   CubitBoolean FACE_surrounded( FACE *ref_FACE_ptr, 
-                                 DLIList<FACE*> &FACE_list );
-   //- Determine if given (reference) FACE is entirely surrounded by 
-   //- the FACEs in FACE_list (reference FACE can be contained in
-   //- FACE_list).
-
-   CubitStatus get_outer_EDGEs( FACE *FACE_ptr, DLIList<EDGE*> &EDGE_list );
-   //- Get EDGEs from outer LOOP of FACE
-
-   CubitStatus get_EDGES_by_BODY( DLIList<Curve*> &input_curve_list, 
-                                  DLIList<BODY*> &BODY_list, 
-                                  DLIList<DLIList<EDGE*>*> &BODY_EDGE_lists );
-   CubitStatus get_EDGES_by_BODY( DLIList<EDGE*> &input_EDGE_list, 
-                                  DLIList<BODY*> &BODY_list, 
-                                  DLIList<DLIList<EDGE*>*> &BODY_EDGE_lists );
-   //- Get separate lists of EDGEs from the input EDGEs by common BODY.  Be
-   //- sure to free the individual lists in BODY_EDGE_lists when you are done
-   //- with them, as this function allocates the memory for these lists.
-
-   CubitStatus all_complete_internal_loops( DLIList<EDGE*> &BODY_EDGE_list,
-                                            DLIList<LOOP*> &LOOP_list );
-   //- Determine if given EDGEs form complete internal LOOPs.  LOOPs must be on
-   //- a sheet BODY.  Return those LOOPs.  All given EDGEs must be in the same
-   //- BODY.
-
-   CubitStatus remove_LOOPs( DLIList<LOOP*> &LOOP_list );
-   //- Remove the given internal LOOPs (from sheet BODIES).
-
-   CubitStatus remove_holes( BODY *sheet_BODY_ptr );
-   //- Remove all of the holes (internal LOOPs) in the given sheet BODY.                     
-
-   CubitStatus extrema_pln_BODY( CubitPlane &plane, BODY *BODY_ptr,
-                                 double &extrema_dist, int back_side = 0 );
-   //- Finds the extrema distance from a plane to an ACIS BODY (perpendicular
-   //- distance from plane to farthest extent of BODY), on one side of the
-   //- plane (by default on the front of the plane - direction of plane
-   //- normal).  If the entire BODY lies on the other side of the plane, the
-   //- extrema distance is 0.0.
-
-   CubitStatus tweak_FACEs_to_target( DLIList<FACE*> &tweak_FACE_list, 
-     FACE *target_FACE, CubitBoolean reverse_flg = CUBIT_FALSE,
-     CubitBoolean skip_self_int_check = CUBIT_FALSE );
-   //- Tweak the given FACEs (which must all be part of the same BODY) to the
-   //- given target FACE.  The reverse flag should never be needed - if it is,
-   //- there may be a bug or a bad normal on a body (i.e., negative volume
-   //- body.  However, it is here as a workaround if needed.
-
-   CubitVector surface_normal( FACE *FACE_ptr, CubitVector &location,
-                               CubitBoolean calc_loc = CUBIT_TRUE );
-   //- Get normal of underlying surface of given FACE.  If calc_loc is 
-   //- CUBIT_TRUE, the location vector is calculated as the closest location on
-   //- the FACE to the center of the bounding box of the FACE, and the normal
-   //- is found there.  If calc_loc is CUBIT_FALSE, the normal is found at the
-   //- given location.  Note the normal is NOT adjusted for the FACE sense.
-
-   CubitVector FACE_normal( FACE *FACE_ptr, CubitVector &location,
-                            CubitBoolean calc_loc = CUBIT_TRUE );
-   //- Get normal of given FACE.  If calc_loc is CUBIT_TRUE, the location
-   //- vector is calculated as the closest location on the FACE to the center
-   //- of the bounding box of the FACE, and the normal is found there.  If
-   //- calc_loc is CUBIT_FALSE, the normal is found at the given location.
-   //- Note the normal is adjusted for the FACE sense.
-
-   CubitVector weighted_average_FACE_normal( DLIList<FACE*> &FACE_list );
-   //- Get weighted average normal of given FACEs.  The normals are weighted
-   //- by a factor related to FACE area utilizing the graphics facets.
-
-   CubitStatus weighted_average_FACE_normal( FACE *FACE_ptr, CubitVector &norm,
-                                             double &weight );
-   //- Get weighted average normal of give FACE.  The normal is weighted
-   //- by a factor related to FACE area utilizing the graphics facets.  Note 
-   //- for a surface like a full cylinder, this can result in a 0,0,0 normal
-   //- vector.
-
-   CubitStatus create_offset_planar_body( CubitPlane &plane, double offset,
-                                          BODY *&planar_BODY_ptr );
-   //- Create a planar ACIS BODY from the given CubitPlane and offset.  The
-   //- offset is in the direction of the plane's normal.  The plane is 
-   //- arbitrarily 10x10x10 in size near the origin.
-
-   CubitStatus create_extended_sheet( DLIList<FACE*> &FACE_list, 
-                                      BODY *&ext_BODY_ptr );
-   //- Extend out a set of FACEs and place into a new sheet BODY.
-
-   CubitStatus prep_cutting_sheet( BODY *&cutting_sheet, 
-                                   BODY *tweaked_BODY_ptr,
-                                   BODY *ext_target_BODY_ptr, 
-                                   CubitVector &source_norm,
-                                   CubitVector &target_norm,
-                                   CubitBoolean check_crossing = CUBIT_TRUE );
-   //- Prepare the cutting sheet for chopping off the BODY in a
-   //- tweak_target_multiple operation.  Inputs include the cutting sheet,
-   //- the tweaked BODY (the BODY that will be cut), the extended target BODY
-   //- with consistent normals and reference source and target normals.  The
-   //- cutting sheet can optionally be trimmed to including only FACEs crossed
-   //- by the extended target (the "side" FACEs) that we want to cut.  Note
-   //- named "tweak" attributes must exist on the side FACEs prior to calling
-   //- this function if "check_crossing" is true.
-
-   CubitStatus chop_off_with_sheet( BODY *BODY_ptr, BODY *sheet_BODY_ptr );
-   //- Chop off all the material in a BODY to one side of a sheet body.  The
-   //- material is removed on the side of the sheet body according to the
-   //- surface normals of the sheet body (material removed in the direction of
-   //- the surface normals of the sheet body, which must be consistent).
-
-   CubitStatus get_overlap_area( BODY *BODY_ptr1, BODY *BODY_ptr2, 
-                                 double &overlap_area, double accuracy = 1e-5 );
-   //- Determine the area of overlap of two BODIES.  Uses an ACIS intersection
-   //- boolean so is quite expensive.
-
-   CubitStatus copy_FACEs_into_sheet( DLIList<FACE*> &FACE_list, 
-                                      BODY *&sheet_ptr,
-                                      CubitBoolean heal = CUBIT_TRUE );
-   //- Copies the given FACEs into a sheet BODY.  The FACEs are united together
-   //- into the new BODY.  Note a regularized boolean is performed (so the body
-   //- is regularized).  By default the sheet BODY is healed, but this can be
-   //- turned off.  Note healing will make the normals consistent, unless there
-   //- is nonmanifold geometry in the body.
-
-   CubitStatus remove_per_nonmanifold_FACEs( BODY *cutting_tool );
-   //- Removes undesired nonmanifold FACEs in the cutting sheet.  See 
-   //- diagram in function for one such case.  If any nonmanifold edges exist
-   //- in the model that can't be removed, CUBIT_FAILURE is returned.
-
-   CubitStatus tangent_outdir( FACE *FACE_ptr, EDGE *EDGE_ptr, 
-                               CubitVector &pos, CubitVector &tangent_outvec );
-   //- Finds the direction tangent to and pointing away from the FACE boundary
-   //- at the given location on the EDGE.
-
-   CubitStatus remove_aligned_periodic_FACEs( BODY *cutting_tool, 
-                                              CubitVector &basis_vec );
-   //- Removes cone, sphere or torus FACEs that have normals aligned with the
-   //- given basis vector.
-
-   CubitStatus heal_BODY( BODY *BODY_ptr );
-   //- Use the ACIS healer to heal the given sheet BODY.
-
-   CubitStatus align_normals( BODY *child, BODY *master );
-   //- Align the normals of the child's FACEs to the master FACEs.  It is
-   //- assumed the child is a subset of the master (i.e., the master is an
-   //- extended BODY).
-
-   FACE * find_overlap_FACE( FACE *FACE_ptr, DLIList<FACE*> &FACE_list );
-   //- Find the FACE in FACE_list that overlaps with FACE_ptr.  Returns
-   //- NULL if no overlap FACE found.
-
-   CubitStatus make_surf_normals_consistent( BODY *BODY_ptr, 
-                                             FACE *seed_FACE = NULL );
-   //- Make the shell normals in the given sheet BODY consistent.  The optional
-   //- seed FACE must be part of the BODY.  If none given, get_seed_FACE (see
-   //- below) is used to select a seed FACE.
-
-   CubitStatus append_neighbors( DLIList<FACE*> &FACE_list );
-   //- Helper function for make_shell_normals_consistent
-
-   FACE *get_seed_FACE( DLIList<FACE*> &FACE_list );
-   //- Get a seed FACE from the given list of FACEs.  Only a seed FACE without
-   //- a named "tweak" attribute on it will be returned.  Also, it may not be
-   //- of advantage, but we try to find a FACE that is not of type CONE, TORUS
-   //- or SPHERE.  If that is not possible, we just return the first FACE in
-   //- the list with no "tweak" attribute on it.
-   
-   CubitStatus draw_tweak_preview_omt( BODY *BODY_ptr, CubitBoolean flush,
-                                       DLIList<AcisBridge*> *prev_ab_list = NULL );
-   //- Draw the preview EDGEs for tweak offset, move and target, for solid and
-   //- sheetbodies.  The function works by finding EDGEs or FACEs without Cubit
-   //- owner attributes on them and drawing those EDGEs as well as the EDGEs
-   //- attached to them.  The "prev_ab_list" may be needed for special cases
-   //- where the target is on the BODY itself.  I recommend always sending in
-   //- the sources and target entities in this list.
-
-   CubitStatus tag_tweak_remove_FACEs_for_preview( BODY *BODY_ptr, 
-                                            DLIList<FACE*> &remove_FACE_list );
-   //- Add an attribute ("tweak_preview") to the required FACEs for a tweak
-   //- remove.  For the preview we draw the EDGEs on the surviving FACEs
-   //- adjoining those that are removed.  Input is the copied BODY, along with
-   //- the FACEs being removed.
-
-   CubitStatus tag_tweak_remove_FACEs_for_preview( BODY *BODY_ptr, 
-                                            DLIList<EDGE*> &remove_EDGE_list );
-   //- Add an attribute ("tweak_preview") to the required FACEs for a tweak
-   //- remove.  For the preview we draw the EDGEs on the surviving FACEs
-   //- adjoining the EDGEs that are removed.  Input is the copied BODY, along 
-   //- with the EDGEs being removed.
-
-   CubitStatus draw_tweak_preview_tagged_FACEs( BODY *BODY_ptr, 
-                                                CubitBoolean flush );
-   //- Draw EDGEs on FACEs with the "tweak_preview" attribute on them.
-
+protected:
    static AcisTweakTool* instance_;
    AcisQueryEngine *AQE;  // For convenience
    AcisModifyEngine *AME; // For convenience
+   CubitBoolean silent;   // True if no output should be made from *certain*
+                          // functions (PRINT_ERROR, etc.) - see above
 };
 
+inline CubitBoolean AcisTweakTool::set_silent( CubitBoolean flg )
+{ 
+  CubitBoolean old_flg = silent;
+  silent = flg; 
+  return old_flg; 
+}
+
 #endif

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -19,26 +19,6 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "constrct/kernapi/api/cstrapi.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#include "kernel/kerndata/top/lump.hxx"
-#include "kernel/kerndata/top/shell.hxx"
-#include "kernel/kerndata/top/face.hxx"
-#include "kernel/kerndata/transent/transent.hxx"
-#include "kernel/kerndata/geom/transfrm.hxx"
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "baseutil/vector/vector.hxx"
-#include "baseutil/vector/transf.hxx"
-#include "baseutil/vector/box.hxx"
-#include "operator/kernapi/api/operapi.hxx"
-#include "kernel/kernutil/tensor/tensor.hxx"
-#include "intersct/kernapi/api/ptcont.hxx"
-
-#else
 #include "cstrapi.hxx"
 #include "body.hxx"
 #include "lump.hxx"
@@ -57,9 +37,6 @@
 #include "warp_api.hxx"
 #include "tensor.hxx"
 #include "ptcont.hxx"
-#include "insanity_list.hxx"
-#include "err_ent.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********
@@ -72,22 +49,13 @@
 
 #include "BodyACIS.hpp"
 #include "BodySM.hpp"
-#include "Lump.hpp"
 #include "Body.hpp"
 
 #include "GeometryQueryTool.hpp"
 #include "AcisQueryEngine.hpp"
+#include "AcisToolUtil.hpp"
 #include "CubitSimpleAttrib.hpp"
 
-#include "CubitUtil.hpp"
-#include "RefVertex.hpp"
-#include "RefEdge.hpp"
-#include "CoEdge.hpp"
-#include "Loop.hpp"
-#include "RefFace.hpp"
-#include "Shell.hpp"
-#include "RefVolume.hpp"
-
 // ********** END CUBIT INCLUDES           **********
 
 // ********** BEGIN STATIC DECLARATIONS    **********
@@ -358,11 +326,11 @@
 // Creation Date : 3/6/98
 //-------------------------------------------------------------------------
 
-int BodyACIS::validate( const CubitString &user_name,
+int BodyACIS::validate( const CubitString &entity_name,
                         DLIList <TopologyEntity*> &bad_entities)
 {
   insanity_list *entity_list = NULL;
-  outcome result = api_check_entity (get_BODY_ptr(), entity_list );
+  outcome result = api_check_entity(get_BODY_ptr(), entity_list );
 
   if ( result.ok() && entity_list == NULL )
   {
@@ -375,10 +343,10 @@
   
   if ( entity_list )
   {
-    convert_entity_list( entity_list, bad_entities );
-    show_bad_geom( bad_entities, user_name );
+    AcisToolUtil::convert_entity_list( entity_list, bad_entities );
+    AcisToolUtil::show_bad_geom( bad_entities, entity_name );
     PRINT_ERROR("with '%s' in the ACIS geometry.\n",
-                user_name.c_str());
+                entity_name.c_str());
   }
 
   else
@@ -527,185 +495,8 @@
 
 // ********** BEGIN PRIVATE FUNCTIONS      **********
 
-void BodyACIS::convert_entity_list( insanity_list *ent_list,
-                                    DLIList <TopologyEntity*> &topo_entity_list)
-{
-  int i;
-  if( ent_list->count() )
-  {
-    insanity_list *tmp_list = ent_list;
-    for(; tmp_list; tmp_list = tmp_list->next() )
-    {
-      insanity_data *error_data = tmp_list->data();
-      ENTITY *bad_ent = error_data->get_ent();
-      ENTITY_LIST bad_ents;
-      if(bad_ent->identity() == ERROR_ENTITY_TYPE )
-      {
-        ERROR_ENTITY *error_ent = (ERROR_ENTITY*)bad_ent;
-        bad_ents.add( error_ent->get_owner(0) ); 
-        bad_ents.add( error_ent->get_owner(1) ); 
-      }
-      else
-        bad_ents.add( bad_ent );
-      
-      bad_ents.init();
-
-      PRINT_INFO("%s: ", error_data->get_message() );
-
-      while( (bad_ent = bad_ents.next()) != NULL )
-      {
-        TopologyEntity* te_ptr = NULL;
-        te_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity( bad_ent );
-        if( te_ptr )
-        {
-          RefEntity *ref_ent = CAST_TO( te_ptr, RefEntity );
-          topo_entity_list.append_unique(te_ptr);
-          if( ref_ent )
-            PRINT_INFO(" %s %d", ref_ent->class_name(), ref_ent->id() );
-        }
-        else
-          PRINT_INFO("%s",bad_ent->type_name() );
-      }
-      PRINT_INFO("\n");
-    }
-  }
-}
-
  
-CubitStatus BodyACIS::show_bad_geom(DLIList <TopologyEntity*> &ent_list,
-                                    const CubitString &user_name)
-{
-  DLIList<RefVertex*> vertex_list;
-  DLIList<RefEdge*> edge_list;
-  DLIList<RefEdge*> curve_coedge_list;
-  DLIList<CoEdge*> coedge_list;
-  DLIList<Loop*> loop_list;
-  DLIList<RefFace*> face_list;
-  DLIList<Shell*> shell_list;
-  DLIList<RefVolume*> volume_list;
-  int i;
 
-  // We need an encapsulated class to handle this sort of thing...
-  for (i=0;i<ent_list.size();i++)
-  {
-    TopologyEntity* TE_ptr = ent_list.get_and_step();
-    RefVertex* ref_vertex;
-    RefEdge* ref_edge;
-    CoEdge* co_edge;
-    Loop* loop;
-    RefFace* face;
-    Shell* shell;
-    RefVolume* volume;
-
-    if( (ref_vertex = CAST_TO( TE_ptr, RefVertex ) ) != NULL )
-      vertex_list.append_unique(ref_vertex);
-    else if( (ref_edge = CAST_TO( TE_ptr, RefEdge ) ) != NULL )
-      edge_list.append_unique(ref_edge);
-    else if( (co_edge = CAST_TO( TE_ptr, CoEdge ) ) != NULL )
-      coedge_list.append_unique(co_edge);
-    else if( (loop = CAST_TO( TE_ptr, Loop ) ) != NULL )
-      loop_list.append_unique(loop);
-    else if( (face = CAST_TO( TE_ptr, RefFace ) ) != NULL )
-      face_list.append_unique(face);
-    else if( (shell = CAST_TO( TE_ptr, Shell ) ) != NULL )
-      shell_list.append_unique(shell);
-    else if( (volume = CAST_TO( TE_ptr, RefVolume ) ) != NULL )
-      volume_list.append_unique(volume);
-  }
-
-  char pre[100];
-
-  if( vertex_list.size() )
-  {
-    sprintf( pre, "Found %d bad vertices in %s. The vertices: ", vertex_list.size(),
-      user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( vertex_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-
-  if( edge_list.size() )
-  {
-    sprintf( pre, "Found %d bad curves in %s. The curves: ", edge_list.size(), 
-      user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( edge_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-
-  for( i=0; i<coedge_list.size(); i++ )
-  {
-    RefEdge* ref_edge_ptr = coedge_list.get_and_step()->get_ref_edge_ptr();
-    curve_coedge_list.append_unique( ref_edge_ptr );
-  }
-  if( coedge_list.size() )
-  {
-    sprintf( pre, "Found %d bad coedges in %s. The curves: ", coedge_list.size(), 
-      user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( curve_coedge_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-
-  // LOOPS
-  Loop* loop_ptr;
-  DLIList<RefEdge*> curve_loop_list;
-  for( i=0; i<curve_loop_list.size(); i++ )
-  {
-    loop_ptr = loop_list.get_and_step();
-    DLIList<RefEdge*> tmp_curve_list;
-    loop_ptr->ordered_ref_edges( tmp_curve_list );
-    curve_loop_list.merge_unique( tmp_curve_list );
-  }
-  curve_loop_list.reset();
-  if( curve_loop_list.size() )
-  {
-    sprintf( pre, "Found %d bad loops in %s. The curves: ", loop_list.size(), user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( curve_loop_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-
-  // SURFACES
-  if( face_list.size() )
-  {
-    sprintf( pre, "Found %d bad surfaces in %s. The surfaces: ", face_list.size(), user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( face_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-
-  // SHELLS
-  Shell* shell_ptr;
-  DLIList<RefFace*> face_shell_list;
-  for( i=0; i<shell_list.size(); i++ )
-  {
-    shell_ptr = shell_list.get_and_step();
-    DLIList<RefFace*> tmp_surface_list;
-    shell_ptr->ref_faces( tmp_surface_list );
-    face_shell_list.merge_unique( tmp_surface_list );
-  }
-  if( face_shell_list.size() )
-  {
-    sprintf( pre, "Found %d bad shells in %s. The surfaces: ", shell_list.size(), user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( face_shell_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-
-  // LUMPS
-  if( volume_list.size() )
-  {
-    sprintf( pre, "Found %d bad volumes in %s. The volumes: ", volume_list.size(), user_name.c_str() );
-    DLIList<CubitEntity*> cubit_list;
-    CAST_LIST( volume_list, cubit_list, CubitEntity );
-    CubitUtil::list_entity_ids( pre, cubit_list );
-  }
-  
-  return CUBIT_SUCCESS;
-}
-
-
 // ********** END PRIVATE FUNCTIONS        **********
 
 // ********** BEGIN HELPER CLASSES         **********

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/BodyACIS.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -19,13 +19,8 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "baseutil/vector/transf.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#else
 #include "transf.hxx"
 #include "body.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********
@@ -157,18 +152,6 @@
     //- the BODY to "absorb" the transformation.
 #endif
 
-
-  CubitStatus show_bad_geom( DLIList <TopologyEntity*> &ent_list, 
-                             const CubitString &user_name);
-  // This was put in only to display bad geometry from a validate.  Needs to 
-  // be encapsulated in another class...
-
-  void convert_entity_list( insanity_list *ent_list,
-                            DLIList <TopologyEntity*> &topology_entities);
-    // Given the acis entities, gets the corrisponding topology entities in
-    // cubit by which they are represented.
-  
-
 };
 
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/CMakeLists.txt
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/CMakeLists.txt	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/CMakeLists.txt	2010-01-27 02:15:23 UTC (rev 3496)
@@ -1,19 +1,24 @@
 
 PROJECT(cubit_acis)
 
+OPTION(CGM_ACIS_USE_TWEAK "my docs" OFF)
+
 SET(ACIS_SRCS
     AcisBridge.cpp
     AcisEdgeTool.cpp
     AcisFacetManager.cpp
     AcisFeatureEngine.cpp
     AcisHealerTool.cpp
+    AcisHistory.cpp
     AcisModifyEngine.cpp
     AcisQueryEngine.cpp
     AcisSurfaceTool.cpp
     AcisToolUtil.cpp
     AcisTweakTool.cpp
+    AcisTopologyTool.cpp
     AcisDrawTool.cpp
     attrib_cubit_owner.cpp
+    attrib_history.cpp
     attrib_snl.cpp
     attrib_snl_simple.cpp
     BodyACIS.cpp
@@ -26,6 +31,10 @@
     SurfaceACIS.cpp
     )
 
+IF(CGM_ACIS_USE_TWEAK)
+  SET(ACIS_SRCS ${ACIS_SRCS} ${cubit_acis_SOURCE_DIR}/CAT/AcisTweakToolCAT.cpp)
+ENDIF(CGM_ACIS_USE_TWEAK)
+
 # for convenience, include this in the project
 IF(WIN32)
   FOREACH(var ${ACIS_SRCS})
@@ -37,36 +46,54 @@
   ENDIF(NOT ${CMAKE_GENERATOR} MATCHES "NMake")
 ENDIF(WIN32)
 
-
 INCLUDE(${cubit_acis_SOURCE_DIR}/UseACIS.cmake)
 
+IF(CUBIT_GEOM_EXTERNAL_GTCATTRIB)
+  INCLUDE_DIRECTORIES(${gtcAttrib_SOURCE_DIR}/incl)
+ELSE(CUBIT_GEOM_EXTERNAL_GTCATTRIB)
+  SUBDIRS(gtcAttrib)
+  INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/gtcAttrib/incl)
+ENDIF(CUBIT_GEOM_EXTERNAL_GTCATTRIB)
+
 # add acis includes to current project
-INCLUDE_DIRECTORIES(${ACIS_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/gtcAttrib/incl)
+INCLUDE_DIRECTORIES(${ACIS_INCLUDE_DIR})
 
+IF(CGM_ACIS_USE_TWEAK)
+  INCLUDE_DIRECTORIES(${cubit_SOURCE_DIR}/geom/ACIS/CAT)
+ENDIF(CGM_ACIS_USE_TWEAK)
+
+IF(CMAKE_COMPILER_IS_GNUCC)
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated")
+ENDIF(CMAKE_COMPILER_IS_GNUCC)
+
 # build cubit acis library from sources
 ADD_LIBRARY(cubit_ACIS ${ACIS_SRCS} ${ACIS_HEADERS} ${EXTRA_ACIS_SRCS})
+TARGET_LINK_LIBRARIES(cubit_ACIS ${ACIS_LIBS})
 
-SUBDIRS(gtcAttrib)
+# install ACIS libs 
+IF(WIN32)
+  STRING(REGEX REPLACE "/lib/" "/bin/" ACIS_INSTALL_LIBS "${ACIS_RELEASE_LIBS}")
+  STRING(REGEX REPLACE "/lib/" "/bin/" ACIS_INSTALL_DEBUG_LIBS "${ACIS_DEBUG_LIBS}")
+  STRING(REGEX REPLACE "\\.lib" ".dll" ACIS_INSTALL_LIBS "${ACIS_INSTALL_LIBS}")
+  STRING(REGEX REPLACE "\\.lib" ".dll" ACIS_INSTALL_DEBUG_LIBS "${ACIS_INSTALL_DEBUG_LIBS}")
+ELSE(WIN32)
+  SET(ACIS_INSTALL_LIBS ${ACIS_RELEASE_LIBS})
+  SET(ACIS_INSTALL_DEBUG_LIBS ${ACIS_DEBUG_LIBS})
+ENDIF(WIN32)
 
-IF(UNIX)
-ADD_CUSTOM_TARGET(switch_acis ${CMAKE_MAKE_PROGRAM} clean)
-ENDIF(UNIX)
-
-# install ACIS libs 
-SET(CMAKE_INSTALL_3RD_PARTY_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH "Install prefix for 3rd party libraries")
 SET(CMAKE_INSTALL_BINARY_DIR "bin" CACHE PATH "Install directory for binaries")
-IF(CMAKE_INSTALL_3RD_PARTY_PREFIX)
-  SET(ACIS_INSTALL_PREFIX ${CMAKE_INSTALL_3RD_PARTY_PREFIX}/${CMAKE_INSTALL_BINARY_DIR})
-  IF(WIN32)
-    STRING(REGEX REPLACE "/lib/" "/bin/" ACIS_SHARED_LIBRARY_DIR ${ACIS_LIBRARY_DIR})
-    STRING(REGEX REPLACE "/lib/" "/bin/" ACIS_SHARED_LIBRARY_DIR_DEBUG ${ACIS_LIBRARY_DIR_DEBUG})
-    SET(ACIS_INSTALL_LIBS ${ACIS_RELEASE_LIBS})
-    SET(ACIS_INSTALL_LIBS_DEBUG ${ACIS_DEBUG_LIBS})
-  ELSE(WIN32)
-    SET(ACIS_SHARED_LIBRARY_DIR ${ACIS_LIBRARY_DIR})
-    SET(ACIS_INSTALL_LIBS ${ACIS_LIBS})
-  ENDIF(WIN32)
-  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/InstallACIS.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/InstallACIS.cmake @ONLY)
-  SET_TARGET_PROPERTIES(cubit_ACIS PROPERTIES POST_INSTALL_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/InstallACIS.cmake)
-ENDIF(CMAKE_INSTALL_3RD_PARTY_PREFIX)
+IF(CMAKE_CONFIGURATION_TYPES)
+  INSTALL(FILES ${ACIS_INSTALL_LIBS} 
+          DESTINATION ${CMAKE_INSTALL_BINARY_DIR}
+          CONFIGURATIONS Release
+          COMPONENT Runtime)
+  INSTALL(FILES ${ACIS_INSTALL_DEBUG_LIBS} 
+          DESTINATION ${CMAKE_INSTALL_BINARY_DIR}
+          CONFIGURATIONS Debug
+          COMPONENT Runtime)
+ELSE(CMAKE_CONFIGURATION_TYPES)
+  INSTALL(FILES ${ACIS_INSTALL_LIBS} 
+          DESTINATION ${CMAKE_INSTALL_BINARY_DIR}
+          COMPONENT Runtime)
+ENDIF(CMAKE_CONFIGURATION_TYPES)
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/CoEdgeACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/CoEdgeACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/CoEdgeACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -16,19 +16,11 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "kernel/kerndata/top/coedge.hxx"
-#include "kernel/kerndata/top/loop.hxx"
-#include "kernel/kerndata/top/edge.hxx"
-#else
 #include "kernapi.hxx"
 #include "datamsc.hxx"
 #include "coedge.hxx"
 #include "loop.hxx"
 #include "edge.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -17,24 +17,6 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/acis.hxx"
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "kernel/kerndata/data/entity.hxx"
-#include "kernel/kerndata/top/edge.hxx"
-#include "kernel/kerndata/top/vertex.hxx"
-#include "kernel/kerndata/geom/point.hxx"
-#include "kernel/kerndata/geom/allcurve.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "kernel/kerndata/top/alltop.hxx" // Required for is_TEDGE
-#include "kernel/kernint/d3_chk/chk_stat.hxx"
-#include "intersct/sg_husk/query/sgquery.hxx"
-#include "intersct/sg_husk/query/sgquertn.hxx"
-#include "baseutil/vector/position.hxx"
-#include "baseutil/vector/interval.hxx"
-#else
 #include "acis.hxx"
 #include "api.hxx" 
 #include "kernapi.hxx" 
@@ -51,7 +33,6 @@
 #include "sgquertn.hxx"
 #include "position.hxx"
 #include "interval.hxx"
-#endif
 
 /*
 //Added for G1_discontinous(..)

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/CurveACIS.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -19,13 +19,8 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kerndata/top/edge.hxx"
-#include "kernel/kerndata/geom/allcurve.hxx"
-#else
 #include "edge.hxx"
 #include "allcurve.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -17,17 +17,11 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "kernel/kerndata/top/loop.hxx"
-#include "kernel/kerndata/top/coedge.hxx"
-#else
 #include "kernapi.hxx"
 #include "datamsc.hxx"
 #include "loop.hxx"
 #include "coedge.hxx"
-#endif
+#include "cstrapi.hxx"  // for api_loop_external()
 
 #include "attrib_cubit_owner.hpp"
 #include "attrib_snl_simple.hpp"
@@ -150,6 +144,33 @@
   AcisBridge::remove_all_simple_attribute_virt();
 }
 
+LoopType LoopACIS::loop_type()
+{
+    LOOP* cur_loop = get_LOOP_ptr();
+    ::loop_type type;
+    int d[2];
+    outcome result = api_loop_type(cur_loop, type, d);
+    if (result.ok())
+    {
+      switch(type)
+      {
+        case loop_unknown:
+          return LOOP_TYPE_UNKNOWN;
+        case loop_periphery:
+          return LOOP_TYPE_EXTERNAL;
+        case loop_hole:
+          return LOOP_TYPE_HOLE;
+        case loop_u_separation:
+          return LOOP_TYPE_V_PERIODIC;
+        case loop_v_separation:
+          return LOOP_TYPE_U_PERIODIC;
+        case loop_uv_separation:
+          return LOOP_TYPE_UNKNOWN;
+      }
+    }
+    return LOOP_TYPE_UNKNOWN;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : The purpose of this function is to get the  
 //                 attributes attached to this geometry entity. The name is 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/LoopACIS.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -54,6 +54,8 @@
     //- This function returns a pointer to the geometric modeling engine
     //- associated with the object.
   
+  virtual LoopType loop_type() ;
+
   virtual void append_simple_attribute_virt(CubitSimpleAttrib*);
     //R void
     //I 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -17,20 +17,6 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "constrct/kernapi/api/cstrapi.hxx"
-#include "kernel/kernutil/tensor/tensor.hxx"
-#include "kernel/kerndata/top/lump.hxx"
-#include "kernel/kerndata/top/body.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "baseutil/vector/position.hxx"
-#include "baseutil/vector/unitvec.hxx"
-#include "baseutil/vector/box.hxx"
-
-#else
 #include "kernapi.hxx"
 #include "datamsc.hxx"
 #include "cstrapi.hxx"
@@ -43,7 +29,6 @@
 #include "unitvec.hxx"
 #include "box.hxx"
 #include "mprop.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********
@@ -51,6 +36,7 @@
 #include "attrib_snl_simple.hpp"
 
 #include "AcisQueryEngine.hpp"
+#include "AcisToolUtil.hpp"
 #include "LumpACIS.hpp"
 #include "CastTo.hpp"
 #include "CubitString.hpp"
@@ -292,7 +278,60 @@
   return CUBIT_SUCCESS;
 }
 
+CubitStatus LumpACIS::mass_properties( CubitVector principal_axes[3], 
+                                       CubitVector &principal_moments,
+                                       CubitVector &centroid, 
+                                       double &volume )
+{
+    // Create a temporary ACIS BODY using a temporary copy of this LUMP
+    // and ask ACIS to compute the volume of that BODY.  The reason this
+    // needs to be done is that ACIS does not provide a function to
+    // compute the volume of a LUMP. This is wrapped with an API_NOP macro
+    // so that ACIS rolls back to destroy the new temporary objects
+    // created during this operation.
+  API_NOP_BEGIN; // This "prevents" any changes from occurring to the BODY
+    // upto the corresponding API_NOP_END
+  
+    // Make a BODY from this LUMP. Note that this modifies the input LUMP
+    // which is one of the reasons for having the API_NOP macros.
+  get_LUMP_ptr()->set_next(( LUMP*)NULL );
+  BODY* BODYPtr = new BODY(get_LUMP_ptr()); 
 
+  mass_props volume_props;
+  mass_props_options volume_props_options;
+  volume_props_options.set_level(VOLUME_CENTROID_AND_INERTIA);
+
+  outcome result = api_body_mass_props( BODYPtr, volume_props, &volume_props_options );
+  if( !result.ok() )
+    return CUBIT_FAILURE;
+
+  volume = volume_props.get_volume();
+  SPAposition tmp_centroid = volume_props.get_centroid();
+  centroid.set( tmp_centroid.x(), tmp_centroid.y(), tmp_centroid.z() );
+
+  // get the principal axes out of the results
+  SPAunit_vector p_axes[3];
+  volume_props.get_p_axes(p_axes);
+
+  // load the axes into the CubitVector array
+  SPAunit_vector x_axis = p_axes[0];
+  SPAunit_vector y_axis = p_axes[1];
+  SPAunit_vector z_axis = p_axes[2];
+  principal_axes[0].set(x_axis.x(), x_axis.y(), x_axis.z());
+  principal_axes[1].set(y_axis.x(), y_axis.y(), y_axis.z());
+  principal_axes[2].set(z_axis.x(), z_axis.y(), z_axis.z());
+
+  // get the principal moments of inertia
+  double p_moments[3];
+  volume_props.get_p_moments(p_moments);
+  principal_moments.set(p_moments[0], p_moments[1], p_moments[2]);
+
+  API_NOP_END;
+
+  return CUBIT_SUCCESS;
+}
+
+
 //-------------------------------------------------------------------------
 // Purpose       : Checks the validity of this lump
 //
@@ -305,10 +344,9 @@
 int LumpACIS::validate(const CubitString &entity_name,
                        DLIList <TopologyEntity*> &bad_entities)
 {
-  ENTITY_LIST entity_list;
-  FILE *file_ptr = NULL;
-  outcome result = api_check_entity(get_LUMP_ptr(), &entity_list, file_ptr);
-  if ( result.ok() && entity_list.count() == 0 )
+  insanity_list *entity_list = NULL;
+  outcome result = api_check_entity(get_LUMP_ptr(), entity_list );
+  if ( result.ok() && entity_list == NULL )
   {
     return 0;
   }
@@ -317,9 +355,10 @@
     get_acis_query_engine()->ACIS_API_error(result);
   }
   
-  if ( entity_list.count() )
+  if ( entity_list )
   {
-    convert_entity_list( entity_list, bad_entities );
+    AcisToolUtil::convert_entity_list( entity_list, bad_entities );
+    AcisToolUtil::show_bad_geom( bad_entities, entity_name );
     PRINT_ERROR("with '%s' in the ACIS geometry.\n",
                 entity_name.c_str());
   }
@@ -329,20 +368,6 @@
   return 1;
 }
 
-void LumpACIS::convert_entity_list( ENTITY_LIST &ent_list,
-                                    DLIList <TopologyEntity*> &topo_entity_list)
-{
-  TopologyEntity* te_ptr = NULL;
-  int i;
-  for (i=0;i<ent_list.count();i++)
-  {
-    te_ptr = ATTRIB_CUBIT_OWNER::get_topology_entity(ent_list[i]);
-    if ( te_ptr != NULL )
-      topo_entity_list.append(te_ptr);
-  }
-}
-
-
 /*
 void LumpACIS::bodysms(DLIList<BodySM*> &bodies) 
 {

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/LumpACIS.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -118,6 +118,16 @@
     //- 1.0 for Point
 
   virtual CubitStatus mass_properties( CubitVector &centroid, double &volume );
+  virtual CubitStatus mass_properties( CubitVector principal_axes[3], 
+                                       CubitVector &principal_moments, 
+                                       CubitVector &centroid, 
+                                       double &volume );
+    //R CubitStatus - CUBIT_SUCCESS/CUBIT_FAILURE
+    //R - centroid of the lump
+    //R - volume of the lump
+    //R - principal axes of the lump
+    //R - principal moments of inertia of the lump
+    //- Calculated using standard kernel mass property functions
 
   virtual int validate(const CubitString &entity_name,
                        DLIList <TopologyEntity*> &bad_entities);
@@ -129,14 +139,7 @@
   
   void get_parents_virt( DLIList<TopologyBridge*>& parents );
   void get_children_virt( DLIList<TopologyBridge*>& children );
-
-protected: 
   
-private:
-  void convert_entity_list(ENTITY_LIST &ent_list,
-                           DLIList <TopologyEntity*> &topo_entity_list);
-    //- From the ent_list, it populates the topo_entity_list with the
-    //- related cubit entities from their corrisponding acis entity.
 } ;
 
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/Makefile.am
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/Makefile.am	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/Makefile.am	2010-01-27 02:15:23 UTC (rev 3496)
@@ -24,13 +24,17 @@
     AcisFacetManager.cpp \
     AcisFeatureEngine.cpp \
     AcisHealerTool.cpp \
+    AcisHistory.cpp \
     AcisModifyEngine.cpp \
     AcisQueryEngine.cpp \
     AcisSurfaceTool.cpp \
     AcisToolUtil.cpp \
+    AcisTopologyTool.cpp \
     AcisTweakTool.cpp \
     AcisDrawTool.cpp \
     attrib_cubit_owner.cpp \
+    attrib_history.cpp \
+    attrib_history.hpp \
     attrib_snl.cpp \
     attrib_snl_simple.cpp \
     BodyACIS.cpp \
@@ -55,10 +59,12 @@
     AcisFacetManager.hpp \
     AcisFeatureEngine.hpp \
     AcisHealerTool.hpp \
+    AcisHistory.hpp \
     AcisModifyEngine.hpp \
     AcisQueryEngine.hpp \
     AcisSurfaceTool.hpp \
     AcisToolUtil.hpp \
+    AcisTopologyTool.hpp \
     AcisTweakTool.hpp \
     AcisTypes.h \
     BodyACIS.hpp \

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/PointACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/PointACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/PointACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -17,17 +17,10 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "kernel/kerndata/top/vertex.hxx"
-#include "kernel/kerndata/geom/point.hxx"
-#else
 #include "kernapi.hxx"
 #include "datamsc.hxx"
 #include "vertex.hxx"
 #include "point.hxx"
-#endif
 
 #include "attrib_cubit_owner.hpp"
 #include "attrib_snl_simple.hpp"

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/ShellACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/ShellACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/ShellACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -17,17 +17,10 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "kernel/kerndata/top/shell.hxx"
-#include "kernel/kerndata/top/lump.hxx"
-#else
 #include "kernapi.hxx"
 #include "datamsc.hxx"
 #include "shell.hxx"
 #include "lump.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -16,30 +16,8 @@
 // ********** END STANDARD INCLUDES        **********
 
 // ********** BEGIN ACIS INCLUDES          **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/acis.hxx"
-#include "kernel/kernapi/api/kernapi.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "constrct/kernapi/api/cstrapi.hxx"
-#include "intersct/kernapi/api/intrapi.hxx"
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kerndata/top/face.hxx"
-#include "kernel/kerndata/top/alltop.hxx"
-#include "kernel/kerndata/geom/allsurf.hxx"
-#include "kernel/kerndata/lists/lists.hxx"
-#include "kernel/kerngeom/surface/surdef.hxx"
-#include "kernel/sg_husk/query/q_wire.hxx"
-#include "kernel/sg_husk/face/faceutil.hxx"
-#include "kernel/kernint/d3_chk/chk_stat.hxx"
-#include "intersct/kerndata/ptinface/ptinface.hxx"
-#include "baseutil/vector/position.hxx"
-#include "baseutil/vector/param.hxx"
-#include "baseutil/vector/vector.hxx"
-#include "baseutil/vector/unitvec.hxx"
-#include "baseutil/vector/interval.hxx"
-
-#else
 #include "acis.hxx"
+#include "acistype.hxx"
 #include "kernapi.hxx"
 #include "datamsc.hxx"
 #include "cstrapi.hxx"
@@ -61,7 +39,6 @@
 #include "getbox.hxx"
 #include "faceutil.hxx"
 #include "raytest.hxx"
-#endif
 // ********** END ACIS INCLUDES            **********
 
 // ********** BEGIN CUBIT INCLUDES         **********
@@ -212,6 +189,28 @@
    return get_acis_query_engine();   
 }                 
 
+// Get the normalized surface parameter direction associated with
+// the passed in world space direction and position on surface.
+void SurfaceACIS::param_dir(CubitVector &unit_dir_in_world_space,
+        CubitVector &pos_on_surf, double &du, double &dv)
+{
+  du = 0.0;
+  dv = 0.0;
+
+  FACE *FACE_ptr = this->get_FACE_ptr();
+  if(FACE_ptr)
+  {
+    SPAposition foot, pos(pos_on_surf.x(), pos_on_surf.y(), pos_on_surf.z());
+    SPApar_pos uv;
+    SPAunit_vector unit_dir(unit_dir_in_world_space.x(), unit_dir_in_world_space.y(), 
+      unit_dir_in_world_space.z());
+    FACE_ptr->geometry()->equation().point_perp(pos, foot, *(SPApar_pos*)NULL_REF, uv);
+    SPApar_dir surf_dir = FACE_ptr->geometry()->equation().param_dir(unit_dir, uv);
+    du = surf_dir.du;
+    dv = surf_dir.dv;
+  }
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Get the bounding box of the object.
 //
@@ -680,7 +679,7 @@
 {
     // Get the number of LOOPs that bound a FACE of this object.
   int num_loops = number_of_LOOPs();
-  
+
   if ( num_loops == 2 &&
        ( this->geometry_type() == CONE_SURFACE_TYPE   ||
          this->geometry_type() == SPHERE_SURFACE_TYPE ||
@@ -1000,28 +999,18 @@
     // surface
   CubitBoolean alls_well = CUBIT_TRUE;
 
-//  SPApar_box face_range;
+  SPApar_box face_range;
 
-//   API_BEGIN
-//     sg_get_face_par_box( FACE_ptr, face_range );   
-//   API_END
+   API_BEGIN
+     sg_get_face_par_box( FACE_ptr, face_range );   
+   API_END
 
-//     // Make sure it is bounded and return the appropriate values
-//   if ( face_range.u_range().bounded() )
-//   {
-//     lower_bound = face_range.u_range().start_pt();
-//     upper_bound = face_range.u_range().end_pt();
-//   }
-  SPAbox *bbox = FACE_ptr->bound();
-  SPAinterval u_face_range;
-  u_face_range = FACE_ptr->geometry()->equation().param_range_u(*bbox);
-// Make sure it is bounded and return the appropriate values
-  if ( u_face_range.bounded() )
-  {
-    lower_bound = u_face_range.start_pt();
-    upper_bound = u_face_range.end_pt();
-  }
-  
+     // Make sure it is bounded and return the appropriate values
+   if ( face_range.u_range().bounded() )
+   {
+     lower_bound = face_range.u_range().start_pt();
+     upper_bound = face_range.u_range().end_pt();
+   }
     // The parameter range is unbounded in one or both directions.
   else
   {
@@ -1066,28 +1055,18 @@
     // surface
   CubitBoolean alls_well = CUBIT_TRUE;
 
-//   SPApar_box face_range;
+   SPApar_box face_range;
 
-//   API_BEGIN
-//     sg_get_face_par_box( FACE_ptr, face_range );   
-//   API_END
+   API_BEGIN
+     sg_get_face_par_box( FACE_ptr, face_range );   
+   API_END
 
-//     // Make sure it is bounded and return the appropriate values
-//   if ( face_range.v_range().bounded() )
-//   {
-//     lower_bound = face_range.v_range().start_pt();
-//     upper_bound = face_range.v_range().end_pt();
-//   }
-  SPAbox *bbox = FACE_ptr->bound();
-  SPAinterval v_face_range;
-  v_face_range = FACE_ptr->geometry()->equation().param_range_v(*bbox);
-// Make sure it is bounded and return the appropriate values
-  if ( v_face_range.bounded() )
-  {
-    lower_bound = v_face_range.start_pt();
-    upper_bound = v_face_range.end_pt();
-  }
-  
+     // Make sure it is bounded and return the appropriate values
+   if ( face_range.v_range().bounded() )
+   {
+     lower_bound = face_range.v_range().start_pt();
+     upper_bound = face_range.v_range().end_pt();
+   }
   else
   {
     alls_well = CUBIT_FALSE;
@@ -1157,6 +1136,36 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : Returns a true if the Surface is a cylinder. This value is
+//                 determined by ACIS.
+//
+// Special Notes : This code is very ACIS-specific and could change with 
+//                 new versions of ACIS.  There are #defines for the
+//                 various surface type ID's.  These are defined in the 
+//                 header files of each of the specific surface classes
+//                 in ACIS.
+//
+//                 This was not added into the geometry_type because that
+//                 function is widely used to verify quadric surface types.
+//
+// Creator       : KGM
+//
+// Creation Date : 03/26/07
+//-------------------------------------------------------------------------
+GeometryType SurfaceACIS::is_cylindrical()
+{
+  GeometryType local_type = UNDEFINED_SURFACE_TYPE;
+
+    // Get the first FACE associated with this SurfaceACIS object
+  FACE* FACE_ptr = get_FACE_ptr();
+  
+  if (is_cylindrical_face(FACE_ptr))
+    local_type = CYLINDER_SURFACE_TYPE;
+
+  return local_type;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : Returns the area of the Surface
 //
 // Special Notes :
@@ -1241,16 +1250,12 @@
 
    // Let the function figure-out uv coordinates
    point_face_containment pf_rel;
-#if CUBIT_ACIS_VERSION < 1100
-   pf_rel = point_in_face( test_point, FACE_ptr, ftrans );
-#else
    outcome r = api_point_in_face( test_point, FACE_ptr, ftrans, pf_rel );
    if (!r.ok())
    {
      PRINT_ERROR("ACIS api_point_in_face failed.\n");
      return CUBIT_PNT_UNKNOWN;
    }
-#endif
    
    switch( pf_rel )
    {
@@ -1279,16 +1284,12 @@
    
    point_face_containment pf_rel;
    
-#if CUBIT_ACIS_VERSION < 1100
-   pf_rel = point_in_face( test_point, FACE_ptr, ftrans, test_uv);
-#else
    outcome r = api_point_in_face( test_point, FACE_ptr, ftrans, pf_rel, test_uv );
    if (!r.ok())
    {
      PRINT_ERROR("ACIS api_point_in_face failed.\n");
      return CUBIT_PNT_UNKNOWN;
    }
-#endif
    
    switch( pf_rel )
    {
@@ -1317,16 +1318,12 @@
    SPAtransf ftrans;
    
    point_face_containment pf_rel;
-#if CUBIT_ACIS_VERSION < 1100
-   pf_rel = point_in_face( test_point, FACE_ptr, ftrans, test_uv);
-#else
    outcome r = api_point_in_face( test_point, FACE_ptr, ftrans, pf_rel, test_uv );
    if (!r.ok())
    {
      PRINT_ERROR("ACIS api_point_in_face failed.\n");
      return CUBIT_PNT_UNKNOWN;
    }
-#endif
 
    switch( pf_rel )
    {

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/SurfaceACIS.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -83,6 +83,9 @@
   void set_FACE_ptr(FACE* FACE_ptr);
     //- I FACE_ptr - The FACE to be associated with this object.
     //- It replaces any previous FACE.
+
+  virtual void param_dir(CubitVector &unit_dir_in_world_space,
+        CubitVector &pos_on_surf, double &du, double &dv);
   
   virtual void append_simple_attribute_virt(CubitSimpleAttrib*);
     //R void
@@ -384,6 +387,10 @@
     //R GeometryType (enum)
     //R- The enumerated type of the geometric representation
   
+  GeometryType is_cylindrical();
+    //R GeometryType (enum)
+    //R- CYLINDRICAL_SURFACE_TYPE if true else UNDEFINED_SURFACE_TYPE
+
   virtual double measure();
     //R double
     //R- The numeric value of the measure (its units depend on the dimension

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/UseACIS.cmake
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/UseACIS.cmake	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/UseACIS.cmake	2010-01-27 02:15:23 UTC (rev 3496)
@@ -7,15 +7,10 @@
 # ACIS_LIBS, ACIS_DEBUG_LIBS, ACIS_RELEASE_LIBS
 # also automatically add -D definitions for compiling
 
+IF(NOT CUBITROOT)
+  MESSAGE(ERROR "CUBITROOT not set")
+ENDIF(NOT CUBITROOT)
 
-IF(UNIX)
-  SET(CUBITROOT $ENV{CUBIT})
-ELSE(UNIX)
-  SET(CUBITROOT $ENV{CUBITROOT})
-ENDIF(UNIX)
-
-STRING(REGEX REPLACE "\\\\" "/" CUBITROOT "${CUBITROOT}")
-
 # allow override of ACIS_DIR
 IF(NOT MYOWN_ACIS_DIR)
   SET(MYOWN_ACIS_DIR "" CACHE PATH "")
@@ -24,17 +19,22 @@
   SET(ACIS_DIR ${MYOWN_ACIS_DIR})
 ENDIF(MYOWN_ACIS_DIR)
 
+IF(CMAKE_COMPILER_IS_GNUCXX)
+  IF(NOT GNUCXX_VERSION)
+    EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
+      ARGS -dumpversion OUTPUT_VARIABLE output_version)
+    SET(GNUCXX_VERSION ${output_version} CACHE STRING "gcc version")
+  ENDIF(NOT GNUCXX_VERSION)
+ENDIF(CMAKE_COMPILER_IS_GNUCXX)
+
 # if ACIS_DIR isn't set yet, then we'll set the default
 IF(NOT ACIS_DIR)
-  IF(CMAKE_SYSTEM MATCHES "IRIX")
-    SET(ACIS_DIR ${CUBITROOT}/acis/acis14.1)
-  ELSE(CMAKE_SYSTEM MATCHES "IRIX")
-    IF(CMAKE_SYSTEM MATCHES "Darwin")
-      SET(ACIS_DIR ${CUBITROOT}/acis/acis16.3)
-    ELSE(CMAKE_SYSTEM MATCHES "Darwin")
-      SET(ACIS_DIR ${CUBITROOT}/acis/acis16.1)
-    ENDIF(CMAKE_SYSTEM MATCHES "Darwin")
-  ENDIF(CMAKE_SYSTEM MATCHES "IRIX")
+  SET(ACIS_DIR ${CUBITROOT}/acis/acis19.2)
+  IF(CMAKE_SYSTEM MATCHES "Linux")
+    IF(GNUCXX_VERSION MATCHES "^3\\.")
+      SET(ACIS_DIR ${CUBITROOT}/acis/acis17.2)
+    ENDIF(GNUCXX_VERSION MATCHES "^3\\.")
+  ENDIF(CMAKE_SYSTEM MATCHES "Linux")
 ENDIF(NOT ACIS_DIR)
 
 # allow override of acis version
@@ -45,131 +45,215 @@
   SET(ACIS_VERSION ${MYOWN_ACIS_VERSION})
 ENDIF(MYOWN_ACIS_VERSION)
 
-# default to version 1601, 1401 for SGI, 1603 for Mac
+# default to version of acis
 IF(NOT ACIS_VERSION)
-  IF(CMAKE_SYSTEM MATCHES "IRIX")
-    SET(ACIS_VERSION 1401)
-  ELSE(CMAKE_SYSTEM MATCHES "IRIX")
-    IF(CMAKE_SYSTEM MATCHES "Darwin")
-      SET(ACIS_VERSION 1603)
-    ELSE(CMAKE_SYSTEM MATCHES "Darwin")
-      SET(ACIS_VERSION 1601)
-    ENDIF(CMAKE_SYSTEM MATCHES "Darwin")
-  ENDIF(CMAKE_SYSTEM MATCHES "IRIX")
+  SET(ACIS_VERSION 1902)
+  IF(CMAKE_SYSTEM MATCHES "Linux")
+    IF(GNUCXX_VERSION MATCHES "^3\\.")
+      SET(ACIS_VERSION 1702)
+    ENDIF(GNUCXX_VERSION MATCHES "^3\\.")
+  ENDIF(CMAKE_SYSTEM MATCHES "Linux")
 ENDIF(NOT ACIS_VERSION)
 
 
 # set the include directory
 SET (ACIS_INCLUDE_DIR ${ACIS_DIR}/include)
 
-SET(ACIS_LIBS)
+IF(ACIS_VERSION LESS 1900)
+  # acis step interop libraries
+  SET(ACIS_STEP_LIBS acisstep xstep)
+  # acis iges interop libraries
+  SET(ACIS_IGES_LIBS acisiges xiges)
+ELSE(ACIS_VERSION LESS 1900)
+  # acis step interop libraries
+  SET(ACIS_STEP_LIBS xstep)
+  # acis iges interop libraries
+  SET(ACIS_IGES_LIBS xiges)
+ENDIF(ACIS_VERSION LESS 1900)
 
-IF(NOT BUILD_64)
-OPTION(ACIS_STEP "Build with ACIS STEP Translator" ON)
-IF(ACIS_STEP)
-  ADD_DEFINITIONS(-DACIS_STEP_TRANSLATOR)
-  SET(ACIS_LIBS ${ACIS_LIBS} acisstep xstep)
-ENDIF(ACIS_STEP)
-ENDIF(NOT BUILD_64)
+# acis interop libraries
+SET(ACIS_INTEROP_LIBS xacis2k xcore2k SPAXAcisBase SPAXAssemblyRep SPAXDefaultGeometryRep SPAXInterop SPAXBase)
+IF(NOT ACIS_VERSION LESS 1600)
+  SET(ACIS_INTEROP_LIBS ${ACIS_INTEROP_LIBS} SPAXGeometryRepresentation)
+ENDIF(NOT ACIS_VERSION LESS 1600)
+IF(NOT ACIS_VERSION LESS 1900)
+  SET(ACIS_INTEROP_LIBS ${ACIS_INTEROP_LIBS} SPAXAcisKernel icuio38 icuin38 icuuc38 )
+  SET(ACIS_INTEROP_LIBS_EXTRA icudt38)
+ENDIF(NOT ACIS_VERSION LESS 1900)
 
-IF(NOT BUILD_64)
-OPTION(ACIS_IGES "Build with ACIS IGES Translator" ON)
-IF(ACIS_IGES)
-  ADD_DEFINITIONS(-DACIS_IGES_TRANSLATOR)
-  SET(ACIS_LIBS ${ACIS_LIBS} acisiges xiges)
-ENDIF(ACIS_IGES)
-ENDIF(NOT BUILD_64)
-
-#IF(NOT BUILD_64)
-#OPTION(ACIS_HEALER "Build with ACIS Healer" ON)
-##IF(ACIS_HEALER)
-  ADD_DEFINITIONS(-DACIS_HEALER)
-  # hmm  what are the healer libs?
-  #SET(ACIS_LIBS ${ACIS_LIBS} xiges acisiges)
-#ENDIF(ACIS_HEALER)
-#ENDIF(NOT BUILD_64)
-
-
-IF(NOT BUILD_64)
-  IF(ACIS_STEP OR ACIS_IGES)
-    SET(ACIS_LIBS ${ACIS_LIBS} xacis2k xcore2k SPAXAcisBase SPAXAssemblyRep SPAXDefaultGeometryRep SPAXInterop SPAXBase )
-    IF(ACIS_VERSION GREATER 1600)
-      SET(ACIS_LIBS ${ACIS_LIBS} SPAXGeometryRepresentation)
-    ENDIF(ACIS_VERSION GREATER 1600)
-  ENDIF(ACIS_STEP OR ACIS_IGES)
-ENDIF(NOT BUILD_64)
-
-SET(ACIS_LIBS ${ACIS_LIBS}
-              SpaAVis SpaAWarp SpaASurf SpaALops SpaABlend SpaACIS SpaBase )
-
-
+# basic acis libraries
+SET(ACIS_CORE_LIBS SpaAVis SpaAWarp SpaASurf SpaALops SpaABlend SpaAAsm SpaACIS SpaBase )              
+             
 IF(WIN32)
-# .Net acis libs have n in their names
-  IF(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio 6")
+  
+  #add in the license library we need....only on windows
+  SET(ACIS_CORE_LIBS ${ACIS_CORE_LIBS} SpaLicExtBase )
+  SET(ACIS_LIB_EXT ".lib")
+  SET(ACIS_LIB_PREFIX "")
+  SET(ACIS_DEBUG_SUFFIX d)
+  
+  # .Net acis libs have n in their names
+  IF(MSVC70 OR MSVC71)
     SET(ACIS_LIB_SUFFIX n)
     SET(ACIS_DIR_ADD _NET)
-  ENDIF(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio 6")
+  ENDIF(MSVC70 OR MSVC71)
+
+  IF(MSVC80)   
+    SET(ACIS_DIR_ADD _VC8)
+    SET(ACIS_LIB_SUFFIX)
+    IF(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
+      SET(ACIS_DIR_ADD _AMD_64)
+      SET(ACIS_LIB_SUFFIX a)
+    ENDIF(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
+  ENDIF(MSVC80)
   
-  SET(TMP_ACIS_LIB_DIR ${ACIS_DIR}/lib)
+  IF(MSVC90)   
+    SET(ACIS_DIR_ADD _VC9)
+    SET(ACIS_LIB_SUFFIX)
+    IF(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
+      SET(ACIS_DIR_ADD _AMD_64)
+      SET(ACIS_LIB_SUFFIX a)
+    ENDIF(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
+  ENDIF(MSVC90)
+  
+  
   SET(ACIS_LIBRARY_DIR ${ACIS_DIR}/lib/NT${ACIS_DIR_ADD}_DLL)
   SET(ACIS_LIBRARY_DIR_DEBUG ${ACIS_DIR}/lib/NT${ACIS_DIR_ADD}_DLLD)
-  SET(ACIS_DEBUG_LIBS)
-  SET(ACIS_RELEASE_LIBS)
+
+ELSE(WIN32)
   
-  FOREACH(var ${ACIS_LIBS})
-    SET(ACIS_DEBUG_LIBS ${ACIS_DEBUG_LIBS} ${var}${ACIS_LIB_SUFFIX}d)
-             
-    SET(ACIS_RELEASE_LIBS ${ACIS_RELEASE_LIBS} ${var}${ACIS_LIB_SUFFIX})
-  ENDFOREACH(var ${ACIS_LIBS})
-  SET(ACIS_LIBS)
-  FOREACH(var ${ACIS_DEBUG_LIBS})
-    SET(ACIS_LIBS ${ACIS_LIBS} debug ${var})
-  ENDFOREACH(var ${ACIS_DEBUG_LIBS})
-  FOREACH(var ${ACIS_RELEASE_LIBS})
-    SET(ACIS_LIBS ${ACIS_LIBS} optimized ${var})
-  ENDFOREACH(var ${ACIS_RELEASE_LIBS})
+  SET(ACIS_LIB_EXT ${CMAKE_SHARED_LIBRARY_SUFFIX})
+  SET(ACIS_LIB_PREFIX "lib")
   
-ENDIF(WIN32)
-
-IF(UNIX)
   # based on the system, define where the acis libraries are
   IF(CMAKE_SYSTEM MATCHES "Linux")
   SET(ACIS_ARCH linux)
-    IF(BUILD_64)
+    IF(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
       SET (ACIS_SYSTEM linux_amd_64_so)
-    ELSE(BUILD_64)
+    ELSE(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
       SET (ACIS_SYSTEM linux_so)
-    ENDIF(BUILD_64)
+    ENDIF(CMAKE_C_SIZEOF_DATA_PTR MATCHES 8)
   ENDIF(CMAKE_SYSTEM MATCHES "Linux")
 
- IF(CMAKE_SYSTEM MATCHES "Darwin")
-  SET(ACIS_SYSTEM macho)
-  SET(ACIS_ARCH mac)
+  IF(CMAKE_SYSTEM MATCHES "Darwin")
+   SET(ACIS_SYSTEM maci386)
+   SET(ACIS_ARCH mac)
   ENDIF(CMAKE_SYSTEM MATCHES "Darwin")
 
+  SET (ACIS_LIBRARY_DIR ${ACIS_DIR}/bin/${ACIS_SYSTEM})
+  SET (ACIS_LIBRARY_DIR_DEBUG ${ACIS_DIR}/bin/${ACIS_SYSTEM})
 
-  IF(CMAKE_SYSTEM MATCHES "SunOS")
-  SET(ACIS_SYSTEM solaris_so)
-  SET(ACIS_ARCH solaris)
-  ENDIF(CMAKE_SYSTEM MATCHES "SunOS")
+ENDIF(WIN32)
 
-  IF(CMAKE_SYSTEM MATCHES "IRIX")
-    SET(ACIS_ARCH sgi)
-    IF(BUILD_64)
-      SET (ACIS_SYSTEM sgi_64_so)
-    ELSE(BUILD_64)
-      SET (ACIS_SYSTEM sgi_so)
-    ENDIF(BUILD_64)
-  ENDIF(CMAKE_SYSTEM MATCHES "IRIX")
 
-  IF(CMAKE_SYSTEM MATCHES "HP-UX")
-  SET(ACIS_ARCH hp700)
-  SET(ACIS_SYSTEM hp700_11_so)
-  ENDIF(CMAKE_SYSTEM MATCHES "HP-UX")
+FOREACH(libgroup ACIS_CORE_LIBS ACIS_INTEROP_LIBS ACIS_STEP_LIBS ACIS_IGES_LIBS)
+  SET(${libgroup}_DEBUG)
+  SET(${libgroup}_RELEASE)
+  SET(${libgroup}_EXISTS OFF)
+  FOREACH(lib ${${libgroup}})
+    SET(tmp_debug_lib
+      "${ACIS_LIBRARY_DIR_DEBUG}/${ACIS_LIB_PREFIX}${lib}${ACIS_LIB_SUFFIX}${ACIS_DEBUG_SUFFIX}${ACIS_LIB_EXT}")
+    SET(tmp_release_lib
+      "${ACIS_LIBRARY_DIR}/${ACIS_LIB_PREFIX}${lib}${ACIS_LIB_SUFFIX}${ACIS_LIB_EXT}")
 
-  SET (ACIS_LIBRARY_DIR ${ACIS_DIR}/bin/${ACIS_SYSTEM})
-ENDIF(UNIX)
+    IF(EXISTS "${tmp_debug_lib}" AND EXISTS "${tmp_release_lib}")
+      SET(${libgroup}_EXISTS ON)
+      SET(${libgroup}_DEBUG ${${libgroup}_DEBUG} "${tmp_debug_lib}")
+      SET(${libgroup}_RELEASE ${${libgroup}_RELEASE} "${tmp_release_lib}")
+    ENDIF(EXISTS "${tmp_debug_lib}" AND EXISTS "${tmp_release_lib}")
+  ENDFOREACH(lib)
+ENDFOREACH(libgroup)
 
+# this list of libs has no 'd' suffix
+SET(ACIS_INTEROP_LIBS_EXTRA_DEBUG)
+SET(ACIS_INTEROP_LIBS_EXTRA_RELEASE)
+FOREACH(var ${ACIS_INTEROP_LIBS_EXTRA})
+  SET(ACIS_INTEROP_LIBS_EXTRA_DEBUG ${ACIS_INTEROP_LIBS_EXTRA_DEBUG}
+    "${ACIS_LIBRARY_DIR_DEBUG}/${ACIS_LIB_PREFIX}${var}${ACIS_LIB_EXT}")
+  SET(ACIS_INTEROP_LIBS_EXTRA_RELEASE ${ACIS_INTEROP_LIBS_EXTRA_RELEASE}
+    "${ACIS_LIBRARY_DIR}/${ACIS_LIB_PREFIX}${var}${ACIS_LIB_EXT}")
+ENDFOREACH(var ${ACIS_INTEROP_LIBS_EXTRA})
+
+
+IF(ACIS_INTEROP_LIBS_EXISTS)
+  OPTION(ACIS_STEP "Build with ACIS STEP Translator, if available" ON)
+  OPTION(ACIS_IGES "Build with ACIS IGES Translator, if available" ON)
+ELSE(ACIS_INTEROP_LIBS_EXISTS)
+  IF(ACIS_STEP OR ACIS_IGES)
+    MESSAGE(STATUS "Ignoring ACIS_STEP and ACIS_IGES options because libraries not found")
+  ENDIF(ACIS_STEP OR ACIS_IGES)
+  SET(ACIS_STEP OFF)
+  SET(ACIS_IGES OFF)
+ENDIF(ACIS_INTEROP_LIBS_EXISTS)
+
+# now fill in public variables
+SET(ACIS_LIBS)
+SET(ACIS_DEBUG_LIBS)
+SET(ACIS_RELEASE_LIBS)
+
+IF(ACIS_IGES)
+  FOREACH(lib ${ACIS_IGES_LIBS_DEBUG})
+    SET(ACIS_DEBUG_LIBS ${ACIS_DEBUG_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_IGES_LIBS_DEBUG})
+  FOREACH(lib ${ACIS_IGES_LIBS_RELEASE})
+    SET(ACIS_RELEASE_LIBS ${ACIS_RELEASE_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_IGES_LIBS_RELEASE})
+ENDIF(ACIS_IGES)
+
+IF(ACIS_STEP)
+  FOREACH(lib ${ACIS_STEP_LIBS_DEBUG})
+    SET(ACIS_DEBUG_LIBS ${ACIS_DEBUG_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_STEP_LIBS_DEBUG})
+  FOREACH(lib ${ACIS_STEP_LIBS_RELEASE})
+    SET(ACIS_RELEASE_LIBS ${ACIS_RELEASE_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_STEP_LIBS_RELEASE})
+ENDIF(ACIS_STEP)
+
+IF(ACIS_STEP OR ACIS_IGES)
+  FOREACH(lib ${ACIS_INTEROP_LIBS_DEBUG})
+    SET(ACIS_DEBUG_LIBS ${ACIS_DEBUG_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_INTEROP_LIBS_DEBUG})
+  FOREACH(lib ${ACIS_INTEROP_LIBS_RELEASE})
+    SET(ACIS_RELEASE_LIBS ${ACIS_RELEASE_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_INTEROP_LIBS_RELEASE})
+  
+  FOREACH(lib ${ACIS_INTEROP_LIBS_EXTRA_DEBUG})
+    SET(ACIS_DEBUG_LIBS ${ACIS_DEBUG_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_INTEROP_LIBS_EXTRA_DEBUG})
+  FOREACH(lib ${ACIS_INTEROP_LIBS_EXTRA_RELEASE})
+    SET(ACIS_RELEASE_LIBS ${ACIS_RELEASE_LIBS} "${lib}")
+  ENDFOREACH(lib ${ACIS_INTEROP_LIBS_EXTRA_RELEASE})
+ENDIF(ACIS_STEP OR ACIS_IGES)
+
+IF(NOT ACIS_CORE_LIBS_EXISTS)
+  MESSAGE(SEND_ERROR "Couldn't find acis libraries in ${ACIS_LIBRARY_DIR}")
+ENDIF(NOT ACIS_CORE_LIBS_EXISTS)
+
+FOREACH(lib ${ACIS_CORE_LIBS_DEBUG})
+  SET(ACIS_DEBUG_LIBS ${ACIS_DEBUG_LIBS} "${lib}")
+ENDFOREACH(lib ${ACIS_CORE_LIBS_DEBUG})
+FOREACH(lib ${ACIS_CORE_LIBS_RELEASE})
+  SET(ACIS_RELEASE_LIBS ${ACIS_RELEASE_LIBS} "${lib}")
+ENDFOREACH(lib ${ACIS_CORE_LIBS_RELEASE})
+
+
+FOREACH(var ${ACIS_DEBUG_LIBS})
+  SET(ACIS_LIBS ${ACIS_LIBS} debug ${var})
+ENDFOREACH(var ${ACIS_DEBUG_LIBS})
+FOREACH(var ${ACIS_RELEASE_LIBS})
+  SET(ACIS_LIBS ${ACIS_LIBS} optimized ${var})
+ENDFOREACH(var ${ACIS_RELEASE_LIBS})
+
+IF(ACIS_STEP)
+  ADD_DEFINITIONS(-DACIS_STEP_TRANSLATOR)
+ENDIF(ACIS_STEP)
+
+IF(ACIS_IGES)
+  ADD_DEFINITIONS(-DACIS_IGES_TRANSLATOR)
+ENDIF(ACIS_IGES)
+
+ADD_DEFINITIONS(-DACIS_TWEAK)
+ADD_DEFINITIONS(-DACIS_HEALER)
 ADD_DEFINITIONS(-DACIS_3D -DACIS_LOCAL_OPS)
 ADD_DEFINITIONS(-DACIS${ACIS_VERSION} -DCUBIT_ACIS_VERSION=${ACIS_VERSION})
 IF(UNIX)
@@ -178,6 +262,7 @@
 ENDIF(UNIX)
 IF(WIN32)
   ADD_DEFINITIONS(-DACIS_DLL -DSPA_NO_AUTO_LINK)
+  # no auto link to make us consistent in specifying library dependencies
 ENDIF(WIN32)
 
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -15,17 +15,10 @@
 // ********** END STANDARD INCLUDES           **********
 
 // ********** BEGIN ACIS INCLUDES             **********
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#include "kernel/kerndata/geom/transfrm.hxx"
-#include "kernel/kerndata/bulletin/bulletin.hxx"
-#else
 #include "api.hxx"	
 #include "datamsc.hxx"
 #include "transfrm.hxx"
 #include "bulletin.hxx"
-#endif
 // ********** END ACIS INCLUDES               **********
 
 // ********** BEGIN CUBIT INCLUDES            **********
@@ -76,6 +69,7 @@
 // ********** END MACRO DEFINITIONS           **********
 
 bool ATTRIB_CUBIT_OWNER::copyingAttribs = true;
+bool ATTRIB_CUBIT_OWNER::splitCopy = false;
 
 // make a cubit_owner attribute
 ATTRIB_CUBIT_OWNER::ATTRIB_CUBIT_OWNER(ENTITY* owner,
@@ -217,24 +211,25 @@
                                          ATTRIB_SNL_TYPE,
                                          ATTRIB_CUBIT_OWNER_TYPE);
     
-      // If the attribute is found, remove it. In the following code
-      // block, a do-while structure is used to ensure that all such
-      // attributes are removed. At present, at most 1 CUBIT_OWNER 
-      // attribute is allowed, per ACIS ENTITY.
+    //collect all the attributes..
+    DLIList<ATTRIB_CUBIT_OWNER*> owner_attribs;
     while (ATTRIB_ptr != NULL)
     {
-          // "unhook" this attribute from the ENTITY (i.e., remove it from
-          // the list of attributes associated with this ENTITY
-        API_BEGIN;
-        ATTRIB_ptr->unhook();
-        API_END;
-        
-          // Find the next CUBIT_OWNER attribute attached to this ENTITY
-        ATTRIB_ptr =
-          (ATTRIB_CUBIT_OWNER *) find_attrib(ENTITY_ptr, 
-                                             ATTRIB_SNL_TYPE,
-                                             ATTRIB_CUBIT_OWNER_TYPE);
+      owner_attribs.append( ATTRIB_ptr );
+
+      ATTRIB_ptr =
+        (ATTRIB_CUBIT_OWNER *) find_next_attrib( ATTRIB_ptr,
+                                                 ATTRIB_SNL_TYPE,
+                                                 ATTRIB_CUBIT_OWNER_TYPE);
     }
+
+    //now unhook them
+    while( owner_attribs.size() )
+    {
+      API_BEGIN;
+      owner_attribs.pop()->unhook();
+      API_END;
+    }
   }
 }
 
@@ -244,20 +239,21 @@
 // a FACE is copied without also copying a LUMP to attach it to.
 void ATTRIB_CUBIT_OWNER::split_owner(ENTITY *entity)
 {
-//   PRINT_INFO("split_owner called for attrib_cubit_owner on ");
+   //PRINT_INFO("split_owner called for attrib_cubit_owner on ");
   
     // must get simple attributes for new entity from CubitAttribUser
   if (!cubitOwnerData)
     return;
   
   TopologyBridge* tb = CAST_TO(cubitOwnerData, TopologyBridge);
-//  CubitEntity* cep = CAST_TO(tb->topology_entity(), CubitEntity);
-//   if (cep)
-//     PRINT_INFO("%s %d\n",
-//                cep->class_name(),
-//                cep->id());
-//   else
-//     PRINT_INFO("unknown ENTITY.\n");
+  //CubitEntity* cep = CAST_TO(tb->topology_entity(), CubitEntity);
+  // if (cep)
+  //   PRINT_INFO("%s %d\n",
+  //              cep->class_name(),
+  //              cep->id());
+  // else
+  //   PRINT_INFO("unknown ENTITY.\n");
+
   CubitAttribUser *cau = CAST_TO(tb->topology_entity(), CubitAttribUser);
   
   if (cau != NULL && cau->num_cubit_attrib() != 0)
@@ -275,13 +271,26 @@
         API_BEGIN;
         new ATTRIB_SNL_SIMPLE ( entity, csa_ptr );
         API_END;
+        delete csa_ptr;
       }
     }
   }
-  
+
+  if( splitCopy )
+  {
+    // Copy to the new entity.  In some operations, such as a fillet, chamfer
+    // or multi-tweak, entities are split then one of the resultant entities is
+    // thrown away.  We want to keep the cubit owner on the kept entity to 
+    // preserve ids, so this special circumstance was created.  This is
+    // analogous to a SplitCopy in the ACIS ATTRIB class.
+    ATTRIB_CUBIT_OWNER::set_cubit_owner( entity, cubitOwnerData );
+  }
+  else
+  {
     // in the case of a split, lose this attribute
-  unhook();
-  lose();
+    unhook();
+    lose();
+  }
 }
 
 void ATTRIB_CUBIT_OWNER::set_copyable( bool copying_attribs )
@@ -295,13 +304,24 @@
   return copyingAttribs;
 }
 
+bool ATTRIB_CUBIT_OWNER::get_split_copy()
+{
+  return splitCopy;
+}
 
+bool ATTRIB_CUBIT_OWNER::set_split_copy( bool split_copy )
+{
+  bool old_splitCopy = splitCopy;
+  splitCopy = split_copy;
+  return old_splitCopy;
+}
+
 // Virtual function called when two entities are to be merged,
 // as may happen with 'unite'
 void ATTRIB_CUBIT_OWNER::merge_owner(ENTITY *other_entity,
                                      logical delete_this)
 {
-//   PRINT_INFO("merge_owner called for attrib_cubit_owner.\n");
+   //PRINT_INFO("merge_owner called for attrib_cubit_owner.\n");
     // Handle merging via the survivor
   if (delete_this)
     return;
@@ -310,6 +330,12 @@
   if (!cubitOwnerData)
     return;
   TopologyBridge* tb = CAST_TO(cubitOwnerData, TopologyBridge);
+  if(tb)
+  {
+    TopologyBridge *tb_owner;
+    while((tb_owner = dynamic_cast<TopologyBridge*>(tb->owner())))
+      tb = tb_owner;
+  }
   CubitAttribUser *cau =
     (tb ? CAST_TO(tb->topology_entity(), CubitAttribUser) :
      NULL);
@@ -324,8 +350,15 @@
   RefEntity *ref_entity = NULL;
   if (other_owner_att && other_owner_att->cubit_owner()) {
     tb = CAST_TO(other_owner_att->cubit_owner(), TopologyBridge);
+    if(tb)
+    {
+      TopologyBridge *tb_owner;
+      while((tb_owner = dynamic_cast<TopologyBridge*>(tb->owner())))
+        tb = tb_owner;
+    }
     ref_entity = CAST_TO(tb->topology_entity(), RefEntity);
-    assert(ref_entity != NULL);
+
+    //assert(ref_entity != NULL);
   }
   
   cau->merge_owner(ref_entity);

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_cubit_owner.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -74,12 +74,21 @@
   virtual void to_tolerant_owner( ENTITY *tol_ent );
 
   static void set_copyable( bool copying_attribs );
+
+  static bool get_split_copy();
+  static bool set_split_copy( bool split_copy );
+  //- Methods to get and set the split_owner behavior for the cubit owner 
+  //- attribute.  If true, the cubit owner attribute is copied to the new
+  //- entity during a split operation, otherwise it is lost.  The set method
+  //- returns the previous value of the flag.  Default is false (the cubit
+  //- owner attribute is lost when an entity is split).
   
   ATTRIB_FUNCTIONS(ATTRIB_CUBIT_OWNER, NONE)
     
     private:
   AcisBridge *cubitOwnerData;
   static bool copyingAttribs;
+  static bool splitCopy;
 };
 
 #endif

Copied: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.cpp (from rev 3491, cgm/branches/cubit/geom/ACIS_SRC/attrib_history.cpp)
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.cpp	                        (rev 0)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -0,0 +1,402 @@
+
+#include "attrib_history.hpp"
+#include "CubitMessage.hpp"
+#include "AcisHistory.hpp"
+
+// ********** BEGIN ACIS INCLUDES             **********
+#include "api.hxx"	
+#include "datamsc.hxx"
+#include "transfrm.hxx"
+#include "bulletin.hxx"
+#include "acistype.hxx"
+// ********** END ACIS INCLUDES               **********
+
+// ********** BEGIN MACRO DEFINITIONS         **********
+#define THIS() ATTRIB_HISTORY
+#define THIS_LIB NONE
+#define PARENT() ATTRIB_SNL
+#define PARENT_LIB NONE
+
+#define ATTRIB_HISTORY_NAME "history"
+
+//ATTRIB_DEF("history_attribute")
+
+int ATTRIB_HISTORY::num_attribs = 0;
+bool ATTRIB_HISTORY::addOrRemoveFromList = true;
+std::set<ATTRIB_HISTORY*> ATTRIB_HISTORY::allHistoryAttribs; 
+
+//When acis backs up this attribute, it gets to this macro right after exiting 
+//the constructor.  Here we remove the backed-up history attribute from our list 
+//since Acis takes care of destroying all backed-up attributes.
+ATTCOPY_DEF("history_attribute")
+  ATTRIB_HISTORY *history_attrib = const_cast<ATTRIB_HISTORY*>(rollback);
+  std::set<ATTRIB_HISTORY*>::iterator iter;
+  iter = allHistoryAttribs.find( history_attrib ); 
+  if( iter != allHistoryAttribs.end() )
+    allHistoryAttribs.erase( iter );
+
+LOSE_DEF
+
+DTOR_DEF
+  num_attribs--;
+  std::set<ATTRIB_HISTORY*>::iterator iter;
+  if( addOrRemoveFromList )
+  {
+    iter = allHistoryAttribs.find( this );
+    if( iter != allHistoryAttribs.end() )
+      allHistoryAttribs.erase( iter );
+  }
+  if( num_attribs == 0 )
+    PRINT_INFO("num_attribs = %d\n", num_attribs ); 
+
+DEBUG_DEF
+
+
+SAVE_DEF
+// Don't save
+
+RESTORE_DEF
+// Don't restore
+
+COPY_DEF
+  //This attribute is being copied from ENTITY "from".  At this point
+  //it would be nice to be able to map the original ENTITY (from->owner())
+  //to the copy (this->owner()) but you can't since all the copying isn't 
+  //complete.  So right now we just get the 'from' attribute.  Later in
+  //FIX_POINTER_DEF after everything is hooked up correctly, we can get
+  //the this->owner().
+  fromHistoryAttrib = (ATTRIB_HISTORY*)from;
+  //get the index of the copy in the array in fix_pointer_def 
+  //index = (ENTITY*) INTEXTEND list.lookup( from->owner() ); 
+
+SCAN_DEF
+
+FIX_POINTER_DEF
+  //change from index to actual value
+  //ENTITY *thisENTITY = ( ENTITY* ) read_array( array, index );
+  
+  //we get in here in the last step of the copy...at this point 
+  //everything should be hooked up nicely so that we can determine
+  //the entity from which this attribute's owner was copied
+  //AcisHistory::AcisEvent event;
+  //event.eventType = AcisHistory::COPY;
+  //append the original entity to the first list
+  //int unique_id = fromHistoryAttrib->get_unique_id();
+  //event.entities.push_back( unique_id ); 
+
+  this->add_acis_history( fromHistoryAttrib->acisHistory );
+  this->trackingIds = fromHistoryAttrib->trackingIds;
+
+  //Append the copied ENTITY to the 'other' list
+  //event.other_entities.push_back( this->get_unique_id() ); 
+
+  //add the event
+  //fromHistoryAttrib->acisHistory->add_event( event ); 
+
+TERMINATE_DEF
+// Don't do anything special
+// ********** END MACRO DEFINITIONS           **********
+
+//bool ATTRIB_CUBIT_OWNER::copyingAttribs = true;
+//bool ATTRIB_CUBIT_OWNER::splitCopy = false;
+
+
+
+ATTRIB_HISTORY::ATTRIB_HISTORY( ENTITY *entity, AcisHistory *acis_history )
+    : ATTRIB_SNL( entity )
+{
+  acisHistory = NULL;
+  num_attribs++;
+  if( acis_history )
+    add_acis_history( acis_history );
+
+  if( addOrRemoveFromList )
+    allHistoryAttribs.insert( this ); 
+}
+
+void ATTRIB_HISTORY::add_acis_history( AcisHistory *acis_history )
+{
+  acisHistory = acis_history; 
+}
+
+std::set<int> ATTRIB_HISTORY::get_tracking_ids()
+{
+  return trackingIds;
+}
+
+void ATTRIB_HISTORY::split_owner( ENTITY *entity)
+{
+  /*
+  PRINT_INFO("I'm in split_owner!!!!\n");
+  if( is_BODY( this->entity() )) 
+    PRINT_INFO("  It's a body\n");
+  if( is_LUMP( this->entity() )) 
+    PRINT_INFO("  It's a volume\n");
+  if( is_FACE( this->entity() )) 
+    PRINT_INFO("  It's a surface\n");
+  if( is_EDGE( this->entity() )) 
+    PRINT_INFO("  It's an edge\n");
+  if( is_VERTEX( this->entity() )) 
+    PRINT_INFO("  It's a vertex\n"); */
+
+  //add an ATTRIB_HISTORY to the new entity
+  ATTRIB_HISTORY *other_history_attrib = get_history_attrib( entity, true, acisHistory );
+  other_history_attrib->trackingIds = this->trackingIds;
+
+  if( trackingIds.size() > 1 )
+    return;
+  //Create an AcisEvent of type CUT 
+  AcisHistory::AcisEvent event;
+  event.eventType = CGMHistory::CUT;
+
+  event.entities.push_back( *(trackingIds.begin()) ); 
+
+  assert( acisHistory );
+  
+  //add the event to the history object
+  acisHistory->add_event( event ); 
+
+  //Create an AcisEvent of type Subdivision
+  //AcisHistory::AcisEvent event;
+  //event.eventType = AcisHistory::SUBDIVISION;
+  //event.entities.push_back( this->get_unique_id() );
+
+  //event.other_entities.push_back( other_history_attrib->get_unique_id() ); 
+  //event.other_entities.push_back( this->get_unique_id() );
+
+  //assert( acisHistory );
+  
+  //add the event to the history object
+  //acisHistory->add_event( event ); 
+}
+  
+void ATTRIB_HISTORY::merge_owner( ENTITY *entity, logical delete_this)
+{
+  if( delete_this )
+    return;
+/*
+  PRINT_INFO("I'm in merge owner!!!!\n");
+  if( is_BODY( this->entity() )) 
+    PRINT_INFO("  It's a body\n");
+  if( is_LUMP( this->entity() )) 
+    PRINT_INFO("  It's a volume\n");
+  if( is_FACE( this->entity() )) 
+    PRINT_INFO("  It's a surface\n");
+  if( is_EDGE( this->entity() )) 
+    PRINT_INFO("  It's an edge\n");
+  if( is_VERTEX( this->entity() )) 
+    PRINT_INFO("  It's a vertex\n");
+ */
+
+  //if the entity we're merging this's->owner() with doesn't have
+  //a history attrib on it, we don't care about this
+  ATTRIB_HISTORY *other_history_attrib = get_history_attrib( entity, false ); 
+  if( !other_history_attrib )
+    return;
+
+  //Create an AcisEvent of type Subdivision
+  //AcisHistory::AcisEvent event;
+  //event.eventType = AcisHistory::ABSORPTION;
+
+  //'entity' got absorbed into 'this->entity()'
+  //event.entities.push_back( other_history_attrib->get_unique_id() ); 
+  //event.entities.push_back( this->get_unique_id() );
+  //event.other_entities.push_back( this->get_unique_id() );
+
+  std::set<int> other_tracking_ids = other_history_attrib->trackingIds;
+  std::set<int>::iterator iter;
+  for(iter = other_tracking_ids.begin(); iter != other_tracking_ids.end(); iter++ )
+    trackingIds.insert( *iter ); 
+
+  assert( acisHistory );
+  
+  //add the event to the history object
+//  acisHistory->add_event( event ); 
+}
+  
+void ATTRIB_HISTORY::trans_owner( SPAtransf const& )
+{
+}
+void ATTRIB_HISTORY::to_tolerant_owner( ENTITY *tol_ent )
+{
+}
+
+void ATTRIB_HISTORY::copy_owner( ENTITY *copy_ent )
+{
+
+  ATTRIB_HISTORY *other_history_attrib = get_history_attrib( copy_ent, true, acisHistory );
+  other_history_attrib->trackingIds = this->trackingIds;
+}
+
+void ATTRIB_HISTORY::replace_owner( ENTITY *other_entity, logical replace_owner )
+{
+  if( replace_owner )
+    return;
+/*
+  PRINT_INFO("I'm in replace owner!!!!\n");
+  if( is_BODY( this->entity() )) 
+    PRINT_INFO("  It's a body\n");
+  if( is_LUMP( this->entity() )) 
+    PRINT_INFO("  It's a volume\n");
+  if( is_FACE( this->entity() )) 
+    PRINT_INFO("  It's a surface\n");
+  if( is_EDGE( this->entity() )) 
+    PRINT_INFO("  It's an edge\n");
+  if( is_VERTEX( this->entity() )) 
+    PRINT_INFO("  It's a vertex\n");
+*/
+  //if this has alrady been merged w/ something else, it will have 
+  //2 tracking ids in it's list.  I don't believe there's a need to 
+  //track it then if it's already been merged
+  
+  if( trackingIds.size() > 1 )
+    return;
+  //Create an AcisEvent of type geometry_changed 
+  AcisHistory::AcisEvent event;
+  event.eventType = CGMHistory::GEOMETRY_CHANGED;
+
+  event.entities.push_back( *(trackingIds.begin()) ); 
+
+  assert( acisHistory );
+  
+  //add the event to the history object
+  acisHistory->add_event( event ); 
+}
+
+void ATTRIB_HISTORY::lop_change_owner()
+{
+  /*
+  PRINT_INFO("I'm in lop_change_owner owner!!!!\n");
+  if( is_BODY( this->entity() )) 
+    PRINT_INFO("  It's a body\n");
+  if( is_LUMP( this->entity() )) 
+    PRINT_INFO("  It's a volume\n");
+  if( is_FACE( this->entity() )) 
+    PRINT_INFO("  It's a surface\n");
+  if( is_EDGE( this->entity() )) 
+    PRINT_INFO("  It's an edge\n");
+  if( is_VERTEX( this->entity() )) 
+    PRINT_INFO("  It's a vertex\n");
+*/
+  //if this has alrady been merged w/ something else, it will have 
+  //2 tracking ids in it's list.  I don't believe there's a need to 
+  //track it then if it's already been merged
+  
+  if( trackingIds.size() > 1 )
+    return;
+
+  //Create an AcisEvent of type Subdivision
+  AcisHistory::AcisEvent event;
+  event.eventType = CGMHistory::GEOMETRY_CHANGED;
+
+  event.entities.push_back( *(trackingIds.begin()) ); 
+
+  assert( acisHistory );
+  
+  //add the event to the history object
+  acisHistory->add_event( event ); 
+}
+
+void ATTRIB_HISTORY::replace_owner_geometry( ENTITY *new_geom )
+{
+  /*
+  PRINT_INFO("I'm in replace_owner_geometry !!!!\n");
+  if( is_BODY( this->entity() )) 
+    PRINT_INFO("  It's a body\n");
+  if( is_LUMP( this->entity() )) 
+    PRINT_INFO("  It's a volume\n");
+  if( is_FACE( this->entity() )) 
+    PRINT_INFO("  It's a surface\n");
+  if( is_EDGE( this->entity() )) 
+    PRINT_INFO("  It's an edge\n");
+  if( is_VERTEX( this->entity() )) 
+    PRINT_INFO("  It's a vertex\n");
+*/
+  //if this has alrady been merged w/ something else, it will have 
+  //2 tracking ids in it's list.  I don't believe there's a need to 
+  //track it then if it's already been merged
+  
+  if( trackingIds.size() > 1 )
+    return;
+  //Create an AcisEvent of type Subdivision
+  AcisHistory::AcisEvent event;
+  event.eventType = CGMHistory::GEOMETRY_CHANGED;
+
+  event.entities.push_back( *(trackingIds.begin()) ); 
+
+  assert( acisHistory );
+  
+  //add the event to the history object
+  acisHistory->add_event( event ); 
+}
+
+void ATTRIB_HISTORY::reverse_owner()
+{
+  PRINT_INFO("I'm in reverse_owner !!!!\n");
+}
+
+void ATTRIB_HISTORY::warp_owner( law *warp )
+{
+  PRINT_INFO("I'm in warp_owner !!!!\n");
+}
+
+ATTRIB_HISTORY* ATTRIB_HISTORY::get_history_attrib( ENTITY *acis_entity,
+                                                    bool create_if_necessary,
+                                                    AcisHistory *acis_history )
+{
+
+  if (acis_entity == NULL)
+  {
+    PRINT_ERROR("Trying to set a history attribute on a "
+                " NULL ACIS ENTITY.\n");
+    return NULL;
+  }
+
+    // Search for the attribute
+  ATTRIB_HISTORY *history_attribute =
+    (ATTRIB_HISTORY*)find_attrib(acis_entity,
+                                 ATTRIB_SNL_TYPE, 
+                                 ATTRIB_HISTORY_TYPE);
+  
+  //if we're not creating anything, return whatever we found
+  if( false == create_if_necessary )
+    return history_attribute;
+
+    // If found, reset it's value
+  if (history_attribute != NULL)
+  {
+
+  }
+    // Otherwise, create a new attribute for acis_entity
+  else
+  {
+    API_BEGIN;
+    history_attribute = new ATTRIB_HISTORY( acis_entity, acis_history );
+    API_END;
+  }
+
+  return history_attribute;
+}
+
+
+void ATTRIB_HISTORY::add_tracking_id( int id ) 
+{
+  trackingIds.insert( id );  
+}
+
+void ATTRIB_HISTORY::remove_all_attribs()
+{
+  //prevents 
+  //addOrRemoveFromList = false;
+
+  std::set<ATTRIB_HISTORY*>::iterator iter = allHistoryAttribs.begin();
+  for( ; iter != allHistoryAttribs.end(); iter++ )
+  {
+    ATTRIB_HISTORY *history_attrib = *iter;
+    history_attrib->unhook();
+    history_attrib->lose();
+  }
+
+  allHistoryAttribs.clear();
+  //addOrRemoveFromList = true;
+}

Copied: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.hpp (from rev 3491, cgm/branches/cubit/geom/ACIS_SRC/attrib_history.hpp)
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.hpp	                        (rev 0)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_history.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -0,0 +1,96 @@
+//-------------------------------------------------------------------------
+// Filename      : attrib_history.hpp
+//
+// Purpose       : Attributes needed to track subdivisions, 
+//                 merges, copy, and geometry-changing events
+//
+// Creator       : Corey Ernst
+//-------------------------------------------------------------------------
+
+#ifndef ATTRIB_HISTORY_HPP
+#define ATTRIB_HISTORY_HPP
+
+// ********** BEGIN ACIS INCLUDES             **********
+// ********** END ACIS INCLUDES               **********
+
+// ********** BEGIN CUBIT INCLUDES            **********
+#include "attrib_snl.hpp"
+#include <set>
+//#include "AcisTypes.h"
+// ********** END CUBIT INCLUDES              **********
+
+// ********** BEGIN MACRO DEFINITIONS         **********
+extern int ATTRIB_HISTORY_TYPE;
+#define ATTRIB_HISTORY_LEVEL (ATTRIB_SNL_LEVEL + 1)
+// ********** END MACRO DEFINITIONS           **********
+
+// ********** BEGIN FORWARD DECLARATIONS      **********
+
+// ********** END FORWARD DECLARATIONS        **********
+
+class AcisHistory;
+
+class ATTRIB_HISTORY: public ATTRIB_SNL
+{
+public:
+  
+  ATTRIB_HISTORY( ENTITY* entity = NULL, AcisHistory* acis_history = NULL ); 
+
+  static ATTRIB_HISTORY* get_history_attrib( ENTITY *acis_entity,
+                                             bool create_if_necessary = false,
+                                             AcisHistory *acis_history = NULL ); 
+  
+ // void set_history_object( AcisHistoryObject *history_object );
+ // AcisHistoryObject* get_history_object(); 
+  
+  //-------------------------
+  virtual void split_owner( ENTITY *entity);
+  
+  virtual void merge_owner( ENTITY *entity, logical delete_this);
+  
+  virtual void trans_owner( SPAtransf const& );
+
+  virtual void to_tolerant_owner( ENTITY *tol_ent );
+
+  virtual void copy_owner( ENTITY *copy_ent );
+
+  virtual void replace_owner( ENTITY *other_entity, logical replace_owner );
+
+  virtual void lop_change_owner();
+
+  virtual void replace_owner_geometry( ENTITY *new_geom );
+
+  virtual void reverse_owner(); 
+
+  virtual void warp_owner( law *warp );
+  //-------------------------
+
+  std::set<int> get_tracking_ids();
+  void add_tracking_id( int id ); 
+  void add_acis_history( AcisHistory *acis_history );
+  
+  static void remove_all_attribs();
+
+  ATTRIB_FUNCTIONS(ATTRIB_HISTORY, NONE)
+    
+  private:
+    //the history object that is being added to
+    AcisHistory *acisHistory; 
+
+    //when an entity gets copied, the resultant copy entity needs to know 
+    //the entity from whence it was copied.  This ATTRIB_HISTORY pointer 
+    //facilitates mapping the original ENTITY to the resultant copied ENTITY 
+    ATTRIB_HISTORY *fromHistoryAttrib;
+    
+    std::set<int> trackingIds;
+    static std::set<ATTRIB_HISTORY*> allHistoryAttribs; 
+    
+    static int num_attribs;
+    static bool addOrRemoveFromList; 
+    //static bool copyingAttribs;
+    //static bool splitCopy;
+};
+
+#endif
+
+

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -26,15 +26,9 @@
 #include <stdio.h>
 
 // ACIS Includes
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/dcl_kern.h"
-#include "kernel/kerndata/attrib/at_tsl.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#else
 #include "dcl_kern.h"
 #include "at_tsl.hxx"
 #include "datamsc.hxx"
-#endif
 
 #include "attrib_snl.hpp"
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -33,11 +33,7 @@
 // CUBIT Includes
 #include "decl_none.h"
 // ACIS Includes
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kerndata/attrib/attrib.hxx"
-#else
 #include "attrib.hxx"
-#endif
 
 // This attribute type is a derived class of ATTRIB.
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.cpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.cpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.cpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -10,17 +10,14 @@
 #include <string.h>
 
 // ACIS Includes
-#if CUBIT_ACIS_VERSION < 1100
-#include "kernel/kernapi/api/api.hxx"
-#include "kernel/kerndata/attrib/at_tsl.hxx"
-#include "kernel/kerndata/data/datamsc.hxx"
-#else
 #include "api.hxx"	
 #include "at_tsl.hxx"
 #include "datamsc.hxx"
 #include "acistype.hxx"
 #include "edge.hxx"
-#endif
+#include "kernapi.hxx"
+#include "vertex.hxx"
+#include "point.hxx"
 
 #include "attrib_snl_simple.hpp"
 #include "attrib_cubit_owner.hpp"
@@ -29,6 +26,7 @@
 #include "CubitAttribUser.hpp"
 #include "CastTo.hpp"
 #include "TopologyEntity.hpp"
+#include "GeometryDefines.h"
 
 // Buffer size
 const int MAX_STRING_LENGTH = 256;
@@ -144,11 +142,89 @@
 // ****DEFINED FUNCTIONS!!!!!!!!!!
 void ATTRIB_SNL_SIMPLE::split_owner(ENTITY* new_ent)
 {
+  // When performing real operations on geometry with
+  // virtual we need to try to maintain the virtual
+  // ids where possible.  To do this we push an ENTITY_ID
+  // attribute onto the ACIS entities before the operation
+  // and then actuate them after the operation to get the 
+  // id back.  If we split an entity however we want
+  // to make sure the id attribute gets thrown away
+  // so that new ids will be generated correctly.  We
+  // check the second string also here in case the ENTITY_ID 
+  // was saved as part of a COMPOSITE_ATTRIB attribute (where
+  // "COMPOSITE_ATTRIB" is in the first position).  
+  if(data->get_string(0) == "ENTITY_ID" || 
+     data->get_string(1) == "ENTITY_ID")
+  {
+    unhook();
+    lose();
+    return;
+  }
+
+  // If we are splitting a curve that is hidden in a
+  // composite surface put a composite attribute on the
+  // new vertices where the split took place.  We don't 
+  // want a new vertex there because the operation should
+  // behave as if the hidden curve was never there.
+  /*   This can ceate cases that can't be composited (see bug_6402.jou in interop
+       test suite).
+  if(!strcmp(data->name().c_str(), "COMPOSITE_GEOM"))
+  {
+    if(is_EDGE(entity()) && is_EDGE(new_ent))
+    {
+      EDGE *e1 = (EDGE*)entity();
+      EDGE *e2 = (EDGE*)new_ent;
+      ENTITY_LIST edge1_verts;
+      api_get_vertices((ENTITY*)e1, edge1_verts);
+      edge1_verts.init();
+      VERTEX *e1v1 = (VERTEX*)edge1_verts.next();
+      VERTEX *e1v2 = (VERTEX*)edge1_verts.next();
+      ENTITY_LIST edge2_verts;
+      api_get_vertices((ENTITY*)e2, edge2_verts);
+      edge2_verts.init();
+      VERTEX *e2v1 = (VERTEX*)edge2_verts.next();
+      VERTEX *e2v2 = (VERTEX*)edge2_verts.next();
+      VERTEX *vert = NULL;
+      // The new entity should be a different length
+      // than the old entity.  One of the vertices on 
+      // the new entity will match one of the vertices
+      // on the old entity.  Find the one that matches
+      // and then we will know that the other one on the
+      // new entity is the vertex where the split took place.
+      if(e2v1 == e1v1 || e2v1 == e1v2)
+        vert = e2v2;
+      else if(e2v2 == e1v1 || e2v2 == e1v2)
+        vert = e2v1;
+      else
+      {
+        double same_pt_tol = GEOMETRY_RESABS*GEOMETRY_RESABS;
+        if((e2v1->geometry()->coords() - e1v1->geometry()->coords()).len_sq() < same_pt_tol)
+          vert = e2v2;
+        else if((e2v1->geometry()->coords() - e1v2->geometry()->coords()).len_sq() < same_pt_tol)
+          vert = e2v2;
+        else if((e2v2->geometry()->coords() - e1v1->geometry()->coords()).len_sq() < same_pt_tol)
+          vert = e2v1;
+        else if((e2v2->geometry()->coords() - e1v2->geometry()->coords()).len_sq() < same_pt_tol)
+          vert = e2v1;
+      }
+      if(vert)
+      {
+        API_BEGIN;
+        new ATTRIB_SNL_SIMPLE(vert, *this);
+        API_END;
+      }
+    }
+  }
+  */
+
   // If we have split an entity that is a hidden
   // entity of a composite transfer the attribute
   // to the new entity.
   if(!strcmp(data->name().c_str(), "COMPOSITE_GEOM") ||
-     !strcmp(data->name().c_str(), "IMPRINT_PREEXISTING"))
+     !strcmp(data->name().c_str(), "IMPRINT_PREEXISTING") ||
+     !strcmp(data->name().c_str(), "COMPOSITE_IGNORE") ||
+     !strcmp(data->name().c_str(), "IMPRINTER") ||
+     !strcmp(data->name().c_str(), "REMOVE_EDGE"))
   {
     API_BEGIN;
     new ATTRIB_SNL_SIMPLE(new_ent, *this);
@@ -173,7 +249,9 @@
   
   if(data &&
      (!strcmp(data->name().c_str(), "ENTITY_NAME") ||
-      !strcmp(data->name().c_str(), "CA_ASSEMBLY_DATA")))
+      !strcmp(data->name().c_str(), "CA_ASSEMBLY_DATA") ||
+      !strcmp(data->name().c_str(), "PROPERTY_BLOCK") ||
+      !strcmp(data->name().c_str(), "MATERIAL_BLOCK")))
   {
     API_BEGIN;
     new ATTRIB_SNL_SIMPLE(new_ent, *this);
@@ -203,6 +281,9 @@
 {
   if(!strcmp(data->name().c_str(), "COMPOSITE_GEOM"))
   {
+    int destroy = 0;
+    //if(is_VERTEX(entity()) && is_VERTEX(other_ent))
+    //  destroy = 1;
     if(is_EDGE(entity()) && is_EDGE(other_ent))
     {
       EDGE *this_edge = (EDGE*)entity();
@@ -212,15 +293,19 @@
          (this_edge->start() == other_edge->end() &&
           this_edge->end() == other_edge->start()))
       {
-        // If we get to this point we most likely have the
-        // case where a geometric operation has cut this
-        // body right along the hidden entity of a composite.
-        // In this case we will just blow away the composite
-        // by removing the attribute.
-        unhook();
-        lose();
+        destroy = 1;
       }
     }
+    if(destroy)
+    {
+      // If we get to this point we most likely have the
+      // case where a geometric operation has cut this
+      // body right along the hidden entity of a composite.
+      // In this case we will just blow away the composite
+      // by removing the attribute.
+      unhook();
+      lose();
+    }
     return;
   }
 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.hpp
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.hpp	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/attrib_snl_simple.hpp	2010-01-27 02:15:23 UTC (rev 3496)
@@ -47,6 +47,9 @@
 
       inline CubitString name() const
         { return numStrings ? stringData[0] : CubitString(); }
+
+      inline CubitString get_string(int index) const
+      { return (index > -1 && numStrings > index) ? stringData[index] : CubitString(); } 
         
       void save() const;
       

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/decl_none.h
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/decl_none.h	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/decl_none.h	2010-01-27 02:15:23 UTC (rev 3496)
@@ -18,10 +18,6 @@
 #ifndef EXPORT_NONE
 # ifdef NT
 
-#if CUBIT_ACIS_VERSION < 1100
-#  pragma comment( lib, "kernel.lib") /* force link in VC++ */
-#endif
-
 # endif
 #endif
 


Property changes on: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib
___________________________________________________________________
Added: svn:mergeinfo
   + 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/CMakeLists.txt
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/CMakeLists.txt	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/CMakeLists.txt	2010-01-27 02:15:23 UTC (rev 3496)
@@ -1,10 +1,103 @@
 
 PROJECT(gtcAttrib)
+IF(IGTO_BUILD)
+ 
+SET(gtcAttrib_MAJOR_VERSION 1
+       	CACHE STRING "gtcAttrib Major Library Version" FORCE)
+SET(gtcAttrib_MINOR_VERSION 0
+       	CACHE STRING "gtcAttrib Minor Library Version" FORCE)
+SET(gtcAttrib_VERSION 
+      "${gtcAttrib_MAJOR_VERSION}.${gtcAttrib_MINOR_VERSION}"
+         CACHE STRING "gtcAttrib Library Version" FORCE)
+#SET (gtcAttrib_VERSION 1.0 CACHE STRING "Library Version" FORCE)
 
 # Disallow in-source build
 STRING(COMPARE EQUAL "${gtcAttrib_SOURCE_DIR}"
  "${gtcAttrib_BINARY_DIR}" INSOURCE)
 IF(INSOURCE)
+  MESSAGE(SEND_ERROR "Build directory ${gtcAttrib_BINARY_DIR}")
+  MESSAGE(SEND_ERROR "Source directory ${gtcAttrib_SOURCE_DIR}")
+  MESSAGE(FATAL_ERROR "gtcAttrib requires an out of source Build. Please create a separate binary directory and run CMake there.")
+ENDIF(INSOURCE)
+
+# set our CMAKE_MODULE_PATH to include the one specific to this project
+SET (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules )
+
+SET (GTC_ATTRIB_SRCS
+     src/attrib_edge_parametric_length.C 
+     src/attrib_gtc.C
+     src/attrib_mark.C
+     src/attrib_name.C
+     )
+
+# check to see if we have the standard namespace
+INCLUDE (TestForSTDNamespace)
+IF (CMAKE_STD_NAMESPACE)
+   ADD_DEFINITIONS(-DHAVE_STD)
+ENDIF (CMAKE_STD_NAMESPACE)
+
+# Find the acis libraries
+
+INCLUDE (FindACIS)
+FindACIS(17)
+
+IF (ACIS_FOUND)
+  # add acis includes to current project
+  INCLUDE_DIRECTORIES(${ACIS_INCLUDE_DIR} ${gtcAttrib_SOURCE_DIR}/incl)
+  
+  #need to define ACIS_VER since it's used in the source here 
+  ADD_DEFINITIONS(-DACIS_VER=${ACIS_VERSION})
+  
+  ADD_DEFINITIONS(${ACIS_DEFINES})
+  
+  LINK_DIRECTORIES(${ACIS_LIBRARY_DIR} ${ACIS_LIBRARY_DIR_DEBUG})
+ELSE (ACIS_FOUND)
+  MESSAGE(FATAL_ERROR "gtcAttrib requires ACIS libraries of version R16 or above.")
+ENDIF (ACIS_FOUND)
+
+
+IF(UNIX)
+  ADD_CUSTOM_TARGET(switch_acis ${CMAKE_MAKE_PROGRAM} clean)
+ELSE(UNIX)
+  ADD_DEFINITIONS(-DNT -DgtcAttrib_EXPORTS)
+#   IF (MSVC60 OR MSVC70)
+#     ADD_DEFINITIONS(-DNT_DLL)
+#   ENDIF (MSVC60 OR MSVC70)
+#   IF (MSVC71)
+#     ADD_DEFINITIONS(-DNT_NET_DLL)
+#   ENDIF (MSVC71)
+  SET (ARCHIVE_DESIGNATOR a)
+  SET (SHARED_DESIGNATOR s)
+ENDIF(UNIX)
+
+
+# build gtcAttrib library from sources
+ADD_LIBRARY(libgtcAttrib STATIC ${GTC_ATTRIB_SRCS})
+ADD_LIBRARY(libgtcAttrib_so SHARED ${GTC_ATTRIB_SRCS})
+SET_TARGET_PROPERTIES(libgtcAttrib PROPERTIES OUTPUT_NAME gtcAttrib${gtcAttrib_VERSION}${ARCHIVE_DESIGNATOR})
+SET_TARGET_PROPERTIES(libgtcAttrib_so PROPERTIES OUTPUT_NAME gtcAttrib${gtcAttrib_VERSION}${SHARED_DESIGNATOR})
+
+TARGET_LINK_LIBRARIES(libgtcAttrib ${ACIS_LIBRARIES})
+TARGET_LINK_LIBRARIES(libgtcAttrib_so ${ACIS_LIBRARIES})
+
+
+INSTALL_TARGETS(/${CMAKE_INSTALL_BINARY_DIR} libgtcAttrib libgtcAttrib_so)
+
+# GET_TARGET_PROPERTY(LIB_OUT_NAME2 libgtcAttrib OUTPUT_NAME)
+# MESSAGE("libgtcAttrib output name is ${LIB_OUT_NAME2}")
+
+# GET_TARGET_PROPERTY(LIBSO_OUT_NAME2 libgtcAttrib_so OUTPUT_NAME)
+# MESSAGE("libgtcAttrib_so output name is ${LIBSO_OUT_NAME2}")
+
+# this keeps the build of the shared lib from erasing the archive lib and v/v
+SET_TARGET_PROPERTIES(libgtcAttrib libgtcAttrib_so PROPERTIES CLEAN_DIRECT_OUTPUT 1) 
+
+ELSE(IGTO_BUILD)
+
+# Disallow in-source build
+STRING(COMPARE EQUAL "${gtcAttrib_SOURCE_DIR}"
+ "${gtcAttrib_BINARY_DIR}" INSOURCE)
+IF(INSOURCE)
  MESSAGE(FATAL_ERROR "gtcAttrib requires an out of source Build. Please create a separate binary directory and run CMake there.")
  ENDIF(INSOURCE)
 
@@ -22,15 +115,18 @@
 ADD_DEFINITIONS(-DACIS_VER=${ACIS_VERSION})
 
 # build cubit acis library from sources
-LINK_DIRECTORIES(${ACIS_LIBRARY_DIR} ${ACIS_LIBRARY_DIR_DEBUG})
 ADD_LIBRARY(gtcAttrib SHARED ${GTC_ATTRIB_SRCS})
 
 TARGET_LINK_LIBRARIES(gtcAttrib ${ACIS_LIBS})
 
+IF(CUBIT_LIBRARY_PROPERTIES)
+  SET_TARGET_PROPERTIES(gtcAttrib
+                        PROPERTIES ${CUBIT_LIBRARY_PROPERTIES})
+ENDIF(CUBIT_LIBRARY_PROPERTIES)
 
-IF(UNIX)
-ADD_CUSTOM_TARGET(switch_acis ${CMAKE_MAKE_PROGRAM} clean)
-ENDIF(UNIX)
+INSTALL(TARGETS gtcAttrib
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+        LIBRARY DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+        )
 
-INSTALL_TARGETS(/${CMAKE_INSTALL_BINARY_DIR} gtcAttrib)
-
+ENDIF(IGTO_BUILD)

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/Makefile
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/Makefile	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/Makefile	2010-01-27 02:15:23 UTC (rev 3496)
@@ -1,5 +1,5 @@
 ##---------------------------------------------------------------------------
-## $Id: Makefile,v 1.1 2006/06/09 13:38:52 rakerr Exp $
+## $Id: Makefile,v 1.1 2006-06-09 13:38:52 rakerr Exp $
 ##===========================================================================
 
 SOURCE_DIR = ./src
@@ -130,10 +130,7 @@
 include make.depend.$(MACHINE_TYPE)
 
 ##---------------------------------------------------------------------------
-## $Log: Makefile,v $
-## Revision 1.1  2006/06/09 13:38:52  rakerr
-## Adding gtcAttrib files.
-##
+## $Log: not supported by cvs2svn $
 ## Revision 1.2  2006/05/30 14:16:24  prwolfe
 ## New version numbners and added check for get_name not to return the generic
 ##    names managed by the gto backpointer attribute.


Property changes on: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/incl
___________________________________________________________________
Added: svn:mergeinfo
   + 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/incl/attrib_gtc_export.h
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/incl/attrib_gtc_export.h	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/incl/attrib_gtc_export.h	2010-01-27 02:15:23 UTC (rev 3496)
@@ -3,14 +3,16 @@
 #ifndef ATTRIB_GTC_EXPORT_H
 #define ATTRIB_GTC_EXPORT_H
 
-#if defined( _WIN32)
+#if defined( _WIN32) && !defined(CAT)
 #if defined(gtcAttrib_EXPORTS)
-#define DECL_GTCATTRIB __declspec(dllexport)
+# define DECL_GTCATTRIB __declspec(dllexport)
 #else
-#define DECL_GTCATTRIB __declspec(dllimport)
+# define DECL_GTCATTRIB __declspec(dllimport)
 #endif
+#elif defined(__GNUC__) && __GNUC__ >= 4
+# define DECL_GTCATTRIB __attribute__ ((visibility("default")))
 #else
-#define DECL_GTCATTRIB
+# define DECL_GTCATTRIB
 #endif
 
 


Property changes on: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/src
___________________________________________________________________
Added: svn:mergeinfo
   + 

Modified: cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/src/attrib_gtc.C
===================================================================
--- cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/src/attrib_gtc.C	2010-01-27 01:06:43 UTC (rev 3495)
+++ cgm/branches/merge-cubit12/geom/ACIS_SRC/gtcAttrib/src/attrib_gtc.C	2010-01-27 02:15:23 UTC (rev 3496)
@@ -22,5 +22,5 @@
 
 #define ATTRIB_GTC_NAME "gtc"
 
-MASTER_ATTRIB_DEFN( "gtc master attribute" )
+MASTER_ATTRIB_DEFN( "gtc master attribute" );
 



More information about the cgma-dev mailing list