[cgma-dev] r3423 - in cgm/branches/cubit: . geom geom/Cholla geom/facet geom/facetbool geom/parallel geom/testing geom/testing/data geom/virtual util util/OtherFiles

kraftche at cae.wisc.edu kraftche at cae.wisc.edu
Wed Jan 6 13:22:16 CST 2010


Author: kraftche
Date: 2010-01-06 13:22:14 -0600 (Wed, 06 Jan 2010)
New Revision: 3423

Added:
   cgm/branches/cubit/geom/AutoMidsurfaceTool.cpp
   cgm/branches/cubit/geom/AutoMidsurfaceTool.hpp
   cgm/branches/cubit/geom/CGMHistory.cpp
   cgm/branches/cubit/geom/CGMHistory.hpp
   cgm/branches/cubit/geom/Cholla/ChollaVolume.cpp
   cgm/branches/cubit/geom/Cholla/ChollaVolume.hpp
   cgm/branches/cubit/geom/Cholla/FacetorUtil.cpp
   cgm/branches/cubit/geom/Cholla/FacetorUtil.hpp
   cgm/branches/cubit/geom/GfxPreview.cpp
   cgm/branches/cubit/geom/GfxPreview.hpp
   cgm/branches/cubit/geom/PeriodicParamTool.cpp
   cgm/branches/cubit/geom/PeriodicParamTool.hpp
   cgm/branches/cubit/geom/testing/
   cgm/branches/cubit/geom/testing/AngleCalc.cpp
   cgm/branches/cubit/geom/testing/CMakeLists.txt
   cgm/branches/cubit/geom/testing/CreateGeometry.cpp
   cgm/branches/cubit/geom/testing/GraphicsData.cpp
   cgm/branches/cubit/geom/testing/Makefile.am
   cgm/branches/cubit/geom/testing/ReadIgesFile.cpp
   cgm/branches/cubit/geom/testing/TestConfig.h.in
   cgm/branches/cubit/geom/testing/TestUtilities.cpp
   cgm/branches/cubit/geom/testing/TestUtilities.hpp
   cgm/branches/cubit/geom/testing/cgm_test.cpp
   cgm/branches/cubit/geom/testing/cgm_test.hpp
   cgm/branches/cubit/geom/testing/cgm_test_script
   cgm/branches/cubit/geom/testing/data/
   cgm/branches/cubit/geom/testing/data/brick.iges
   cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.cpp
   cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.hpp
   cgm/branches/cubit/util/CommandFeedback.hpp
   cgm/branches/cubit/util/CubitUndo.cpp
   cgm/branches/cubit/util/CubitUndo.hpp
   cgm/branches/cubit/util/ExternalCoordinateSystem.hpp
   cgm/branches/cubit/util/GlobalCommandFeedback.cpp
   cgm/branches/cubit/util/GlobalCommandFeedback.hpp
   cgm/branches/cubit/util/ManagedPtrVector.hpp
   cgm/branches/cubit/util/OrderedMap.hpp
   cgm/branches/cubit/util/OrderedSet.hpp
Modified:
   cgm/branches/cubit/configure.in
   cgm/branches/cubit/geom/AnalyticGeometryTool.cpp
   cgm/branches/cubit/geom/AnalyticGeometryTool.hpp
   cgm/branches/cubit/geom/Body.cpp
   cgm/branches/cubit/geom/Body.hpp
   cgm/branches/cubit/geom/BoundingBoxTool.cpp
   cgm/branches/cubit/geom/BoundingBoxTool.hpp
   cgm/branches/cubit/geom/CADefines.hpp
   cgm/branches/cubit/geom/CAEntityId.cpp
   cgm/branches/cubit/geom/CAMergePartner.cpp
   cgm/branches/cubit/geom/CGMApp.cpp
   cgm/branches/cubit/geom/CGMApp.hpp
   cgm/branches/cubit/geom/CGMEngineDynamicLoader.cpp
   cgm/branches/cubit/geom/CMakeLists.txt
   cgm/branches/cubit/geom/Cholla/CMakeLists.txt
   cgm/branches/cubit/geom/Cholla/Cholla.cpp
   cgm/branches/cubit/geom/Cholla/ChollaCurve.cpp
   cgm/branches/cubit/geom/Cholla/ChollaCurve.hpp
   cgm/branches/cubit/geom/Cholla/ChollaEngine.cpp
   cgm/branches/cubit/geom/Cholla/ChollaEngine.hpp
   cgm/branches/cubit/geom/Cholla/ChollaPoint.cpp
   cgm/branches/cubit/geom/Cholla/ChollaPoint.hpp
   cgm/branches/cubit/geom/Cholla/ChollaSurface.cpp
   cgm/branches/cubit/geom/Cholla/ChollaSurface.hpp
   cgm/branches/cubit/geom/Cholla/CubitFacet.cpp
   cgm/branches/cubit/geom/Cholla/CubitFacet.hpp
   cgm/branches/cubit/geom/Cholla/CubitFacetData.cpp
   cgm/branches/cubit/geom/Cholla/CubitFacetData.hpp
   cgm/branches/cubit/geom/Cholla/CubitFacetEdge.hpp
   cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.cpp
   cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.hpp
   cgm/branches/cubit/geom/Cholla/FacetDataUtil.cpp
   cgm/branches/cubit/geom/Cholla/FacetDataUtil.hpp
   cgm/branches/cubit/geom/Cholla/FacetEvalTool.cpp
   cgm/branches/cubit/geom/Cholla/FacetEvalTool.hpp
   cgm/branches/cubit/geom/Cholla/FacetorTool.cpp
   cgm/branches/cubit/geom/Cholla/FacetorTool.hpp
   cgm/branches/cubit/geom/Cholla/LoopParamTool.cpp
   cgm/branches/cubit/geom/Cholla/LoopParamTool.hpp
   cgm/branches/cubit/geom/Cholla/Makefile.am
   cgm/branches/cubit/geom/Cholla/TDGeomFacet.cpp
   cgm/branches/cubit/geom/Cholla/TDGeomFacet.hpp
   cgm/branches/cubit/geom/Cholla/debug.cpp
   cgm/branches/cubit/geom/Cholla/debug.hpp
   cgm/branches/cubit/geom/CubitAttrib.cpp
   cgm/branches/cubit/geom/CubitAttribUser.cpp
   cgm/branches/cubit/geom/CubitAttribUser.hpp
   cgm/branches/cubit/geom/CubitGeomConfigure.h.in
   cgm/branches/cubit/geom/Curve.cpp
   cgm/branches/cubit/geom/CurveOverlapFacet.cpp
   cgm/branches/cubit/geom/CurveOverlapFacet.hpp
   cgm/branches/cubit/geom/DAG.hpp
   cgm/branches/cubit/geom/DagDrawingTool.hpp
   cgm/branches/cubit/geom/GSaveOpen.cpp
   cgm/branches/cubit/geom/GSaveOpen.hpp
   cgm/branches/cubit/geom/GeomMeasureTool.cpp
   cgm/branches/cubit/geom/GeomMeasureTool.hpp
   cgm/branches/cubit/geom/GeometryFeatureTool.hpp
   cgm/branches/cubit/geom/GeometryHealerTool.cpp
   cgm/branches/cubit/geom/GeometryHealerTool.hpp
   cgm/branches/cubit/geom/GeometryModifyEngine.cpp
   cgm/branches/cubit/geom/GeometryModifyEngine.hpp
   cgm/branches/cubit/geom/GeometryModifyTool.cpp
   cgm/branches/cubit/geom/GeometryModifyTool.hpp
   cgm/branches/cubit/geom/GeometryQueryEngine.cpp
   cgm/branches/cubit/geom/GeometryQueryEngine.hpp
   cgm/branches/cubit/geom/GeometryQueryTool.cpp
   cgm/branches/cubit/geom/GeometryQueryTool.hpp
   cgm/branches/cubit/geom/GroupingEntity.cpp
   cgm/branches/cubit/geom/IntermediateGeomEngine.hpp
   cgm/branches/cubit/geom/Loop.cpp
   cgm/branches/cubit/geom/Loop.hpp
   cgm/branches/cubit/geom/LoopSM.hpp
   cgm/branches/cubit/geom/Lump.hpp
   cgm/branches/cubit/geom/Makefile.am
   cgm/branches/cubit/geom/MergeTool.cpp
   cgm/branches/cubit/geom/MergeTool.hpp
   cgm/branches/cubit/geom/ModelQueryEngine.hpp
   cgm/branches/cubit/geom/OffsetSplitTool.cpp
   cgm/branches/cubit/geom/RefEdge.cpp
   cgm/branches/cubit/geom/RefEdge.hpp
   cgm/branches/cubit/geom/RefEntity.cpp
   cgm/branches/cubit/geom/RefEntity.hpp
   cgm/branches/cubit/geom/RefEntityFactory.cpp
   cgm/branches/cubit/geom/RefEntityFactory.hpp
   cgm/branches/cubit/geom/RefEntityName.cpp
   cgm/branches/cubit/geom/RefEntityName.hpp
   cgm/branches/cubit/geom/RefFace.cpp
   cgm/branches/cubit/geom/RefFace.hpp
   cgm/branches/cubit/geom/RefGroup.cpp
   cgm/branches/cubit/geom/RefVertex.cpp
   cgm/branches/cubit/geom/RefVolume.cpp
   cgm/branches/cubit/geom/RefVolume.hpp
   cgm/branches/cubit/geom/SenseEntity.hpp
   cgm/branches/cubit/geom/SplitSurfaceTool.cpp
   cgm/branches/cubit/geom/SplitSurfaceTool.hpp
   cgm/branches/cubit/geom/SurfParamTool.cpp
   cgm/branches/cubit/geom/SurfParamTool.hpp
   cgm/branches/cubit/geom/Surface.hpp
   cgm/branches/cubit/geom/SurfaceOverlapFacet.cpp
   cgm/branches/cubit/geom/SurfaceOverlapFacet.hpp
   cgm/branches/cubit/geom/SurfaceOverlapTool.cpp
   cgm/branches/cubit/geom/SurfaceOverlapTool.hpp
   cgm/branches/cubit/geom/TDSplitSurface.cpp
   cgm/branches/cubit/geom/TDSplitSurface.hpp
   cgm/branches/cubit/geom/TDUniqueId.cpp
   cgm/branches/cubit/geom/TopologyBridge.cpp
   cgm/branches/cubit/geom/TopologyBridge.hpp
   cgm/branches/cubit/geom/facet/FacetCurve.cpp
   cgm/branches/cubit/geom/facet/FacetLoop.cpp
   cgm/branches/cubit/geom/facet/FacetLoop.hpp
   cgm/branches/cubit/geom/facet/FacetModifyEngine.cpp
   cgm/branches/cubit/geom/facet/FacetModifyEngine.hpp
   cgm/branches/cubit/geom/facet/FacetParamTool.cpp
   cgm/branches/cubit/geom/facet/FacetParamTool.hpp
   cgm/branches/cubit/geom/facet/FacetQueryEngine.cpp
   cgm/branches/cubit/geom/facet/FacetQueryEngine.hpp
   cgm/branches/cubit/geom/facet/FacetboolInterface.cpp
   cgm/branches/cubit/geom/facetbool/FBRetriangulate.cpp
   cgm/branches/cubit/geom/parallel/Makefile.am
   cgm/branches/cubit/geom/virtual/CMakeLists.txt
   cgm/branches/cubit/geom/virtual/CollapseCurveTool.cpp
   cgm/branches/cubit/geom/virtual/CollapseCurveTool.hpp
   cgm/branches/cubit/geom/virtual/CompSurfFacets.cpp
   cgm/branches/cubit/geom/virtual/CompositeEngine.cpp
   cgm/branches/cubit/geom/virtual/CompositeEngine.hpp
   cgm/branches/cubit/geom/virtual/CompositeGeom.cpp
   cgm/branches/cubit/geom/virtual/CompositeGeom.hpp
   cgm/branches/cubit/geom/virtual/CompositeLoop.cpp
   cgm/branches/cubit/geom/virtual/CompositeLoop.hpp
   cgm/branches/cubit/geom/virtual/CompositeSurface.cpp
   cgm/branches/cubit/geom/virtual/CompositeSurface.hpp
   cgm/branches/cubit/geom/virtual/CompositeTool.cpp
   cgm/branches/cubit/geom/virtual/FacetProjectTool.cpp
   cgm/branches/cubit/geom/virtual/FacetProjectTool.hpp
   cgm/branches/cubit/geom/virtual/Faceter.cpp
   cgm/branches/cubit/geom/virtual/ImprintBoundaryTool.cpp
   cgm/branches/cubit/geom/virtual/Makefile.am
   cgm/branches/cubit/geom/virtual/PST_Data.cpp
   cgm/branches/cubit/geom/virtual/PartSurfFacetTool.cpp
   cgm/branches/cubit/geom/virtual/PartitionEngine.cpp
   cgm/branches/cubit/geom/virtual/PartitionEngine.hpp
   cgm/branches/cubit/geom/virtual/PartitionLoop.cpp
   cgm/branches/cubit/geom/virtual/PartitionLoop.hpp
   cgm/branches/cubit/geom/virtual/PartitionSurface.cpp
   cgm/branches/cubit/geom/virtual/PartitionTool.cpp
   cgm/branches/cubit/geom/virtual/RemoveBlends.cpp
   cgm/branches/cubit/geom/virtual/SimplifyTool.cpp
   cgm/branches/cubit/geom/virtual/SimplifyTool.hpp
   cgm/branches/cubit/geom/virtual/SubCurve.cpp
   cgm/branches/cubit/geom/virtual/SubSurface.cpp
   cgm/branches/cubit/geom/virtual/VGLoopTool.cpp
   cgm/branches/cubit/geom/virtual/VirtualQueryEngine.cpp
   cgm/branches/cubit/geom/virtual/VirtualQueryEngine.hpp
   cgm/branches/cubit/util/AppUtil.cpp
   cgm/branches/cubit/util/AppUtil.hpp
   cgm/branches/cubit/util/ArrayBasedContainer.cpp
   cgm/branches/cubit/util/CMakeLists.txt
   cgm/branches/cubit/util/CastTo.hpp
   cgm/branches/cubit/util/CpuTimer.cpp
   cgm/branches/cubit/util/CpuTimer.hpp
   cgm/branches/cubit/util/CubitBox.cpp
   cgm/branches/cubit/util/CubitBox.hpp
   cgm/branches/cubit/util/CubitColorConstants.hpp
   cgm/branches/cubit/util/CubitCoordinateSystem.cpp
   cgm/branches/cubit/util/CubitDefines.h
   cgm/branches/cubit/util/CubitDynamicLoader.cpp
   cgm/branches/cubit/util/CubitEntity.cpp
   cgm/branches/cubit/util/CubitEventDefines.h
   cgm/branches/cubit/util/CubitFile.cpp
   cgm/branches/cubit/util/CubitFile.hpp
   cgm/branches/cubit/util/CubitFileFEModel.cpp
   cgm/branches/cubit/util/CubitFileFEModel.hpp
   cgm/branches/cubit/util/CubitFileIOWrapper.cpp
   cgm/branches/cubit/util/CubitFileIOWrapper.hpp
   cgm/branches/cubit/util/CubitFileMetaData.cpp
   cgm/branches/cubit/util/CubitFileUtil.cpp
   cgm/branches/cubit/util/CubitInputFile.hpp
   cgm/branches/cubit/util/CubitMatrix.cpp
   cgm/branches/cubit/util/CubitMessage.cpp
   cgm/branches/cubit/util/CubitMessage.hpp
   cgm/branches/cubit/util/CubitPlane.cpp
   cgm/branches/cubit/util/CubitPlane.hpp
   cgm/branches/cubit/util/CubitStack.cpp
   cgm/branches/cubit/util/CubitString.cpp
   cgm/branches/cubit/util/CubitString.hpp
   cgm/branches/cubit/util/CubitTransformMatrix.cpp
   cgm/branches/cubit/util/CubitTransformMatrix.hpp
   cgm/branches/cubit/util/CubitUtil.cpp
   cgm/branches/cubit/util/CubitUtil.hpp
   cgm/branches/cubit/util/CubitUtilConfigure.h.in
   cgm/branches/cubit/util/CubitVector.cpp
   cgm/branches/cubit/util/CubitVector.hpp
   cgm/branches/cubit/util/DIntArray.cpp
   cgm/branches/cubit/util/DLIList.cpp
   cgm/branches/cubit/util/DLIList.hpp
   cgm/branches/cubit/util/DLList.hpp
   cgm/branches/cubit/util/DynamicArray.cpp
   cgm/branches/cubit/util/DynamicArray.hpp
   cgm/branches/cubit/util/ElementType.h
   cgm/branches/cubit/util/GMem.cpp
   cgm/branches/cubit/util/GeometryDefines.h
   cgm/branches/cubit/util/GetLongOpt.hpp
   cgm/branches/cubit/util/GfxDebug.cpp
   cgm/branches/cubit/util/GfxDebug.hpp
   cgm/branches/cubit/util/IntersectionTool.cpp
   cgm/branches/cubit/util/IntersectionTool.hpp
   cgm/branches/cubit/util/KDDTree.cpp
   cgm/branches/cubit/util/Makefile.am
   cgm/branches/cubit/util/MemoryBlock.hpp
   cgm/branches/cubit/util/MemoryManager.cpp
   cgm/branches/cubit/util/MemoryManager.hpp
   cgm/branches/cubit/util/OctTree.cpp
   cgm/branches/cubit/util/OtherFiles/make.client
   cgm/branches/cubit/util/ParamTool.hpp
   cgm/branches/cubit/util/PlanarParamTool.cpp
   cgm/branches/cubit/util/PlanarParamTool.hpp
   cgm/branches/cubit/util/PriorityQueue.cpp
   cgm/branches/cubit/util/RTree.cpp
   cgm/branches/cubit/util/RTree.hpp
   cgm/branches/cubit/util/RandomMersenne.cpp
   cgm/branches/cubit/util/SDLList.cpp
   cgm/branches/cubit/util/SDLList.hpp
   cgm/branches/cubit/util/SettingHandler.cpp
   cgm/branches/cubit/util/SettingHandler.hpp
   cgm/branches/cubit/util/TextProgressTool.cpp
   cgm/branches/cubit/util/ToolData.cpp
   cgm/branches/cubit/util/ToolData.hpp
   cgm/branches/cubit/util/ToolDataUser.cpp
   cgm/branches/cubit/util/ToolDataUser.hpp
   cgm/branches/cubit/util/TtyProgressTool.cpp
Log:
CGM from Cubit 12.0 (w/out ACIS)

Modified: cgm/branches/cubit/configure.in
===================================================================
--- cgm/branches/cubit/configure.in	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/configure.in	2010-01-06 19:22:14 UTC (rev 3423)
@@ -12,7 +12,7 @@
 AC_PROG_LIBTOOL
 LIBS="-lm"
 AC_PROG_LIBTOOL
-AC_C_BIGENDIAN( [LITTLE_ENDIAN=], [LITTLE_ENDIAN="-DLITTLE_ENDIAN=BYTE_ORDER"] )
+AC_C_BIGENDIAN( [LITTLE_ENDIAN=], [LITTLE_ENDIAN=-DLITTLE_ENDIAN] )
 AC_SUBST(LITTLE_ENDIAN)
 
 

Modified: cgm/branches/cubit/geom/AnalyticGeometryTool.cpp
===================================================================
--- cgm/branches/cubit/geom/AnalyticGeometryTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/AnalyticGeometryTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -17,6 +17,8 @@
 #include "DLIList.hpp"
 #include <math.h>
 #include "CastTo.hpp"
+#include "GfxPreview.hpp"
+#include "GMem.hpp"
 
 #include <fstream>
 using std::cout;
@@ -144,6 +146,7 @@
 
 AnalyticGeometryTool::~AnalyticGeometryTool()
 {
+  instance_ = NULL;
 }
 
 //***************************************************************************
@@ -1996,57 +1999,85 @@
    double cubit2pln_mtx[4][4],
       pln2cubit_mtx[4][4];
    double pln_orig[3];
+   double box_tol = 1e-6;
 
+   // Adjust bounding box if it is zero in any direction
+   double abox_min[3], abox_max[3];
+   copy_pnt( box_min, abox_min );
+   copy_pnt( box_max, abox_max );
+
+   double x_range = fabs(box_max[0]-box_min[0]);
+   double y_range = fabs(box_max[1]-box_min[1]);
+   double z_range = fabs(box_max[2]-box_min[2]);
+
+   if( x_range < box_tol || y_range < box_tol || z_range < box_tol )
+   {
+     // Adjust zero length side(s) to maximum range
+     double adj = CUBIT_MAX((CUBIT_MAX((x_range),(y_range))),(z_range))/2.0;
+
+     // Arbitrarily expand box if it is zero in size
+     if( adj < box_tol )
+       adj = 5.0;  
+
+     if( x_range < box_tol )
+     {
+       abox_min[0] -= adj;
+       abox_max[0] += adj;
+     }
+     if( y_range < box_tol )
+     {
+       abox_min[1] -= adj;
+       abox_max[1] += adj;
+     }
+     if( z_range < box_tol )
+     {
+       abox_min[2] -= adj;
+       abox_max[2] += adj;
+     }
+   }
+
+   // Get plane origin
    double A = pln_norm[0];
    double B = pln_norm[1];
    double C = pln_norm[2];
    double D = pln_coeff;
-
-   //PRINT_INFO( "A=%0.4lf, B=%0.4lf, C=%0.4lf, D=%0.4lf\n", A, B, C, D );
-
    get_pln_orig_norm( A, B, C, D, pln_orig );
 
-//   PRINT_INFO( "Plane Orig = %0.4lf, %0.4lf, %0.4lf\n", pln_orig[0],
-//      pln_orig[1], pln_orig[2] );
-
-   // Find intersections of edges with plane.  Add to unique
-   // array.  At most there are 6 intersections...
+   // Find intersections of edges with plane.  Add to unique array.  At most
+   // there are 6 intersections...
    double int_array[6][3];
    int num_int = 0;
-   num_int = get_plane_bbox_intersections( box_min, box_max, pln_orig, pln_norm, int_array );
+   num_int = get_plane_bbox_intersections( abox_min, abox_max, pln_orig, pln_norm,
+     int_array );
 
-   //attempt to adjust bounding box to x,y,z intercepts of plane
-   if( num_int == 0 )
+   // Adjust so plane intercepts bounding box
+   if( num_int < 3 )
    {
-     //Stretch bounding box so that plane will fit, for sure
-     //get x,y,z intercepts
-     double x_intercept = 0;
-     double y_intercept = 0;
-     double z_intercept = 0;
-     if( !dbl_eq( A, 0.0 ) )
-       x_intercept = -D/A;
-     if( !dbl_eq( B, 0.0 ) )
-       y_intercept = -D/B;
-     if( !dbl_eq( C, 0.0 ) )
-       z_intercept = -D/C;
-    
-    //adjust box 
-    if( x_intercept < box_min[0] )
-      box_min[0] = x_intercept;
-    else if( x_intercept > box_max[0] )
-      box_max[0] = x_intercept;
+     // Move the plane to the center of the bounding box
+     double box_cent[3];
+     box_cent[0] = (abox_min[0]+abox_max[0])/2.0;
+     box_cent[1] = (abox_min[1]+abox_max[1])/2.0;
+     box_cent[2] = (abox_min[2]+abox_max[2])/2.0;
 
-    if( y_intercept < box_min[1] )
-      box_min[1] = y_intercept;
-    else if( y_intercept > box_max[1] )
-      box_max[1] = y_intercept;
-      
-    if( z_intercept < box_min[2] )
-      box_min[2] = z_intercept;
-    else if( z_intercept > box_max[2] )
-      box_max[2] = z_intercept;
+     // Get the intersections
+     num_int = get_plane_bbox_intersections( abox_min, abox_max, box_cent, pln_norm, int_array );
 
-     num_int = get_plane_bbox_intersections( box_min, box_max, pln_orig, pln_norm, int_array );
+     // Project the points back to the original plane
+     switch (num_int)
+     {
+     case 6:
+       int_pnt_pln( int_array[5], pln_orig, pln_norm, int_array[5] );
+     case 5:
+       int_pnt_pln( int_array[4], pln_orig, pln_norm, int_array[4] );
+     case 4:
+       int_pnt_pln( int_array[3], pln_orig, pln_norm, int_array[3] );
+     case 3:
+       int_pnt_pln( int_array[2], pln_orig, pln_norm, int_array[2] );
+     case 2:
+       int_pnt_pln( int_array[1], pln_orig, pln_norm, int_array[1] );
+     case 1:
+       int_pnt_pln( int_array[0], pln_orig, pln_norm, int_array[0] );
+     }
    }
 
    if( num_int == 0 )
@@ -2152,12 +2183,11 @@
 }
 
 int AnalyticGeometryTool::get_plane_bbox_intersections( double box_min[3],
-                                                           double box_max[3],
-                                                           double pln_orig[3],
-                                                           double pln_norm[3],
-                                                           double int_array[6][3])
+                                                        double box_max[3],
+                                                        double pln_orig[3],
+                                                        double pln_norm[3],
+                                                        double int_array[6][3])
 {
-
    // Fill in an array with all 8 box corners
    double corner[8][3];
    get_box_corners( box_min, box_max, corner );
@@ -2211,7 +2241,7 @@
 }
 
 CubitStatus
-AnalyticGeometryTool::get_tight_bounding_box( DLIList<CubitVector*> &point_list,                                              
+AnalyticGeometryTool::get_tight_bounding_box( DLIList<CubitVector*> &point_list,
                                               CubitVector &center,
                                               CubitVector axes[3],
                                               CubitVector &extension )
@@ -2227,6 +2257,7 @@
    for( i=0; i<num_pnts; i++ )
    {
       vec = point_list.get_and_step();
+      //GfxPreview::draw_point( vec, 3 );
 
       pnt_arr[i].x = vec->x();
       pnt_arr[i].y = vec->y();
@@ -3231,6 +3262,17 @@
     double angle[3];
     InitialGuess(N,pt,angle);
     double oldVolume = Volume(N,pt,angle);
+ 
+  //if initial guess gives angles that are zero, the rest of this code 
+  //can give bounding box that isn't tight.  This probably 
+  //isn't the best fix but it works.  CDE  4-20-2009
+  if( angle[0] == 0 )
+    angle[0] = 0.5;
+  if( angle[1] == 0 )
+    angle[1] = 0.5;
+  if( angle[2] == 0 )
+    angle[2] = 0.5;
+
     double saveAngle[3] = { angle[0], angle[1], angle[2] };
 
     // Powell's direction set method
@@ -6111,7 +6153,7 @@
 //---------------------------------------------------------------------------
 
 double
-AnalyticGeometryTool::AreaIntersection( Triangle &tri1, Triangle &tri2 )
+AnalyticGeometryTool::AreaIntersection( Triangle &tri1, Triangle &tri2  )
 {
   AgtTriList* list = Intersection(&tri1,&tri2);
   double area = Area(list);
@@ -6180,7 +6222,7 @@
 }
 
 double
-AnalyticGeometryTool::ProjectedOverlap( Triangle3& tri1, Triangle3& tri2 )
+AnalyticGeometryTool::ProjectedOverlap( Triangle3& tri1, Triangle3& tri2, bool draw_overlap )
 {
   // Transform both triangles into local coordinate system of tri1
   // to eliminate z-coordinate. 
@@ -6209,9 +6251,10 @@
   origin[1] = tri1.b.y;
   origin[2] = tri1.b.z;
 
+  double mtxTriOne2Global[4][4];
+  vecs_to_mtx( x, y, z, origin, mtxTriOne2Global ); // Really mtxTriOne2Global
   double mtxGlobal2TriOne[4][4];
-  vecs_to_mtx( x, y, z, origin, mtxGlobal2TriOne ); // Really mtxTriOne2Global
-  inv_trans_mtx( mtxGlobal2TriOne, mtxGlobal2TriOne );
+  inv_trans_mtx( mtxTriOne2Global, mtxGlobal2TriOne );
   
   double v0[3], v1[3], v2[3]; // Vertices of triangle
   v0[0]=tri1.b.x;   v0[1]=tri1.b.y;  v0[2]=tri1.b.z;
@@ -6244,5 +6287,63 @@
   T2.v[2].x = v2[0]; T2.v[2].y = v2[1];
 
   // Now find area of overlap
-  return AreaIntersection( T1, T2 );
+  if( draw_overlap )
+  {
+    AgtTriList* list = Intersection(&T1, &T2);
+    double overlap_area = Area(list);
+    while ( list )
+    {
+      Triangle *tmp_tri = list->tri;
+      
+      v0[0]=tmp_tri->v[0].x;   
+      v0[1]=tmp_tri->v[0].y;   
+      v0[2]=0;
+
+      v1[0]=tmp_tri->v[1].x;
+      v1[1]=tmp_tri->v[1].y;
+      v1[2]=0;
+      
+      v2[0]=tmp_tri->v[2].x; 
+      v2[1]=tmp_tri->v[2].y; 
+      v2[2]=0;
+      
+      transform_pnt( mtxTriOne2Global, v0, v0 );
+      transform_pnt( mtxTriOne2Global, v1, v1 );
+      transform_pnt( mtxTriOne2Global, v2, v2 );
+
+      //Now Draw the thing
+       GMem g_mem;
+       g_mem.allocate_tri(1);
+       g_mem.pointListCount = 3;
+      
+       g_mem.point_list()[0].x = v0[0]; 
+       g_mem.point_list()[0].y = v0[1]; 
+       g_mem.point_list()[0].z = v0[2]; 
+        
+       g_mem.point_list()[1].x = v1[0]; 
+       g_mem.point_list()[1].y = v1[1]; 
+       g_mem.point_list()[1].z = v1[2]; 
+        
+       g_mem.point_list()[2].x = v2[0]; 
+       g_mem.point_list()[2].y = v2[1]; 
+       g_mem.point_list()[2].z = v2[2]; 
+
+       g_mem.facet_list()[0] = 3;
+       g_mem.facet_list()[1] = 0;
+       g_mem.facet_list()[2] = 1;
+       g_mem.facet_list()[3] = 2;
+
+       g_mem.fListCount = 1;
+       GfxPreview::draw_polygon(g_mem.point_list(),3,4,4,true);
+
+      AgtTriList* save = list;
+      list = list->next;
+      delete save->tri;
+      delete save;
+    }
+    delete list;
+    return overlap_area;
+  }
+  else
+    return AreaIntersection( T1, T2 );
 }

Modified: cgm/branches/cubit/geom/AnalyticGeometryTool.hpp
===================================================================
--- cgm/branches/cubit/geom/AnalyticGeometryTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/AnalyticGeometryTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -271,6 +271,7 @@
 // END OF MAGIC SOFTWARE
 ///////////////////////////////////////////////////////////////////////////////
 
+//! Performs calculations on analytic geometry.
 class CUBIT_GEOM_EXPORT AnalyticGeometryTool
 {
 public:
@@ -278,29 +279,41 @@
    ~AnalyticGeometryTool();
    static AnalyticGeometryTool* instance();
 
+   static void delete_instance() { if( instance_ ) delete instance_; };
+
    //*********************************************************
    // Double numbers
    //*********************************************************
+
+   /*! Check to see if double numbers are equal within epsilon.
+    Values are equal if fabs(val_1 - val_2) < epsilon.
+    Epsilon is determined by next two functions. */
    CubitBoolean dbl_eq( double val_1, double val_2 );
-   // Check to see if double numbers are equal within epsilon.
-   // Values are equal if fabs(val_1 - val_2) < epsilon.
-   // Epsilon is determined by next two functions.
+
+   //! Get epsilon used for double number comparisons.
+   //! Default value is 1e-6.
    double get_epsilon();
+   //! Set epsilon used for double number comparisons.
+   //! Default value is 1e-6.
    double set_epsilon( double new_epsilon );
-   // Get/set epsilon used for double number comparisons.
-   // Default value is 1e-6.
+
 #ifdef BOYD14
+   //! Swap two double number memory locations.
    void swap_dbl(double& dbl1,double& dbl2);
-   // Swap two double number memory locations.
+
+   //! Find minimum array of double numbers.
+   //! Position in array is returned as well.
    double min_array( const double *array, int len, int &pos );
+
+   //! Find maximum array of double numbers.
+   //! Position in array is returned as well.
    double max_array( const double *array, int len, int &pos );
-   // Find minimum or maximum of an array of double numbers.
-   // Position in array is returned as well.
 #endif
+
+   /*! Round value to either -1, 0, or 1 if within epsilon to
+    to one of these.  Epsilon determined by get_epsilon/set_epsilon
+    functions. */
    void round_near_val( double& val );
-   // Round value to either -1, 0, or 1 if within epsilon to
-   // to one of these.  Epsilon determined by get_epsilon/set_epsilon
-   // functions.
 
    //**************************************************************************
    // Matrices & Transforms
@@ -314,20 +327,27 @@
    //                            | x3 y3 z3 0 |
    //			                     | ox oy oz 1 |
    //			                      -          -
+   /*! This functions applies the transformation matrix to the specified
+       point and returns the new point coordinates through the call list.
+       Point in and point out can be the same memory address or different. */
    void transform_pnt( double m[4][4], double pin[3], double pout[3] );
-   // This functions applies the transformation matrix to the specified
-   // point and returns the new point coordinates through the call list.
-   // Point in and point out can be the same memory address or different.
+
 #ifdef BOYD14
+   //! Transform a point array.  Points can be transformed in place.
    void transform_pnt_arr( double m[4][4], double pin_arr[][3], 
                            size_t num_pnts, double pout_arr[][3] );
-   // Transform a point array.  Points can be transformed in place.
 #endif
+
+   /*! This routine applies a transformation matrix to a specified vector
+      and returns the new vector orientation.  Vector in and vector out can
+      be the same memory address or different. */
    void transform_vec( double m3[3][3], double vin[3], double vout[3] );
+
+   /*! This routine applies a transformation matrix to a specified vector
+      and returns the new vector orientation.  Vector in and vector out can
+      be the same memory address or different. */
    void transform_vec( double m4[4][4], double vin[3], double vout[3] );
-   // This routine applies a transformation matrix to a specified vector
-   // and returns the new vector orientation.  Vector in and vector out can
-   // be the same memory address or different.
+
 #ifdef BOYD14
    double transform_dist( double m3[3][3], double distance, double v[3] );
    double transform_dist( double m4[4][4], double distance, double v[3] );
@@ -339,47 +359,68 @@
    // 6 units covers in the x-direction may not equal the distance 6 units
    // covers in the y-direction - a rectangular system!).
 #endif
+   /*! Transforms a line using the given transformation mtx.  The mtx is typically
+    built using add_origin_to_rotation_mtx. */
    void transform_line( double rot_mtx[4][4], double origin[3], double axis[3] );
+   /*! Transforms a line using the given transformation mtx.  The mtx is typically
+    built using add_origin_to_rotation_mtx. */
    void transform_line( double rot_mtx[4][4], CubitVector &origin, CubitVector &axis );
-   // Transforms a line using the given transformation mtx.  The mtx is typically
-   // built using add_origin_to_rotation_mtx.
+
+  
+   //@{ 
+   /*! This routine simply copies one matrix to another.  If a NULL is passed in
+   for the from matrix, then the identity matrix is copied into the out matrix.
+   Last function allows you to specify 1st 3 doubles of row 4 (origin) of the 
+   4x4 matrix.*/ 
    void copy_mtx( double from[3][3],double to[3][3] );
    void copy_mtx( double from[4][4], double to[4][4] );
    void copy_mtx( double from[4][4], double to[3][3] );
    void copy_mtx(double from[3][3], double to[4][4], double *origin = NULL );
-   // This routine simply copies one matrix to another.  If a NULL is passed in
-   // for the from matrix, then the identity matrix is copied into the out matrix.
-   // Last function allows you to specify 1st 3 doubles of row 4 (origin) of the 
-   // 4x4 matrix.
+   //@}
+
+   //@{
+   //! This routine determines the tranformation matrix given the theta and
+   //! the vector to cross through.
    void create_rotation_mtx( double theta, double v[3], double mtx3x3[3][3] );
    void create_rotation_mtx( double theta, double v[3], double mtx4x4[4][4] );
-   // This routine determines the tranformation matrix given the theta and
-   // the vector to cross through.
+   //@}
+
+   /*! Adds origin to rotation matrix, so you can rotate points about a line.
+   Line is defined as original vector used in create_rotation_mtx and
+   the origin. */
    void add_origin_to_rotation_mtx( double rot_mtx[4][4], double origin[3] );
-   // Adds origin to rotation matrix, so you can rotate points about a line.
-   // Line is defined as original vector used in create_rotation_mtx and
-   // the origin.
+
+   //@{
+   //! \brief Simply sets the given matrix to the identity matrix.
    void identity_mtx( double mtx3x3[3][3] );
    void identity_mtx( double mtx4x4[4][4] );
-   // Simply sets the given matrix to the identity matrix.
+   //@}
+
+   //@{
+   //! Gets rotation angles to rotate one system to another - returned rotation 
+   //! angles are about global system.
+   //! To use the result from this function, align the unoriented object's origin 
+   //! with the global origin, then apply the rotation angles returned from this 
+   //! routine to the object in the order of ax,ay,az about the global origin.  
+   //! The object will be oriented such that its xyz axes will point in the same
+   //! direction as the object whose transformation matrix was given.  The object
+   //! can then be translated.
    void mtx_to_angs( double mtx3x3[3][3], double &ax, double &ay, double &az );
    void mtx_to_angs( double mtx4x4[4][4], double &ax, double &ay, double &az );
-   // Gets rotation angles to rotate one system to another - returned rotation 
-   // angles are about global system.
-   // To use the result from this function, align the unoriented object's origin 
-   // with the global origin, then apply the rotation angles returned from this 
-   // routine to the object in the order of ax,ay,az about the global origin.  
-   // The object will be oriented such that its xyz axes will point in the same
-   // direction as the object whose transformation matrix was given.  The object
-   // can then be translated.
+   //@}
+
+  
+   //@{
+   // This routine rotates a 3x3 system given a transformation matrix.  The 
+   // matrix can be rotated in place by sending same variable in & out, or a 
+   // new matrix can be created.  In the 4x4 case, the translation portion
+   // of the matrix is unchanged.
    void rotate_system( double mtx[3][3], double sys_in[3][3], 
                        double sys_out[3][3] );
    void rotate_system( double mtx[4][4], double sys_in[4][4], 
                        double sys_out[4][4] );
-   // This routine rotates a 3x3 system given a transformation matrix.  The 
-   // matrix can be rotated in place by sending same variable in & out, or a 
-   // new matrix can be created.  In the 4x4 case, the translation portion
-   // of the matrix is unchanged.
+   //@}
+
 #ifdef BOYD14
    double mtx_to_ratio( double m3[3][3] );
    double mtx_to_ratio( double m4[4][4] );
@@ -387,324 +428,384 @@
    // length in the first system.  Multiply the length in system 1 by this 
    // ratio to get the length in system 2.
 #endif
+
+   //! Find determinant of matrix.
    double det_mtx( double m[3][3] );
-   // Find determinant of matrix.
+
+   //@{
+   // Multiply matrices together.  If any input is NULL, the identity
+   // matrix is used in its place.
    void mult_mtx( double a[3][3],double b[3][3], double d[3][3] );
    void mult_mtx( double a[4][4], double b[4][4], double d[4][4] );
-   // Multiply matrices together.  If any input is NULL, the identity
-   // matrix is used in its place.
+   //@}
+
+   //!This routine inverts a 3x3 matrix using the adjoint method.  If NULL 
+   //! is sent in for first matrix, the second matrix is set to the identity 
+   //! matrix.  If the same memory address is passed in for both incoming and 
+   //! outgoing matrices, the matrix is inverted in place.  Returns CUBIT_FAILURE
+   //! if no inverse exists.
    CubitStatus inv_mtx_adj( double mtx[3][3], double inv_mtx[3][3] );
-   //This routine inverts a 3x3 matrix using the adjoint method.  If NULL 
-   // is sent in for first matrix, the second matrix is set to the identity 
-   // matrix.  If the same memory address is passed in for both incoming and 
-   // outgoing matrices, the matrix is inverted in place.  Returns CUBIT_FAILURE
-   // if no inverse exists.
+
+   //! This routine inverts a 4x4 transformation matrix.  If NULL is sent in 
+   //! for first matrix, the second matrix is set to the identity matrix.  If 
+   //! the same memory address is passed in for both incoming and outgoing matrices, 
+   //! the matrix is inverted in place.  Uses LU decomposition.
    CubitStatus inv_trans_mtx( double transf[4][4], double inv_transf[4][4] );
-   // This routine inverts a 4x4 transformation matrix.  If NULL is sent in 
-   // for first matrix, the second matrix is set to the identity matrix.  If 
-   // the same memory address is passed in for both incoming and outgoing matrices, 
-   // the matrix is inverted in place.  Uses LU decomposition.
+
+   //@{
+   //! Creates a transformation matrix given three vectors (and origin
+   //! for 4x4 case).
    void vecs_to_mtx( double xvec[3], double yvec[3], double zvec[3], 
                      double matrix[3][3] );
    void vecs_to_mtx( double xvec[3], double yvec[3], double zvec[3], 
                      double origin[3], double matrix[4][4] );
-   // Creates a transformation matrix given three vectors (and origin
-   // for 4x4 case).
+   //@}
+
 #ifdef BOYD14
+   //@{
+   //! Extract vectors from a matrix.  NULL can be input for any of the
+   //! arguments and the routine will not extract that vector.  NULL can
+   //! also be input for the matrix, in which case the function assumes
+   //! the identity matrix.
    void mtx_to_vecs( double matrix[3][3], double xvec[3], double yvec[3], 
                      double zvec[3] );
    void mtx_to_vecs( double matrix[4][4], double xvec[3], double yvec[3], 
                      double zvec[3], double origin[3] );
-   // Extract vectors from a matrix.  NULL can be input for any of the
-   // arguments and the routine will not extract that vector.  NULL can
-   // also be input for the matrix, in which case the function assumes
-   // the identity matrix.
+   //@}
 #endif
-
+    
+   //@{
+   //! Prints matrix values, for debugging.
    void print_mtx( double mtx[3][3] );
    void print_mtx( double mtx[4][4] );
-   // Prints matrix values, for debugging.
+   //@}
 
    //**************************************************************************
    // 3D Points
    //**************************************************************************
+   //! Copy one double[3] point to another double[3] point (uses memcpy).
+   //! If first point in NULL then second point is set to 0,0,0.
    void copy_pnt( double pnt_in[3], double pnt_out[3] );
-   // Copy one double[3] point to another double[3] point (uses memcpy).
-   // If first point in NULL then second point is set to 0,0,0.
+
+   //@{
+   //! For going back and forth from CubitVectors
    void copy_pnt( double pnt_in[3], CubitVector &cubit_vec );
    void copy_pnt( CubitVector &cubit_vec, double pnt_out[3] );
-   // For going back and forth from CubitVectors
+   //@}
+
+   //! Sets the value of pnt to x,y,z (inline function).
    void set_pnt( double pnt[3], double x, double y, double z );
-   // Sets the value of pnt to x,y,z (inline function).
+
 #ifdef BOYD14
+   //! Swaps two double[3] points with each other.
    void swap_pnt(double pnt1[3],double pnt2[3]);
-   // Swaps two double[3] points with each other.
 #endif
+
+   //! Compares two points to determine if they are equivalent.  The
+   //! equivalence is based on epsilon (get_epsilon, set_epsilon).
+   //! If the distance between them is less than epsilon, the points
+   //! are considered equal.
    CubitBoolean pnt_eq( double pnt1[3],double pnt2[3] );
-   // Compares two points to determine if they are equivalent.  The
-   // equivalence is based on epsilon (get_epsilon, set_epsilon).
-   // If the distance between them is less than epsilon, the points
-   // are considered equal.
+
 #ifdef BOYD14
+   //! Compares two point arrays or portions of two point arrays to 
+   //! determine if they are equivalent within epsilon (get_epsilon,
+   //! set_epsilon).  Checking will stop when either of the array ends
+   //! is encountered or num_to_check is exceeded.  Note that he function
+   //! can return CUBIT_TRUE even if the arrays are of a different length.
    CubitBoolean pnt_arr_eq( double **pnt_arr1, long num1, double **pnt_arr2,
                            long num2, long start_pos1 = 0, long start_pos2 = 0,
                            long num_to_check = -1 );
-   // Compares two point arrays or portions of two point arrays to 
-   // determine if they are equivalent within epsilon (get_epsilon,
-   // set_epsilon).  Checking will stop when either of the array ends
-   // is encountered or num_to_check is exceeded.  Note that he function
-   // can return CUBIT_TRUE even if the arrays are of a different length.
 #endif
+
+   //! Function to mirror a point about a plane.  The mirror point
+   //! is the same distance from the plane as the original, but on 
+   //! the opposite side of the plane.  Function returns CUBIT_FAILURE
+   //! if the point is on the plane - in which case the point is
+   //! just copied.
    CubitStatus mirror_pnt( double pnt[3], double pln_orig[3], 
                            double pln_norm[3], double m_pnt[3]);
-   // Function to mirror a point about a plane.  The mirror point
-   // is the same distance from the plane as the original, but on 
-   // the opposite side of the plane.  Function returns CUBIT_FAILURE
-   // if the point is on the plane - in which case the point is
-   // just copied.
 #ifdef BOYD14
+   //! Mirrors an array of points about a plane.  If mirror_arr is
+   //! non-NULL, function assumes it was allocated to correct lenght.
+   //! If NULL, function allocates the array.
    double ** mirror_pnt_arr( double **pnt_arr, long num_pnts, 
                              double pln_orig[3], double pln_norm[3],
                              double **mirror_arr );
-   // Mirrors an array of points about a plane.  If mirror_arr is
-   // non-NULL, function assumes it was allocated to correct lenght.
-   // If NULL, function allocates the array.
 #endif
+
+   //! Given start pnt, vec dir and length find next point in space.  The
+   //! vector direction is first unitized then the following formula is used:
+   //!  new_point[] = start_point[] + (length * unit_vector[])
+   //! new_pnt can be the same as input point (overwrites old location).
    CubitStatus next_pnt( double str_pnt[3], double vec_dir[3], double len,
                          double new_pnt[3]);
-   // Given start pnt, vec dir and length find next point in space.  The
-   // vector direction is first unitized then the following formula is used:
-   //  new_point[] = start_point[] + (length * unit_vector[])
-   // new_pnt can be the same as input point (overwrites old location).
+
 #ifdef BOYD14
+
+   //! This routine creates a point between two other points, at a specified
+   //! distance between the two given points.  The distance can be either
+   //! absolute (meaning an actual distance, ie. in mm), or a normalized distance
+   //! (ie., 50% or 0.5 between the other two points).  The reference point for
+   //! the distance is always the first point. 
+   //! - The normalized distance does not need to be between 0.0 & 1.0.  For example,
+   //! a 1.25 normalized distance would result in a point 25% beyond the second 
+   //! point (not actually "between" the two points).   
+   //! - The distances can also be negative.  For example, a -1.25 normalized
+   //! distance would result in a point 25% before the first point.  A -50.0
+   //! absolute distance would extend 50.0 from the first point in the opposite
+   //! direction of the second point.
    CubitStatus pnt_between2pnts( double pnt1[3], double pnt2[3], 
                                  AgtDistanceMethod dist_meth, double dist,
                                  double out_pnt[3] );
-   // This routine creates a point between two other points, at a specified
-   // distance between the two given points.  The distance can be either
-   // absolute (meaning an actual distance, ie. in mm), or a normalized distance
-   // (ie., 50% or 0.5 between the other two points).  The reference point for
-   // the distance is always the first point. 
-   // - The normalized distance does not need to be between 0.0 & 1.0.  For example,
-   // a 1.25 normalized distance would result in a point 25% beyond the second 
-   // point (not actually "between" the two points).   
-   // - The distances can also be negative.  For example, a -1.25 normalized
-   // distance would result in a point 25% before the first point.  A -50.0
-   // absolute distance would extend 50.0 from the first point in the opposite
-   // direction of the second point.
 #endif
 
    //***************************************************************************
    // 3D Vectors
    //***************************************************************************
+   //! Finds unit vector of input vector (vout can equal vin - converts in place).
    CubitStatus unit_vec( double vin[3], double vout[3] );
-   // Finds unit vector of input vector (vout can equal vin - converts in place).
+
+   //! Dots two vectors.  Property of dot product is:
+   //!   angle between vectors acute if dot product > 0
+   //!   angle between vectors obtuse if dot product < 0
+   //!   angle between vectors 90 deg if dot product = 0
    double dot_vec( double uval[3], double vval[3] );
-   // Dots two vectors.  Property of dot product is:
-   //   angle between vectors acute if dot product > 0
-   //   angle between vectors obtuse if dot product < 0
-   //   angle between vectors 90 deg if dot product = 0
+
+   //! Finds cross product of two vectors:
+   //!    cross[0] = u[1] * v[2] - u[2] * v[1];
+   //!    cross[1] = u[2] * v[0] - u[0] * v[2];
+   //!    cross[2] = u[0] * v[1] - u[1] * v[0];
    void cross_vec( double uval[3], double vval[3], double cross[3] );
-   // Finds cross product of two vectors:
-   //    cross[0] = u[1] * v[2] - u[2] * v[1];
-   //    cross[1] = u[2] * v[0] - u[0] * v[2];
-   //    cross[2] = u[0] * v[1] - u[1] * v[0];
+
+   //! Finds unit vector that is cross product of two vectors.
    void cross_vec_unit( double uval[3], double vval[3], double cross[3] );
-   // Finds unit vector that is cross product of two vectors.
+
+   //! Finds 2 arbitrary orthoganal vectors to the first.
    void orth_vecs( double uvect[3], double vvect[3], double wvect[3] );
-   // Finds 2 arbitrary orthoganal vectors to the first.
+
+   //! Finds the magnitude of a vector:
+   //!    magnitude = sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
    double mag_vec( double vec[3] );
-   // Finds the magnitude of a vector:
-   //    magnitude = sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
+
+   //! Finds a vector from str_pnt to stp_pnt.
+   //! Returns CUBIT_FAILURE if points are coincident.
    CubitStatus get_vec ( double str_pnt[3], double stp_pnt[3],
                          double vector_out[3] );
-   // Finds a vector from str_pnt to stp_pnt.
-   // Returns CUBIT_FAILURE if points are coincident.
+
+   //! Finds a unit vector from str_pnt to stp_pnt.
+   //! Returns CUBIT_FAILURE if points are coincident.
    CubitStatus get_vec_unit( double str_pnt[3], double stp_pnt[3],
                              double uv_out[3] );
-   // Finds a unit vector from str_pnt to stp_pnt.
-   // Returns CUBIT_FAILURE if points are coincident.
+
+   //! Multiples a vector by a constant (vec_out can equal vec).
    void mult_vecxconst( double constant, double vec[3], double vec_out[3] );
-   // Multiples a vector by a constant (vec_out can equal vec).
+
 #ifdef BOYD14
+   //! Adds two vectors (vec_out can equal vec_1 or vec_2)
    void add_vec_vec( double vec_1[3], double vec_2[3], double vec_out[3]);
-   // Adds two vectors (vec_out can equal vec_1 or vec_2)
+
+   //! Subtracts two vectors (vec_out can equal vec_1 or vec_2).
    void sub_vec_vec( double vec_1[3], double vec_2[3], double vec_out[3] );
-   // Subtracts two vectors (vec_out can equal vec_1 or vec_2).
 #endif
+
 #ifdef BOYD14
+   //! Rotate a vector about another vector a given angle.  v_out can equal
+   //! v1 (v_out replaces v1) or be a new vector.
    void rotate_vec( double v1[3], double v2[3], double angle, double v_out[3] );
-   // Rotate a vector about another vector a given angle.  v_out can equal
-   // v1 (v_out replaces v1) or be a new vector.
 #endif
+
+   //! Multiples -1.0 by a vector (vout can equal vin).
    void reverse_vec( double vin[3],double vout[3] );
-   // Multiples -1.0 by a vector (vout can equal vin).
+
+   //! Finds angle in radians between two vectors.  Angle will always be
+   //! between 0.0 and PI.  For accuracy, the routine uses the cosine for large
+   //! angles and the sine for small angles.
    double angle_vec_vec( double v1[3],double v2[3] );
-   // Finds angle in radians between two vectors.  Angle will always be
-   // between 0.0 and PI.  For accuracy, the routine uses the cosine for large
-   // angles and the sine for small angles.
    
    //***************************************************************************
    // Distances
    //***************************************************************************
+   //! Determines distance between two points in space.
    double dist_pnt_pnt( double pnt1[3], double pnt2[3] );
-   // Determines distance between two points in space.
+
 #ifdef BOYD14
+   //! Determines shortest distance between two infinite lines.  Optional
+   //! output also includes intersection points.  The num_ints will be zero
+   //! if the lines are parallel, one if they physically cross and two if
+   //! they are non-parallel and non-crossing.
    double dist_ln_ln( double ln_1_orig[3], double ln_1_vec[3],
                       double ln_2_orig[3], double ln_2_vec[3],
                       unsigned short *num_ints = NULL, double int_pnt1[3] = NULL,
                       double int_pnt2[3] = NULL );
-   // Determines shortest distance between two infinite lines.  Optional
-   // output also includes intersection points.  The num_ints will be zero
-   // if the lines are parallel, one if they physically cross and two if
-   // they are non-parallel and non-crossing.
+   //! This routine determines the shortest distance between a point and a
+   //! plane.  This is the perpendicular distance from the point to the plane.
+   //! Optionally you can find which side of the plane the point is on and 
+   //! the plane intersection with the point.
    double dist_pnt_pln( double pnt[3], double pln_orig[3], double pln_norm[3], 
                         AgtSide *side = NULL, double pln_int[3] = NULL );
-   // This routine determines the shortest distance between a point and a
-   // plane.  This is the perpendicular distance from the point to the plane.
-   // Optionally you can find which side of the plane the point is on and 
-   // the plane intersection with the point.
 #endif
+   //! This routine determines the shortest distance between two planes.  This 
+   //! is the perpendicular distance between the two planes.  Note that if the
+   //! two planes are not parallel, the returned distance is zero.  The routine
+   //! can also be used to determine which side of the first plane the second
+   //! plane is on, and the orientation of the two planes to each other.
    double dist_pln_pln( double pln_1_orig[3], double pln_1_norm[3], 
                         double pln_2_orig[3], double pln_2_norm[3],
                         AgtSide *side = NULL, AgtOrientation *orien = NULL,
                         unsigned short *status = NULL );
-   // This routine determines the shortest distance between two planes.  This 
-   // is the perpendicular distance between the two planes.  Note that if the
-   // two planes are not parallel, the returned distance is zero.  The routine
-   // can also be used to determine which side of the first plane the second
-   // plane is on, and the orientation of the two planes to each other.
 #ifdef BOYD14
+   //! This routine determines the shortest distance between a line and a plane.  
+   //! This is the perpendicular distance between the line and the plane.  Note 
+   //! that if the line is not parallel to the plane, the returned distance is 
+   //! zero.  You can also find which side of the plane the line is on and
+   //! the status (= 0 if line & plane not parallel).
    double dist_ln_pln( double ln_orig[3], double ln_vec[3], double pln_orig[3],
                        double pln_norm[3], AgtSide *side = NULL, 
                        unsigned short *status = NULL );
-   // This routine determines the shortest distance between a line and a plane.  
-   // This is the perpendicular distance between the line and the plane.  Note 
-   // that if the line is not parallel to the plane, the returned distance is 
-   // zero.  You can also find which side of the plane the line is on and
-   // the status (= 0 if line & plane not parallel).
+
+   //! This routine determines the shortest distance between a point and a line.  
+   //! This is the perpendicular distance between the point and the line.  You
+   //! can optionally get the intersection point of the point and line.
    double dist_pnt_ln( double pnt[3], double ln_orig[3], double ln_vec[3],
                        double int_pnt[3] = NULL );
-   // This routine determines the shortest distance between a point and a line.  
-   // This is the perpendicular distance between the point and the line.  You
-   // can optionally get the intersection point of the point and line.
 #endif
    
    //***************************************************************************
    // Intersections
    //***************************************************************************
+   //! This routine calculates the intersection point of a line and a plane.
+   //! Returns CUBIT_FAILURE if no intersection exists (line is parallel to the
+   //! plane).
    CubitStatus int_ln_pln( double ln_orig[3], double ln_vec[3], double pln_orig[3],
                            double pln_norm[3], double int_pnt[3] );
-   // This routine calculates the intersection point of a line and a plane.
-   // Returns CUBIT_FAILURE if no intersection exists (line is parallel to the
-   // plane).
+   //! This function finds the intersection of two lines.  If the lines cross,
+   //! it finds the one unique point.  If the lines do not cross (but are non-
+   //! parallel), it finds the nearest intersection points (a line drawn from 
+   //! each of these intersections would be perpendicular to both lines).
+   //! Returns number of intersections found:
+   //!   0 intersections found, lines are parallel
+   //!   1 intersection found, lines physically intersect
+   //!   2 intersections found, lines do not intersect but nearest 
+   //!     intersections found
    int int_ln_ln( double p1[3], double v1[3], double p2[3], double v2[3], 
                   double int_pnt1[3], double int_pnt2[3] );
-   // This function finds the intersection of two lines.  If the lines cross,
-   // it finds the one unique point.  If the lines do not cross (but are non-
-   // parallel), it finds the nearest intersection points (a line drawn from 
-   // each of these intersections would be perpendicular to both lines).
-   // Returns number of intersections found:
-   //   0 intersections found, lines are parallel
-   //   1 intersection found, lines physically intersect
-	//   2 intersections found, lines do not intersect but nearest 
-	//     intersections found
+
+   //! This routine finds the perpendicular intersection of a point & line.  This
+   //! point will lie on the line.
+   //! Returns 0 if point is not on the line, otherwise 1.
    int int_pnt_ln( double pnt[3], double ln_orig[3],  double ln_vec[3],
                             double int_pnt[3] );
-   // This routine finds the perpendicular intersection of a point & line.  This
-   // point will lie on the line.
-   // Returns 0 if point is not on the line, otherwise 1.
+
+   //! This routine determines the perpendicular intersection of a point and a 
+   //! plane.  This is the perpendicular intersection point on the plane.
+   //! Returns 0 if point is not on the plane, otherwise 1.  
    int int_pnt_pln( double pnt[3], double pln_orig[3], double pln_norm[3], 
                              double pln_int[3] );
-   // This routine determines the perpendicular intersection of a point and a 
-   // plane.  This is the perpendicular intersection point on the plane.
-   // Returns 0 if point is not on the plane, otherwise 1.  
+
+   //! This routine finds intersection of two planes.  This intersection results
+   //! in a line.  Returns CUBIT_FAILURE if planes are parallel.
    CubitStatus int_pln_pln( double pln_1_orig[3], double pln_1_norm[3],
                             double pln_2_orig[3], double pln_2_norm[3],
                             double ln_orig[3], double ln_vec[3] );
-   // This routine finds intersection of two planes.  This intersection results
-   // in a line.  Returns CUBIT_FAILURE if planes are parallel.
 #ifdef BOYD14
+   //! This routine finds the intersection of three orthoganal planes.  This 
+   //! intersection is a point.  Returns CUBIT_FAILURE if no point intersection
+   //! exists.
    CubitStatus int_pln_pln_pln( double pln_1_orig[3], double pln_1_norm[3],
                                 double pln_2_orig[3], double pln_2_norm[3],
                                 double pln_3_orig[3], double pln_3_norm[3],
                                 double int_pnt[3] );
-   // This routine finds the intersection of three orthoganal planes.  This 
-   // intersection is a point.  Returns CUBIT_FAILURE if no point intersection
-   // exists.
 #endif
    
    //**************************************************************************
    // Comparison/Containment Tests
    //**************************************************************************
+   //! This routine checks to see if two vectors are parallel.  Two vectors
+   //! are considered parallel if they are pointing in the same direction or
+   //! opposite directions.
    CubitBoolean is_vec_par( double vec_1[3], double vec_2[3] );
-   // This routine checks to see if two vectors are parallel.  Two vectors
-   // are considered parallel if they are pointing in the same direction or
-   // opposite directions.
+
+   //! This routine checks to see if two vectors are perpendicular.  Two vectors
+   //! are considered perpendicular if they are PI/2 radians to each other.
    CubitBoolean is_vec_perp( double vec_1[3],double vec_2[3]);
-   // This routine checks to see if two vectors are perpendicular.  Two vectors
-   // are considered perpendicular if they are PI/2 radians to each other.
+
+   //! This routine checks to see if two vectors point in the same direction.
+   //! The vector magnitudes do not have to be equal for a successful return.
    CubitBoolean is_vecs_same_dir( double vec_1[3], double vec_2[3] );
-   // This routine checks to see if two vectors point in the same direction.
-   // The vector magnitudes do not have to be equal for a successful return.
+
+   //! This routined determines if a specified point is on a given infinite line
+   //! defined by a point and a vector.
    CubitBoolean is_pnt_on_ln( double pnt[3], double ln_orig[3], double ln_vec[3] );
-   // This routined determines if a specified point is on a given infinite line
-   // defined by a point and a vector.
+
+   //! This routine determines if a specified point is on a given line segment
+   //! defined by two endpoints.  The point is on the line only if it lies on
+   //! the line between or on the two endpoints.
    CubitBoolean is_pnt_on_ln_seg( double pnt1[3], double end1[3], double end2[3] );
-   // This routine determines if a specified point is on a given line segment
-   // defined by two endpoints.  The point is on the line only if it lies on
-   // the line between or on the two endpoints.
+
+   //! This routined determines if a specified point is on a given plane
+   //! which is defined by an origin and three vectors.
    CubitBoolean is_pnt_on_pln( double pnt[3], double pln_orig[3], double pln_norm[3] );
-   // This routined determines if a specified point is on a given plane
-   // which is defined by an origin and three vectors.
+
+   //! This routine determines if a specified line (defined by a point and
+   //! a vector) is in a given plane (defined by the two vectors in the plane 
+   //! and the normal to that plane).
    CubitBoolean is_ln_on_pln( double ln_orig[3], double ln_vec[3],
                               double pln_orig[3], double pln_norm[3] );
-   // This routine determines if a specified line (defined by a point and
-   // a vector) is in a given plane (defined by the two vectors in the plane 
-   // and the normal to that plane).
+
+
 #ifdef BOYD14
+   //! This routine checks to see if two rays converge or diverge towards each
+   //! other.  A ray is a line that is not infinite (consists of an origin and
+   //! a vector direction).  Rays are defined to converge if they intersect
+   //! within a common plane to each ray (ie., if the rays do not lie in a 
+   //! common plane, one of the rays is temporarily translated into the common
+   //! plane for checking).  If the rays are parallel, no one common plane exists,
+   //! so they are checked as-is.  See the following examples for a clearer 
+   //! picture of how this routine works.  Assume that the rays in the first row
+   //! are in planes that are parallel to this document but not in planes that are
+   //! necessarily coincident.  Assume that the rays in the second row are in the
+   //! same plane.  Note that rays may converge even if they are not in the same 
+   //! plane.
+   //!    
+   //!    Examples:
+   //!    
+   //!      *---->          <----*           <----*                      
+   //!              ^               ^             ^            ^
+   //!              |               |             |            |      
+   //!              |               |             |            |
+   //!              *               *             *            *---->
+   //!	    
+   //!      converge        diverge           converge        converge   
+   //!      
+   //!      
+   //!      *--->  *--->    *--->  <---*    *--->            *--->    
+   //!                                            <---*         *--->
+   //!        converge        converge        diverge         diverge 
    CubitBoolean do_rays_converge( double ray_1_orig[3], double ray_1_vec[3],
                                   double ray_2_orig[3], double ray_2_vec[3] );
-   // This routine checks to see if two rays converge or diverge towards each
-   // other.  A ray is a line that is not infinite (consists of an origin and
-   // a vector direction).  Rays are defined to converge if they intersect
-   // within a common plane to each ray (ie., if the rays do not lie in a 
-   // common plane, one of the rays is temporarily translated into the common
-   // plane for checking).  If the rays are parallel, no one common plane exists,
-   // so they are checked as-is.  See the following examples for a clearer 
-   // picture of how this routine works.  Assume that the rays in the first row
-   // are in planes that are parallel to this document but not in planes that are
-   // necessarily coincident.  Assume that the rays in the second row are in the
-   // same plane.  Note that rays may converge even if they are not in the same 
-   // plane.
-   //    
-   //    Examples:
-   //    
-   //      *---->          <----*           <----*                      
-   //              ^               ^             ^            ^
-   //              |               |             |            |      
-   //              |               |             |            |
-   //              *               *             *            *---->
-   //	    
-   //      converge        diverge           converge        converge   
-   //      
-   //      
-   //      *--->  *--->    *--->  <---*    *--->            *--->    
-   //                                            <---*         *--->
-   //        converge        converge        diverge         diverge 
+
+   //! This routine checks to see if two lines are colinear.  Two lines are 
+   //! considered colinear if they are parallel and the origin of one line is on 
+   //! the other line.
    CubitBoolean is_ln_on_ln( double ln_orig1[3], double ln_vec1[3],
                              double ln_orig2[3], double ln_vec2[3] );
-   // This routine checks to see if two lines are colinear.  Two lines are 
-   // considered colinear if they are parallel and the origin of one line is on 
-   // the other line.
 #endif
+
+   //! This routine checks to see if two infinite planes are coincident.
    CubitBoolean is_pln_on_pln( double pln_orig1[3], double pln_norm1[3],
                                double pln_orig2[3], double pln_norm2[3] );
-   // This routine checks to see if two infinite planes are coincident.
 
    //**************************************************************************
    // Arcs/Circles
    //**************************************************************************
+
+   //@{
+   //! Functions to populate an arc structure.  The arc is defined with two
+   //! orthogonal vectors in a plane, the arc origin, the beginning angle
+   //! in radians to rotate from the start vector (towards second vector), the 
+   //! ending angle in radians to rotate from the start vector, and the radius 
+   //! of the arc.  The arc is parameterized from 0 to 1.
    void setup_arc( double vec_1[3], double vec_2[3], double origin[3],
                   double start_angle, double end_angle, // Angles in radians
                   double radius, AGT_3D_Arc &arc );
@@ -712,35 +813,47 @@
                    CubitVector origin, double start_angle, // Angles in radians
                    double end_angle, double radius,
                    AGT_3D_Arc &arc );
-   // Functions to populate an arc structure.  The arc is defined with two
-   // orthogonal vectors in a plane, the arc origin, the beginning angle
-   // in radians to rotate from the start vector (towards second vector), the 
-   // ending angle in radians to rotate from the start vector, and the radius 
-   // of the arc.  The arc is parameterized from 0 to 1.
+   //@}
+  
+   //@{
+   //! Given a parameter value from 0 to 1 on the arc, return the xyz location.
+   //! Arc is assumed to be parameterized from 0 to 1.
    void get_arc_xyz( AGT_3D_Arc &arc, double param, double pnt[3] );
    void get_arc_xyz( AGT_3D_Arc &arc, double param, CubitVector& pnt );
-   // Given a parameter value from 0 to 1 on the arc, return the xyz location.
-   // Arc is assumed to be parameterized from 0 to 1.
+   //@}
 
+   //! Get number of tessellation points on the circle required to 
+   //! approximate the length of the circle within len_tolerance.  Can
+   //! be used to find the number of tessellations points to display a 
+   //! circle - smaller circles will have fewer tessellation points, larger 
+   //! circles will have more tessellation points with the same tolerance.
+   //! Minimum number of tessellations points returned is 8.
    int get_num_circle_tess_pnts( double radius, double len_tolerance = 1e-4 );
-   // Get number of tessellation points on the circle required to 
-   // approximate the length of the circle within len_tolerance.  Can
-   // be used to find the number of tessellations points to display a 
-   // circle - smaller circles will have fewer tessellation points, larger 
-   // circles will have more tessellation points with the same tolerance.
-   // Minimum number of tessellations points returned is 8.
 
    //**************************************************************************
    // Miscellaneous
    //**************************************************************************
+
+   //! Finds an origin-normal format plane from reduced form
+   //! A*x + B*y + C*z + D = 0
    void get_pln_orig_norm( double A, double B, double C, double D, 
                            double pln_orig[3], double pln_norm[3] = NULL );
-   // Finds an origin-normal format plane from reduced form
-   //   A*x + B*y + C*z + D = 0
+   //! Find 8 corners of a box given minimum and maximum points.  Box is
+   //! defined starting from left-bottom-front clockwise (at front of box), 
+   //! then to the rear in same order.
    void get_box_corners( double box_min[3],double box_max[3],double c[8][3] );
-   // Find 8 corners of a box given minimum and maximum points.  Box is
-   // defined starting from left-bottom-front clockwise (at front of box), 
-   // then to the rear in same order.
+
+   //@{
+   //! Finds the 4 corner points of the input infinite plane that just 
+   //! intersects the input box (defined by bottom-left and top-right corners, 
+   //! axis aligned with the cubit coordinate system) - plane should have
+   //! minimal area.  The resultant plane's corner points can be extended out 
+   //! by a percentage of diagonal or absolute (making it bigger than the minimal
+   //! area plane).  extension_type - 0=none, 1=percentage, 2=absolute
+   //! If silent is CUBIT_TRUE, no error messages are given.  Note this returns
+   //! points even if the plane doesn't physically intersect the given box... it
+   //! does this by moving  the plane to the center of the box, doing the
+   //! intersection, then projecting the points back to the original plane. 
    CubitStatus min_pln_box_int_corners( const CubitPlane& plane, 
                                         const CubitBox& box,
                                         int extension_type, double extension,
@@ -761,26 +874,34 @@
                                        double p1[3], double p2[3],   // OUT
                                        double p3[3], double p4[3],   // OUT
                                        CubitBoolean silent = CUBIT_FALSE); 
-   // Finds the 4 corner points of the input infinite plane that just 
-   // intersects the input box (defined by bottom-left and top-right corners, 
-   // axis aligned with the cubit coordinate system) - plane should have
-   // minimal area.  The resultant plane's corner points can be extended out 
-   // by a percentage of diagonal or absolute (making it bigger than the minimal
-   // area plane).  extension_type - 0=none, 1=percentage, 2=absolute
-   // If silent is CUBIT_TRUE, no error messages are given.
+   //@}
 
+   //@{
+   //! Finds the minimum size bounding box that fits around the points.  Box
+   //! will not necessarily be oriented in xyz directions.
    CubitStatus get_tight_bounding_box( DLIList<CubitVector*> &point_list,                                       
                                        CubitVector& p1, CubitVector& p2,
                                        CubitVector& p3, CubitVector& p4,
                                        CubitVector& p5, CubitVector& p6,
                                        CubitVector& p7, CubitVector& p8);
-   CubitStatus get_tight_bounding_box( DLIList<CubitVector*> &point_list,                                              
+   CubitStatus get_tight_bounding_box( DLIList<CubitVector*> &point_list,                              
                                        CubitVector &center,
                                        CubitVector axes[3],
                                        CubitVector &extension );
-   // Finds the minimum size bounding box that fits around the points.  Box
-   // will not necessarily be oriented in xyz directions.
+   //@}
 
+  
+   //@{
+   //! Finds the start and end of a cylinder that just intersects the input
+   //! box (defined by bottom-left and top-right corners, axis aligned with 
+   //! the cubit coordinate system).  The resultant cylinder's start and end
+   //! points can be extended out by a percentage of cylinder's length or
+   //! absolute (making it longer in both directions).
+   //!   extension_type - 0=none, 1=percentage, 2=absolute
+   //! The num_tess_pnts is the number of line points along the circle the 
+   //! function projects to the box to calculate the minimum intersection
+   //! (more points could give a more accurate result for non-axis aligned
+   //! cylinders).
    CubitStatus min_cyl_box_int( double radius, CubitVector& axis, CubitVector& center,
                                 CubitBox& box,
                                 int extension_type, double extension,
@@ -791,39 +912,32 @@
                                 int extension_type, double extension, 
                                 double start[3], double end[3],
                                 int num_tess_pnts = 2048 );
-   // Finds the start and end of a cylinder that just intersects the input
-   // box (defined by bottom-left and top-right corners, axis aligned with 
-   // the cubit coordinate system).  The resultant cylinder's start and end
-   // points can be extended out by a percentage of cylinder's length or
-   // absolute (making it longer in both directions).
-   //   extension_type - 0=none, 1=percentage, 2=absolute
-   // The num_tess_pnts is the number of line points along the circle the 
-   // function projects to the box to calculate the minimum intersection
-   // (more points could give a more accurate result for non-axis aligned
-   // cylinders).
+   //@}
 
-   double MinTriangleTriangle (Triangle3& tri0, Triangle3& tri1, double& s, double& t, double& u, double& v);
-   // Finds minimum distance between two triangles in 3D (MAGIC)
+   //! Finds minimum distance between two triangles in 3D (MAGIC)
+   double MinTriangleTriangle (Triangle3& tri0, 
+                               Triangle3& tri1, 
+                              double& s, double& t, double& u, double& v);
    
+   //! Finds area of intersection between two triangles (MAGIC)
    double AreaIntersection (Triangle &tri1, Triangle &tri2 );
-   // Finds area of intersection between two triangles (MAGIC)
 
+   //! Finds angle between normals of the two triangles (radians)
    double Angle( Triangle3& tri1, Triangle3& tri2 );
-   // Finds angle between normals of the two triangles (radians)
 
+   //! Finds minimum distance beween a triange and point in 3D (MAGIC)
    double MinPointTriangle (const Point3& p, const Triangle3& tri, double& s, double& t);
-   // Finds minimum distance beween a triange and point in 3D (MAGIC)
 
 #ifdef BOYD14
    void Center( Triangle3& tri, double center[3] );
    // Finds center position of given triangle
 #endif
 
+   //! Finds normal vector of given triangle
    void Normal( Triangle3& tri, double normal[3] );
-   // Finds normal vector of given triangle
 
-   double ProjectedOverlap( Triangle3& tri1, Triangle3& tri2 );
-   // Projects tri2 to the plane of tri1 and finds the overlap area
+   //! Projects tri2 to the plane of tri1 and finds the overlap area
+   double ProjectedOverlap( Triangle3& tri1, Triangle3& tri2, bool draw_overlap = false );
 
 protected:
    AnalyticGeometryTool();

Added: cgm/branches/cubit/geom/AutoMidsurfaceTool.cpp
===================================================================
--- cgm/branches/cubit/geom/AutoMidsurfaceTool.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/AutoMidsurfaceTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,908 @@
+//-------------------------------------------------------------------------
+// Filename      : AutoMidsurfaceTool.cpp
+//
+// Purpose       : 
+//   Create a midsurface of a body/volume given a thickness range. If no thickness range is given
+//   then make a educated guess at the thickness (using something like Volume/Surface Area).
+//   
+//   Create Midsurface Volume <id_list> auto [<min_thickness> <max_thickness>]
+//
+// Creator       : Sam Showman
+//
+// Creation Date : 05/10/2008
+//-------------------------------------------------------------------------
+#include "AutoMidsurfaceTool.hpp"
+#include "GeometryModifyEngine.hpp"
+#include "GeometryQueryTool.hpp"
+#include "BodySM.hpp"
+#include "Body.hpp"
+#include "GeometryModifyTool.hpp"
+#include "RefFace.hpp"
+#include "Surface.hpp"
+#include "Curve.hpp"
+#include "RefEntity.hpp"
+#include "SurfaceOverlapTool.hpp"
+#include "CubitPlane.hpp"
+#include "GfxPreview.hpp"
+#include "GfxDebug.hpp"
+#include "RefVertex.hpp"
+#include "ProgressTool.hpp"
+#include "AppUtil.hpp"
+#include "BoundingBoxTool.hpp"
+#include "GeomMeasureTool.hpp"
+
+// Constructor - nothing going on here
+AutoMidsurfaceTool::AutoMidsurfaceTool()
+{
+}
+
+// The main midsurface function
+// lower_tol, upper_tol and preview are optional
+CubitStatus AutoMidsurfaceTool::midsurface(
+	DLIList<Body*> &body_list_in,
+	DLIList<BodySM*> &body_list_out,
+    DLIList<Body*> &old_bodies_midsurfaced,
+    DLIList<double> &thickness_out,
+	double lower_limit,
+	double upper_limit,
+    CubitBoolean delete_midsurfaced,
+    CubitBoolean preview)
+{
+    if(lower_limit == CUBIT_DBL_MAX)// no limit set
+        lower_limit = -CUBIT_DBL_MAX;
+    double lower_tol = CUBIT_DBL_MAX;
+    double upper_tol = CUBIT_DBL_MAX;
+    const double auto_thickness_margin = 0.05; // if the user wants to automatically find the search
+	                                          // thickness then this var give the search margin around the
+	                                          // guess
+    ProgressTool* prog_tool = 0;
+    if(body_list_in.size()>5)
+        prog_tool = AppUtil::instance()->progress_tool();
+
+	// At lease one body must be provided
+	if(body_list_in.size() < 1)
+	{
+		PRINT_ERROR( "No bodies given for midsurfacing\n" );
+		return CUBIT_FAILURE;
+	}
+
+	// The surfaceOverlapTool is persistent so we need to save the 
+	// max_gap and such to restore them at the end or if we error out
+	// save current settings
+	double max_gap_save = SurfaceOverlapTool::instance()->get_gap_max();
+	double min_gap_save = SurfaceOverlapTool::instance()->get_gap_min();
+	int normal_type = SurfaceOverlapTool::instance()->get_normal_type();
+	CubitBoolean cubit_bool_save = SurfaceOverlapTool::instance()->get_check_within_bodies();
+    CubitBoolean skip_facing_surfaces = SurfaceOverlapTool::instance()->get_skip_facing_surfaces();
+
+    // we want to only find overlap within a body
+    SurfaceOverlapTool::instance()->set_check_within_bodies(CUBIT_TRUE);
+    // 1=any, 2=opposite, 3=same  - we want to find only the overlaps that normals
+    // pointing in the opposite directions
+    SurfaceOverlapTool::instance()->set_normal_type(2);
+    // Don't pickup surfaces that face each other
+    SurfaceOverlapTool::instance()->set_skip_facing_surfaces(CUBIT_TRUE);
+
+    // list of bodies that fail to midsurface
+    DLIList<Body*> failing_bodies; 
+
+    GeometryModifyEngine* gme = 0;
+    GeometryQueryEngine* gqe = 0;
+
+	// loop over every body and try to create midsurface(s)
+	int i = 0;
+	CubitStatus return_status = CUBIT_FAILURE;
+
+    if(prog_tool)
+        prog_tool->start(0,body_list_in.size());
+
+    for(i = body_list_in.size();i--;)
+    {
+        if(prog_tool)
+            prog_tool->step();
+
+		Body* cur_body = body_list_in[i];
+		if(!cur_body)
+			continue;
+
+		BodySM* body_sm = cur_body->get_body_sm_ptr();
+		if(!body_sm)
+			continue;
+
+        if(cur_body->is_sheet_body())
+        {
+            PRINT_INFO("Body %d is a sheet body.\n",cur_body->id());
+            continue;
+        }
+
+		// Grab the geometrymodify and geometryquery engines to use later
+		gqe = cur_body->get_geometry_query_engine();
+		gme = GeometryModifyTool::instance()->get_engine(body_sm);
+
+		if(!gqe || !gme)
+			continue;
+
+		// Here are the steps to finding/creating the midsurface
+		// 1. If the user did not give a thickness range to search then
+		//    make an educated guess at the proper thickness range. The assumption
+		//    is that the midsurface is a square and the thickness is constant.
+		//    The resulting equation is a third order polynomial that is solved using
+		//    a few newton iterations. The initial thickness guess is Volume/Area
+		// 2. Using the given search distances use the SurfaceOverlapTool to find
+		//    surface pairs.
+        // 3. If there is only one surface pair then use the existing midsurface commands
+		// 4. Find if the surface pairs represent two surface patches
+		// 5. If there are only two surface patches try to offset one of the patches
+		// 6. (this step is commented out for now) - If 5 fails or there are more than
+        //           two surface patches then try the following:
+		//         - Use the manual midsurface creation function to create midsurfaces for each
+		//           pair of surfaces.
+		//         - Unite all of the created midsurfaces together
+		//         - remove any surfaces that have a curve touching a surface pair 
+		//         - Regularize the resulting body
+		// 7. Done
+
+		{
+			PRINT_DEBUG_198("AUTOMATICALLY calculating search range\n");
+			DLIList<RefVolume*> vol_list;
+			cur_body->ref_volumes(vol_list);
+			double total_vol = 0;
+            double total_vol_bb = 0;
+			for(int vol_cnt = 0; vol_cnt < vol_list.size(); vol_cnt++)
+			{
+                CubitVector cg;
+                double temp_volume;
+                vol_list[vol_cnt]->mass_properties(cg,temp_volume);
+                CubitBox vol_bb = vol_list[vol_cnt]->bounding_box();
+                total_vol += temp_volume;
+                total_vol_bb += vol_bb.x_range()*vol_bb.y_range()*vol_bb.z_range();
+            }
+
+            if(total_vol<0 || total_vol > total_vol_bb)
+            {
+                PRINT_INFO("Could not midsurface Body %d - try healing the body.\n",cur_body->id());
+                failing_bodies.append(cur_body);
+                continue;
+            }
+                
+			PRINT_DEBUG_198("Volume of %f\n",total_vol);
+
+			DLIList<RefFace*> face_list;
+			cur_body->ref_faces(face_list);
+			double total_surf = 0;
+			for(int surf_cnt = 0; surf_cnt < face_list.size(); surf_cnt++)
+				total_surf += face_list[surf_cnt]->area();
+			PRINT_DEBUG_198("Area of %f\n",total_surf);
+
+			double t_g = total_vol/(total_surf/2.0);
+            double initial_guess = t_g;
+			PRINT_DEBUG_198("Initial guess of thickness %f\n",t_g);
+			// use a newton solver to get a more accurate estimate the thickness of the volume
+			for(int n_i = 0;n_i<100;n_i++)
+			{
+				double tol_newton = GEOMETRY_RESABS;
+				double t_gn = t_g + tol_newton;
+				double f_prime = ((2.0*total_vol + sqrt(total_vol*t_g*t_g*t_g)*4.0 - total_surf*t_g)
+					-(2.0*total_vol + sqrt(total_vol*t_gn*t_gn*t_gn)*4.0 - total_surf*t_gn))/
+					(t_g-t_gn);
+
+				// avoid divide by zero
+				if(fabs(f_prime)<tol_newton)
+					break;
+
+				double t_old = t_g;
+				t_g = t_g - (2.0*total_vol + sqrt(total_vol*t_g*t_g*t_g)*4.0 - total_surf*t_g)/f_prime;
+				
+				PRINT_DEBUG_198("Guess %d Thickness %f\n",n_i,t_g);
+				if(fabs(t_g-t_old)<tol_newton)
+				{
+					PRINT_DEBUG_198("Converged with thickness of %f in %d steps\n",t_g,n_i);
+					break;
+				}
+                if(t_g<0.0)
+                {
+					PRINT_DEBUG_198("thickness less than zero setting back to initial guess\n");
+                    t_g = fabs(initial_guess);
+					break;
+                }
+			}
+			upper_tol = t_g + t_g*auto_thickness_margin;
+			lower_tol = t_g - t_g*auto_thickness_margin;
+            upper_tol = upper_tol <= upper_limit?upper_tol:upper_limit;
+            lower_tol = lower_tol >= lower_limit?lower_tol:lower_limit;
+
+			PRINT_DEBUG_198("Guessing a thickness of %f to %f\n",lower_tol,upper_tol);
+		}
+
+		// set the lower and upper search distances
+		SurfaceOverlapTool::instance()->set_gap_max(upper_tol);
+		SurfaceOverlapTool::instance()->set_gap_min(lower_tol);
+
+		DLIList<RefFace*> ref_face_list,list1,list2;
+        DLIList<RefEntity*> faces_to_draw; 
+        cur_body->ref_faces(ref_face_list);
+        // find the surface pairs
+        SurfaceOverlapTool::instance()->find_overlapping_surfaces(ref_face_list,list1,list2,faces_to_draw);
+
+        int tweak_iters = 4;
+        for(int tweak = 0;tweak<tweak_iters;tweak++)
+        {
+            // if we didn't find anything then the part may be long and selender so grow the search thickness
+            if(list1.size()==0 && list2.size() == 0)
+            {
+                if(tweak == tweak_iters-1 && lower_limit != -CUBIT_DBL_MAX && upper_limit != CUBIT_DBL_MAX)
+                {
+                    // on the last try use the user defined limits
+                    lower_tol = lower_limit;
+                    upper_tol = upper_limit;
+                }
+                else
+                {
+                    lower_tol = (upper_tol + lower_tol)/2.0;
+                    upper_tol += lower_tol*auto_thickness_margin*2;
+                    upper_tol = upper_tol <= upper_limit?upper_tol:upper_limit;
+                    lower_tol = lower_tol >= lower_limit?lower_tol:lower_limit;
+                }
+
+                PRINT_DEBUG_198("Guessing again with thickness of %f to %f\n",lower_tol,upper_tol);
+                SurfaceOverlapTool::instance()->set_gap_max(upper_tol);
+                SurfaceOverlapTool::instance()->set_gap_min(lower_tol);
+                SurfaceOverlapTool::instance()->find_overlapping_surfaces(ref_face_list,list1,list2,faces_to_draw);
+            }
+
+            DLIList<RefFace*> check_list;
+            check_list += list1;
+            check_list += list2;
+
+            if(check_list.size() == 0 )
+                continue;
+
+            // make sure the pairs will match the solid within 10% or so
+            if(!check_surf_pairs(lower_tol,upper_tol,check_list,cur_body))
+            {
+                list1.clean_out();
+                list2.clean_out();
+                continue;
+            }
+            break;
+        }
+
+        if(list1.size() != list2.size())
+        {
+            PRINT_INFO("Could not find workable surface pairs for Body %d - try using the Sheet Offset command. \n",cur_body->id());
+            failing_bodies.append(cur_body);
+            continue;
+        }
+		else if(list1.size() == 0 || list2.size() == 0)
+		{
+				PRINT_INFO("No surface pairs found for Body %d - try changing the search range\n",cur_body->id());
+			failing_bodies.append(cur_body);
+			continue;
+		}
+
+		// get the first pair and see if there are only two patches
+		DLIList<RefFace*> red_faces;
+		red_faces.append(list1[0]);
+		DLIList<RefFace*> yellow_faces;
+		yellow_faces.append(list2[0]);
+		DLIList<RefFace*> paired_faces;
+		paired_faces += list1;
+		paired_faces += list2;
+		paired_faces.uniquify_unordered();
+
+		// red surfaces
+		while(1)
+		{
+			int start_cnt = red_faces.size();
+			DLIList<RefEdge*> red_edges;
+			int j = 0;
+			for(j =0;j<red_faces.size();j++)
+				red_faces[j]->ref_edges(red_edges);
+			red_edges.uniquify_unordered();
+			for(j =0;j<red_edges.size();j++)
+				red_edges[j]->ref_faces(red_faces);
+			red_faces.uniquify_unordered();
+			red_faces.intersect_unordered(paired_faces);
+			if(start_cnt == red_faces.size())
+				break;
+		}
+
+		// yellow surfaces
+		while(1)
+		{
+			int start_cnt = yellow_faces.size();
+			DLIList<RefEdge*> yellow_edges;
+			int j = 0;
+			for(j =0;j<yellow_faces.size();j++)
+				yellow_faces[j]->ref_edges(yellow_edges);
+			yellow_edges.uniquify_unordered();
+			for(j =0;j<yellow_edges.size();j++)
+				yellow_edges[j]->ref_faces(yellow_faces);
+			yellow_faces.uniquify_unordered();
+			yellow_faces.intersect_unordered(paired_faces);
+			if(start_cnt == yellow_faces.size())
+				break;
+		}
+
+        DLIList<BodySM*> results;
+        bool midsurface_done = false;
+
+        if(DEBUG_FLAG(198))
+        {
+            int j = 0;
+            PRINT_INFO("Trying surface offset to create the mid_surface\n");
+            PRINT_INFO("Red surface ");
+            for(j = 0;j < red_faces.size();j++)
+            {
+                GfxDebug::draw_ref_face(red_faces[j],CUBIT_RED);
+                PRINT_INFO("%d ",red_faces[j]->id());
+            }
+
+            PRINT_INFO("\nYellow surface ");
+            for(j = 0;j < yellow_faces.size();j++)
+            {
+                GfxDebug::draw_ref_face(yellow_faces[j],CUBIT_YELLOW);
+                PRINT_INFO("%d ",yellow_faces[j]->id());
+            }
+
+            PRINT_INFO("\n");
+        }
+
+        // first check to see if we can use the simple midsurface functions
+        if(red_faces.size() == 1 && yellow_faces.size() == 1 &&
+            paired_faces.size() == red_faces.size() + yellow_faces.size()) 
+        {
+            RefFace* face_1 = red_faces[0];
+            RefFace* face_2 = yellow_faces[0];
+            midsurface_done = false;
+
+            if(face_1->geometry_type() == face_2->geometry_type())
+            {
+                Surface* surf_1 = face_1->get_surface_ptr();
+                Surface* surf_2 = face_2->get_surface_ptr();
+                BodySM* result_body;
+                // grab the distance between surfaces
+                CubitVector temp_vec0;
+                CubitVector temp_vec1;
+                double temp_dist = 0;
+                gqe->entity_entity_distance(
+                    face_1->get_surface_ptr(),
+                    face_2->get_surface_ptr(),
+                    temp_vec0,temp_vec1,temp_dist);
+
+                switch(face_1->geometry_type())
+                {
+                case CONE_SURFACE_TYPE:
+                    if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+                    {
+                        midsurface_done = true;
+                        results.append(result_body);
+                        thickness_out.append(fabs(temp_dist));
+                    }
+                    break;
+                case PLANE_SURFACE_TYPE:
+                    if(get_planar_mid_surface(face_1,face_2,body_sm,result_body,gme) == CUBIT_SUCCESS)
+                    {
+                        midsurface_done = true;
+                        results.append(result_body);
+                        thickness_out.append(fabs(temp_dist));
+                    }
+                    break;
+                case SPHERE_SURFACE_TYPE:
+                    if(gme->get_spheric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+                    {
+                        midsurface_done = true;
+                        results.append(result_body);
+                        thickness_out.append(fabs(temp_dist));
+                    }
+                    break;
+                case TORUS_SURFACE_TYPE:
+                    if(gme->get_toric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+                    {
+                        midsurface_done = true;
+                        results.append(result_body);
+                        thickness_out.append(fabs(temp_dist));
+                    }
+                    break;
+                case CYLINDER_SURFACE_TYPE:
+                    if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+                    {
+                        midsurface_done = true;
+                        results.append(result_body);
+                        thickness_out.append(fabs(temp_dist));
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+
+		if(!midsurface_done &&
+            paired_faces.size() == red_faces.size() + yellow_faces.size()) // just do the offset
+		{
+			int j = 0;
+            DLIList<double> offset_distances;
+            for(j = 0;j<list1.size();j++)
+            {
+                CubitVector temp_vec0;
+                CubitVector temp_vec1;
+				double temp_dist = 0;
+				if(!gqe->entity_entity_distance(
+					list1[j]->get_surface_ptr(),
+					list2[j]->get_surface_ptr(),
+					temp_vec0,temp_vec1,temp_dist))
+				{
+					break;
+				}
+				offset_distances.append(-temp_dist*.5);
+			}
+
+			DLIList<Surface*> red_surfs;
+			for(j = 0;j<red_faces.size();j++)
+				red_surfs.append(red_faces[j]->get_surface_ptr());
+
+			DLIList<Surface*> yellow_surfs;
+			for(j = 0;j<yellow_faces.size();j++)
+				yellow_surfs.append(yellow_faces[j]->get_surface_ptr());
+
+            // all of the surfaces are offset the same distance
+			double offset_distance = offset_distances[0];
+            bool old_error_flag = GET_ERROR_FLAG();
+            SET_ERROR_FLAG(false); // don't throw any gme errors
+			if( gme->create_offset_sheet(red_surfs,offset_distance,
+				NULL,NULL,results))
+            {
+                midsurface_done = true;
+                for(j = 0;j<results.size();j++) // for every body add a thickness
+                    thickness_out.append(fabs(offset_distance*2.));
+            }
+            else if( gme->create_offset_sheet(yellow_surfs,offset_distance,
+				NULL,NULL,results)) // try the other direction
+            {
+                midsurface_done = true;
+                for(j = 0;j<results.size();j++) // for every body add a thickness
+                    thickness_out.append(fabs(offset_distance*2.));
+            }
+            else
+            {
+                PRINT_INFO("Could not create midsurface for Body %d - try using the surface offset command\n",cur_body->id());
+                failing_bodies.append(cur_body);
+            }
+            SET_ERROR_FLAG(old_error_flag); // turn errors back on
+        }
+        
+        if(!midsurface_done && paired_faces.size() != red_faces.size() + yellow_faces.size())
+        {
+            PRINT_INFO("Could not find workable surface pairs for Body %d - try changing the search range or \n"
+                "        using the Sheet Offset command.\n",cur_body->id());
+        }
+
+      /*if(!midsurface_done)
+        {
+			if(DEBUG_FLAG(198))
+				PRINT_INFO("Trying the extend, unite, and trim method\n");
+
+			// okay now remove duplicate pairs and unsupported pairs
+			DLIList<Surface*> surf_list1;
+			DLIList<Surface*> surf_list2;
+			bool delete_and_exit = false;
+			for(int j = 0;j<list1.size();j++)
+			{
+				RefFace* face_1 = list1[j];
+				RefFace* face_2 = list2[j];
+
+				if(DEBUG_FLAG(198))
+				{
+					PRINT_INFO("Red surface ");
+					GfxDebug::draw_ref_face(face_1,CUBIT_RED);
+					PRINT_INFO("%d ",face_1->id());
+
+					PRINT_INFO("\nYellow surface ");
+					GfxDebug::draw_ref_face(face_2,CUBIT_YELLOW);
+					PRINT_INFO("%d ",face_2->id());
+
+					PRINT_INFO("\n");
+				}
+
+				if(face_1->geometry_type() != 	face_2->geometry_type())
+					continue;
+
+				Surface* surf_1 = face_1->get_surface_ptr();
+				surf_list1.append(surf_1);
+				Surface* surf_2 = face_2->get_surface_ptr();
+				surf_list2.append(surf_2);
+				BodySM* result_body;
+				switch(face_1->geometry_type())
+				{
+				case CONE_SURFACE_TYPE:
+					if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+						results.append(result_body);
+					else
+					    delete_and_exit = true;
+					break;
+				case PLANE_SURFACE_TYPE:
+					if(get_planar_mid_surface(face_1,face_2,body_sm,result_body,gme) == CUBIT_SUCCESS)
+						results.append(result_body);
+					else
+					    delete_and_exit = true;
+					break;
+				case SPHERE_SURFACE_TYPE:
+					if(gme->get_spheric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+						results.append(result_body);
+					else
+					    delete_and_exit = true;
+					break;
+				case TORUS_SURFACE_TYPE:
+					if(gme->get_toric_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+						results.append(result_body);
+					else
+					    delete_and_exit = true;
+					break;
+				case CYLINDER_SURFACE_TYPE:
+					if(gme->get_conic_mid_surface(surf_1,surf_2,body_sm,result_body) == CUBIT_SUCCESS)
+						results.append(result_body);
+					else
+					    delete_and_exit = true;
+					break;
+				default:
+					delete_and_exit = true;
+					break;
+				}
+
+				if(delete_and_exit)
+				{
+					PRINT_WARNING("Failed to pair surface %d with surface %d\n",face_1->id(),face_2->id());
+					break;
+				}
+			}
+
+			if(delete_and_exit)
+			{
+				failing_bodies.append(cur_body);
+    			gqe->delete_solid_model_entities(results);
+				continue;
+			}
+
+			DLIList<BodySM*> unite_results;
+			if(results.size()>1)
+			{
+				bool reg_result = GeometryModifyTool::instance()->boolean_regularize();
+				GeometryModifyTool::instance()->boolean_regularize(true);
+				if(gme->unite(results,unite_results)== CUBIT_SUCCESS)
+				{
+					// if the unite works just add them to the result list
+					results = unite_results;
+				}
+				else
+				{
+					// clean up the created surfaces and move on to the next
+					// body
+					failing_bodies.append(cur_body);
+					gqe->delete_solid_model_entities(results);
+					GeometryModifyTool::instance()->boolean_regularize(reg_result);
+					continue;
+				}
+
+				GeometryModifyTool::instance()->boolean_regularize(reg_result);
+			}
+
+			// trim the hanging surfaces 
+			DLIList<Surface*> paired_surfs;
+			paired_surfs += surf_list1;
+			paired_surfs += surf_list2;
+
+			DLIList<Curve*> all_curves;
+
+			int k = 0;
+			for(k = 0;k<results.size();k++)
+				results[k]->curves(all_curves);
+
+			all_curves.uniquify_unordered();
+
+			DLIList<Surface*> remove_surfs;
+			for(k = 0;k<all_curves.size();k++)
+				for(int m = 0;m<paired_surfs.size();m++)
+					if(curve_in_surface(all_curves[k],paired_surfs[m]))
+						all_curves[k]->surfaces(remove_surfs);
+
+			remove_surfs.uniquify_unordered();
+
+			body_list_out += results;
+			DLIList<BodySM*> tweak_results;
+			if(gme->tweak_remove(remove_surfs,tweak_results,CUBIT_FALSE))
+			{
+				results = tweak_results;
+			}
+			else
+			{
+				// clean up the created surfaces and move on to the next
+				// body
+				failing_bodies.append(cur_body);
+				gqe->delete_solid_model_entities(results);
+				continue;
+			}
+
+			DLIList<BodySM*> regularize_results;
+			// regularize the results
+			for(k = 0;k < results.size();k++)
+			{
+				BodySM* new_body = 0;
+				if(gme->regularize_body(results[k],new_body))
+					regularize_results.append(new_body);
+				else if(DEBUG_FLAG(198))
+					PRINT_INFO("Regularize failure\n");
+			}
+            results = regularize_results;
+        }*/
+
+        if(!midsurface_done)
+        {
+           failing_bodies.append(cur_body);
+           continue;
+        }
+
+        old_bodies_midsurfaced.append(cur_body);
+
+        if(delete_midsurfaced && !preview)
+            GeometryQueryTool::instance()->delete_Body(cur_body);
+
+        return_status = CUBIT_SUCCESS;
+        body_list_out += results;
+    }
+
+    if(prog_tool)
+        prog_tool->end();
+
+    PRINT_INFO("Successfully midsurface %d of %d bodies\n",body_list_out.size(),body_list_in.size());
+    if(preview)
+    {
+        for(int k = 0;k<body_list_out.size();k++)
+        {
+            DLIList<Surface*> preview_surfaces;
+            body_list_out[k]->surfaces(preview_surfaces);
+            for(int p = 0;p<preview_surfaces.size();p++)
+                GfxPreview::draw_surface_facets_shaded(preview_surfaces[p],CUBIT_BLUE);
+        }
+        GfxPreview::flush();
+        if(gqe)
+            gqe->delete_solid_model_entities(body_list_out);
+        body_list_out.clean_out();
+    }
+
+	if(failing_bodies.size() > 0)
+	{
+        PRINT_INFO("\n");
+		PRINT_INFO("Failed to midsurface Body ");
+		for(i = 0;i<failing_bodies.size();i++)
+			PRINT_INFO("%d ",failing_bodies[i]->id());
+		PRINT_INFO("\n");
+	}
+
+	if(DEBUG_FLAG(198))
+		GfxDebug::flush();
+
+	SurfaceOverlapTool::instance()->set_check_within_bodies(cubit_bool_save);
+	SurfaceOverlapTool::instance()->set_gap_max(max_gap_save);
+	SurfaceOverlapTool::instance()->set_normal_type(normal_type);
+	SurfaceOverlapTool::instance()->set_gap_min(min_gap_save);
+    SurfaceOverlapTool::instance()->set_skip_facing_surfaces(skip_facing_surfaces);
+
+	return return_status;
+}
+
+
+CubitStatus AutoMidsurfaceTool::get_planar_mid_surface( RefFace* ref_face1,
+													   RefFace* ref_face2,
+													   BodySM* body_sm_to_trim_to,
+													   BodySM*& midsurface_body_sm,
+													   GeometryModifyEngine *gme_ptr )
+{
+	CubitVector normal_1, normal_2, point_1, point_2, point_3;
+	CubitPlane plane_1, plane_2;
+	CubitVector p_mid, n_mid;
+
+	point_1 = ref_face1->center_point();
+	point_2 = ref_face2->center_point();
+
+	normal_1 = ref_face1->normal_at(point_1);
+	normal_2 = ref_face2->normal_at(point_2);
+
+	plane_1 = CubitPlane(normal_1,point_1);
+	plane_2 = CubitPlane(normal_2,point_2);
+
+	if(point_1 == point_2)
+	{
+		PRINT_ERROR( "In GeometryModifyTool:: get_planar_mid_surface\n"
+			"       Since both surfaces share the same point, the midsurface is not well-defined\n");
+		return CUBIT_FAILURE;
+	}
+	else
+	{
+		CubitVector temp1 = point_2;
+		temp1 = plane_1.project(temp1);
+		temp1 -= point_2;
+		if ( temp1.length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
+		{
+			PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n"
+				"       Since both planes are the same, the midsurface is not well-defined.\n");
+			return CUBIT_FAILURE;
+		}
+	}
+
+	if ( ( normal_1.about_equal( normal_2 ) ) || ( (-normal_1).about_equal( normal_2 ) ) )
+	{
+		p_mid = (point_1+point_2)/2;
+		n_mid = plane_1.normal();
+	}
+	else
+	{
+		CubitVector direction_of_line;
+		plane_1.intersect(plane_2,p_mid,direction_of_line);
+		direction_of_line.normalize();
+
+		// Find if point_1 and point_2 are on the line of intersection
+		// If they are, then the mid-plane is not well-defined
+		CubitVector p1 = point_1-p_mid;
+		CubitVector p2 = point_2-p_mid;
+		p1.normalize();
+		p2.normalize();
+
+		if(p1==direction_of_line || p1==-direction_of_line)
+		{
+			PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n"
+				"       P1 is on the line of intersection.\n");
+			return CUBIT_FAILURE;
+		}
+
+		if(p2==direction_of_line || p2==-direction_of_line)
+		{
+			PRINT_ERROR("In GeometryModifyTool:: get_planar_mid_surface\n"
+				"       P2 is on the line of intersection.\n");
+			return CUBIT_FAILURE;
+		}
+
+		CubitVector v1 = p1 - (p1%direction_of_line)*direction_of_line;
+		v1.normalize();
+
+		CubitVector v2 = p2 - (p2%direction_of_line)*direction_of_line;
+		v2.normalize();
+
+		n_mid = v1 - v2;
+		n_mid.normalize();
+	}
+
+	CubitPlane mid_plane(n_mid, p_mid);
+	point_1 = p_mid;
+
+	//find three points that will define the infinite plane from the
+	//mid plane.through the point in any direction just not along the
+	//normal direction
+	CubitVector Xdir(1,0,0), Ydir(0,1,0);
+	CubitVector direction1;
+
+	if ( ( ! n_mid.about_equal( Xdir ) ) && ( ! (-n_mid).about_equal( Xdir ) ) )
+		direction1 = Xdir + n_mid;
+	else
+		direction1 = Ydir + n_mid;
+
+	point_2 = p_mid + direction1;
+	point_2 = mid_plane.project(point_2);
+
+	direction1 = point_2-point_1;
+	CubitVector direction2 = direction1*n_mid;
+	point_3 = point_1 + direction2;
+
+	CubitStatus ret = gme_ptr->get_mid_plane(point_1, point_2, point_3,
+		body_sm_to_trim_to, midsurface_body_sm );
+	return ret;
+}
+
+CubitBoolean AutoMidsurfaceTool::curve_in_surface(Curve *curve_in, Surface *surf_in)
+{
+	CubitVector loc_0;
+	CubitVector loc_1;
+	CubitVector loc_2;
+
+	curve_in->position_from_fraction(0.1,loc_0);
+	curve_in->position_from_fraction(0.5,loc_1);
+	curve_in->position_from_fraction(0.9,loc_2);
+
+	GeometryQueryEngine* gqe = surf_in->get_geometry_query_engine();
+	double tol = gqe->get_sme_resabs_tolerance();
+	CubitVector cl_pnt_0;
+	CubitVector cl_pnt_1;
+	CubitVector cl_pnt_2;
+	surf_in->closest_point(loc_0,&cl_pnt_0);
+	surf_in->closest_point(loc_1,&cl_pnt_1);
+	surf_in->closest_point(loc_2,&cl_pnt_2);
+
+	if(cl_pnt_0.distance_between(loc_0)<tol &&
+		cl_pnt_1.distance_between(loc_1)<tol &&
+		cl_pnt_2.distance_between(loc_2)<tol)
+	{
+		return CUBIT_TRUE;
+	}
+
+	return CUBIT_FALSE;
+}
+
+CubitStatus AutoMidsurfaceTool::find_offset_pair_patches(
+	DLIList<RefFace*> pairs_list_0,
+	DLIList<RefFace*> pairs_list_1,	
+	DLIList<RefFace*>& red_faces,
+	DLIList<RefFace*>& yellow_faces,
+	DLIList<double>& offset_distances)
+{
+	return CUBIT_FAILURE;
+}
+
+CubitStatus AutoMidsurfaceTool::random_loc_on_surface( Surface* face_ptr, CubitVector &loc )
+{
+  GMem g_mem;
+  GeometryQueryEngine* gqe = face_ptr->get_geometry_query_engine();
+  unsigned short norm_tol = 10;
+  double dist_tol = -1.0;
+  gqe->get_graphics( face_ptr, &g_mem, norm_tol, dist_tol );
+
+  if(g_mem.fListCount < 1)
+  {
+    // Decrease tolerance and try again (we can get this for small features)
+    norm_tol /= 2;
+    gqe->get_graphics( face_ptr, &g_mem, norm_tol, dist_tol);
+  }
+
+  if(g_mem.fListCount < 1)
+  {
+    // Lets give up
+    PRINT_ERROR( "Unable to find location on a surface\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Use the first triangle
+  GPoint p[3];
+  GPoint* plist = g_mem.point_list();
+  int* facet_list = g_mem.facet_list();
+  int c = 0;
+
+  p[0] = plist[facet_list[++c]];
+  p[2] = plist[facet_list[++c]];
+  p[1] = plist[facet_list[++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;
+
+  face_ptr->closest_point_trimmed(center,loc);
+
+  return CUBIT_SUCCESS;
+}
+
+CubitBoolean AutoMidsurfaceTool::check_surf_pairs(double min_thick, double max_thick,
+                                                 DLIList<RefFace*> check_list, Body* body_in )
+{
+    double total_area = 0.0;
+    DLIList<RefVolume*> vol_list;
+    body_in->ref_volumes(vol_list);
+    double total_vol = 0;
+    for(int vol_cnt = 0; vol_cnt < vol_list.size(); vol_cnt++)
+    {
+        CubitVector cg;
+        double temp_volume;
+        vol_list[vol_cnt]->mass_properties(cg,temp_volume);
+        total_vol += temp_volume;
+    }
+
+    for(int i = 0;i<check_list.size();i++)
+        total_area += check_list[i]->area();
+
+    total_area/=2.0;
+
+    if(min_thick*total_area < total_vol && max_thick*total_area > total_vol)
+        return CUBIT_TRUE;
+
+    return CUBIT_FALSE;
+}

Added: cgm/branches/cubit/geom/AutoMidsurfaceTool.hpp
===================================================================
--- cgm/branches/cubit/geom/AutoMidsurfaceTool.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/AutoMidsurfaceTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,79 @@
+//-------------------------------------------------------------------------
+// Filename      : AutoMidsurfaceTool.cpp
+//
+// Purpose       : 
+//   Create a midsurface of a body/volume given a thickness range. If no thickness range is given
+//   then make a educated guess at the thickness (using something like Volume/Surface Area).
+//   
+//   Create Midsurface Volume <id_list> auto [<lower_tol> <upper_tol>]
+//
+// Creator       : Sam Showman
+//
+// Creation Date : 05/10/2008
+//-------------------------------------------------------------------------
+#ifndef AutoMidsurfaceTool_HPP
+#define AutoMidsurfaceTool_HPP
+
+#include "CubitDefines.h"
+#include "CubitVector.hpp"
+#include "CubitPlane.hpp"
+
+class GeometryModifyEngine;
+class Body;
+class RefFace;
+class BodySM;
+class Surface;
+class Curve;
+class RefEdge;
+template <class X> class DLIList;
+
+class AutoMidsurfaceTool
+{
+public:
+
+    AutoMidsurfaceTool();
+    ~AutoMidsurfaceTool(){}
+
+    CubitStatus midsurface(
+	DLIList<Body*> &body_list_in,
+    DLIList<BodySM*> &body_list_out,
+    DLIList<Body*> &old_bodies_midsurfaced,
+    DLIList<double> &thickness_out,
+    double lower_tol = CUBIT_DBL_MAX,
+    double upper_tol = CUBIT_DBL_MAX,
+    CubitBoolean delete_midsurfaced = CUBIT_FALSE,
+    CubitBoolean preview = CUBIT_FALSE);
+    //- automatically midsurfaces a volume based on surface pairs and surface area
+    //- body_list_in - list of bodies to midsurface
+	//- body_list_out - result bodies
+    //- lower_tol - lower tolerance
+    //- upper_tol - upper tolerance
+    //- delete_midsurfaced - delete the midsurfaced solid
+    //- transp_midsurfaced - make the midsurfaced solid transparent
+	//- preview - preview the results
+
+private:
+	CubitBoolean curve_in_surface(Curve *curve_in, Surface *surf_in);
+
+	CubitStatus get_planar_mid_surface(
+		RefFace* ref_face1,
+		RefFace* ref_face2,
+		BodySM* body_sm_to_trim_to,
+		BodySM*& midsurface_body_sm,
+		GeometryModifyEngine *gme_ptr );
+
+	CubitStatus find_offset_pair_patches(
+        DLIList<RefFace*> pairs_list_0,
+        DLIList<RefFace*> pairs_list_1,	
+        DLIList<RefFace*>& red_faces,
+        DLIList<RefFace*>& yellow_faces,
+        DLIList<double>& offset_distances);
+
+    CubitStatus random_loc_on_surface( Surface* face_ptr, CubitVector &loc );
+
+    CubitBoolean check_surf_pairs(double min_thick, double max_thick,
+        DLIList<RefFace*> check_list, Body* body_in );
+};
+
+#endif
+

Modified: cgm/branches/cubit/geom/Body.cpp
===================================================================
--- cgm/branches/cubit/geom/Body.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Body.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -33,6 +33,7 @@
 #include "GeometryQueryEngine.hpp"
 #include "CastTo.hpp"
 
+
 //-------------------------------------------------------------------------
 // Purpose       : Default constructor.
 //
@@ -73,8 +74,6 @@
    // Set the Entity ID for this new Body
    entityId = RefEntityFactory::instance()->next_body_id();
 
-   copied_from_body_id = 0;
-
      // read and initialize attributes
    auto_read_cubit_attrib();
    auto_actuate_cubit_attrib();
@@ -112,73 +111,6 @@
   return dynamic_cast<BodySM*>(bridge);
 }
 
-//* Method: copiedFromId
-//** Sets the Id of the body that this body was copied from
-//*==
-
-void Body::copiedFromId( int Id )
-{
-    copied_from_body_id = Id;
-}
-
-//* Method: copiedFromId
-//** Returns the Id of the body that this body was copied from
-//*==
-
-int Body::copiedFromId ()
-{
-    return copied_from_body_id;
-}
-
-/* This is wrong for misc. arrangements of non-manifold topology
- * -- j.kraftcheck
-   
-CubitBoolean Body::is_sheet_body()
-{
-    //This function just checks for bodies which have a single coedge
-    // on a RefEdge, which would indicate an open sheet body.  This
-    // function will not find sheet bodies which are closed...
-  DLIList<CoEdge*> co_edges;
-  this->co_edges( co_edges );
-  DLIList<RefEdge*> edge_list_1, edge_list_2;
-  int i;
-  for( i = co_edges.size(); i > 0; i-- )
-  {
-    CoEdge* this_co_edge = co_edges.get_and_step();
-    RefEdge* this_ref_edge = this_co_edge->get_ref_edge_ptr();
-    if( edge_list_1.is_in_list( this_ref_edge ) )
-    {
-      edge_list_2.append( this_ref_edge );
-    }
-    else
-    {
-      edge_list_1.append_unique( this_ref_edge );
-    }
-  }
-  
-    //subtract edge_list_2 from edge_list_1
-  DLIList<RefEdge*> temp_list = edge_list_1;
-  for( i = temp_list.size(); i > 0; i-- )
-  {
-    RefEdge* this_edge = temp_list.get_and_step();
-    if( edge_list_2.is_in_list( this_edge ) )
-    {
-      edge_list_1.remove( this_edge );
-    }
-  }
-  
-  if( edge_list_1.size() > 0 )
-  {
-    for( i = edge_list_1.size(); i > 0; i-- )
-    {
-      if( edge_list_1.get_and_step()->geometry_type() != POINT_CURVE_TYPE )
-         return CUBIT_TRUE;
-    }
-  }
-  return CUBIT_FALSE;
-}
- */
-
 //-------------------------------------------------------------------------
 // Purpose       : Check if this body contains only sheet volumes.
 //

Modified: cgm/branches/cubit/geom/Body.hpp
===================================================================
--- cgm/branches/cubit/geom/Body.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Body.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -30,6 +30,7 @@
 
 class CubitTransformMatrix;
 
+//! Body class.
 class CUBIT_GEOM_EXPORT Body : public GroupingEntity,
              public RefEntity
 {
@@ -45,36 +46,44 @@
 
     /* topology */
   
+  //! Gets the dag type.
   DagType dag_type() const { return DagType::body_type(); }
+
+  //! Gets the type info.
   const type_info& entity_type_info() const { return typeid(Body); }
 
+  //! Gets the class name: "Body". 
   static const char* get_class_name()
      {
        return "Body";
      }
+
+  //! Gets the class name: "Body". 
   virtual const char* class_name() const
      {
        return get_class_name();
      }
   
+  //! Gets the underlying BodySM pointer.
   BodySM* get_body_sm_ptr() const;
 
+  //! Returns the bounding box of this body
   virtual CubitBox bounding_box();
-  /*- Returns the bounding box of this body
-   */
 
+  //! Return a CubitVector set to the centroid of this body
   virtual CubitVector center_point();
-  /*- Return a CubitVector set to the centroid of this body
-   */
 
+  //! Get certain mass props, cofg is center of gravity
   CubitBoolean get_mass_props(CubitVector& cofg);
-    /* Get certain mass props, cofg is center of gravity */
        
+  //! Determines whether a point is inside, outside, or on boundary
+  //! of a volume.
   CubitPointContainment point_containment( CubitVector &point );
-    //- Determines whether a point is inside, outside, or on boundary
-    //- of a volume.
   
+  //! Returns the volume of this body.
   virtual double measure();
+
+  //! Query to see if this is a sheet body.
   CubitBoolean is_sheet_body();
 
 #ifdef BOYD14
@@ -100,20 +109,15 @@
    */
 #endif
 
+  //! Do a measure and api entity check.
   virtual int validate();
-  /*- do a measure and api entity check.
-   */
   
+  //! Functions related to "measuring" the Body
   virtual CubitString measure_label();
-  /*- Functions related to "measuring" the Body
-   */
 
-  void copiedFromId( int Id );
-  int copiedFromId ();
-  /*- Sets/Gets the id of the body that it was copied from */
-
-
+  //! Sets the color.
   virtual void color(int value);
+  //! Gets the color.
   virtual int color() const;
 
 protected: 
@@ -139,8 +143,6 @@
    */
 #endif
 
-  int copied_from_body_id;
-  
   Body( const Body& );
   void operator=( const Body& );
 

Modified: cgm/branches/cubit/geom/BoundingBoxTool.cpp
===================================================================
--- cgm/branches/cubit/geom/BoundingBoxTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/BoundingBoxTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -219,9 +219,9 @@
          num_tri = num_facet / 4;
 
          GPoint* point_list = g_mem->point_list();
-         int num_pnts = g_mem->point_list_size();
+         //int num_pnts = g_mem->point_list_size();
          int y;
-         for( y=0; y<num_pnts; y++ )
+         for( y=0; y<num_pnt; y++ )
          {
             CubitVector* cubit_vector_ptr = new CubitVector(
                point_list[y].x, point_list[y].y, point_list[y].z );

Modified: cgm/branches/cubit/geom/BoundingBoxTool.hpp
===================================================================
--- cgm/branches/cubit/geom/BoundingBoxTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/BoundingBoxTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -13,28 +13,30 @@
 class CubitVector;
 class RefEntity;
 
+//! Class for bounding boxes (primarily for "tight" bounding boxes).
 class CUBIT_GEOM_EXPORT BoundingBoxTool
 {
 
 public :   
 
+   //! Gets tightest box around the given entity list, using facets.
+   //! Box is defined as center point, vector axes (unit vectors), and
+   //!  extension in each axis (x extension is 1/2 width of box, for example).
    static CubitStatus get_tight_bounding_box( DLIList<RefEntity*> &ref_entity_list, 
                                        CubitVector &center,
                                        CubitVector axes[3],
                                        CubitVector &extension,
                                        double ang_facet_tol,
                                        double abs_facet_tol);
-   //- Gets tightest box around the given entity list, using facets.
-   //- Box is defined as center point, vector axes (unit vectors), and
-   //-  extension in each axis (x extension is 1/2 width of box, for example).
 
+   //! Convenience function to get an axis box in the same output format as
+   //! a tight box.
    static CubitStatus get_axis_bounding_box( DLIList<RefEntity*> &ref_entity_list, 
                                       CubitVector &center,
                                       CubitVector axes[3],
                                       CubitVector &extension );
-   //- Convenience function to get an axis box in the same output format as
-   //- a tight box.
 
+   //! Using the center, axes and extension, gets the 8 corners of the box.
    static CubitStatus get_corner_points( CubitVector &center,
                                   CubitVector axes[3],
                                   CubitVector &extension,
@@ -42,45 +44,47 @@
                                   CubitVector& p3, CubitVector& p4,
                                   CubitVector& p5, CubitVector& p6,
                                   CubitVector& p7, CubitVector& p8);
-   //- Using the center, axes and extension, gets the 8 corners of the box.
 
+   //! If triangles are used, surface facet points will be included in 
+   //! the point list used to calculate the tight bounding box.  This 
+   //! will include vertices and points on the curves.  This is the 
+   //! default implementation.
    static CubitBoolean get_use_triangles();
    static void set_use_triangles( CubitBoolean val );
-   //- If triangles are used, surface facet points will be included in 
-   //- the point list used to calculate the tight bounding box.  This 
-   //- will include vertices and points on the curves.  This is the 
-   //- default implementation.
+
    static int get_use_triangles_setting();
    static void set_use_triangles_setting( int val );
 
+   //! If curves are used, curve tesselation points will be included in
+   //! the point list used to calculate the tight bounding box.  This
+   //! includes the vertices on the ends of the curves.  One use for this
+   //! is to find a more accurate tight bounding box, since curve 
+   //! tessellations are typically more fine than surface tessellations.
+   //! However, in practice, I would generally recommend just using surface
+   //! tessellations.  One special case is if the user sends in a list of
+   //! curves as the criteria for the tight bounding box, the curve 
+   //- tessellations are always used, even if this parameter is false.
    static CubitBoolean get_use_curves();
    static void set_use_curves( CubitBoolean val );
-   //- If curves are used, curve tesselation points will be included in
-   //- the point list used to calculate the tight bounding box.  This
-   //- includes the vertices on the ends of the curves.  One use for this
-   //- is to find a more accurate tight bounding box, since curve 
-   //- tessellations are typically more fine than surface tessellations.
-   //- However, in practice, I would generally recommend just using surface
-   //- tessellations.  One special case is if the user sends in a list of
-   //- curves as the criteria for the tight bounding box, the curve 
-   //- tessellations are always used, even if this parameter is false.
+
    static int get_use_curves_setting();
    static void set_use_curves_setting( int val );
 
+   //! If vertices are used, vertex points will be included in the point 
+   //! list used to calculate the tight bounding box.  In extremely large
+   //! models, it could be advantageous to just use vertices.  So the user
+   //! would turn off both the surface and curve flags.  One special case 
+   //! is if the user sends in a list of curves as the criteria for the 
+   //! tight bounding box, the curve tessellations are always used, even 
+   //! if the curve parameter is false and this parameter is true.
    static CubitBoolean get_use_vertices();
    static void set_use_vertices( CubitBoolean val );
-   //- If vertices are used, vertex points will be included in the point 
-   //- list used to calculate the tight bounding box.  In extremely large
-   //- models, it could be advantageous to just use vertices.  So the user
-   //- would turn off both the surface and curve flags.  One special case 
-   //- is if the user sends in a list of curves as the criteria for the 
-   //- tight bounding box, the curve tessellations are always used, even 
-   //- if the curve parameter is false and this parameter is true.
+
    static int get_use_vertices_setting();
    static void set_use_vertices_setting( int val );
 
  
-   //Initialize all settings in this class
+   //! Initialize all settings in this class
    static void initialize_settings();
     
 protected :

Modified: cgm/branches/cubit/geom/CADefines.hpp
===================================================================
--- cgm/branches/cubit/geom/CADefines.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CADefines.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -52,6 +52,9 @@
     CA_ASSEMBLY_DATA,
     CA_SIZING_FUNCTION_SKELETON,
     CA_SOURCE_FEATURE
+#ifdef CAT
+	,CA_PRO_WELD
+#endif
 };
 
 #endif // __CADEFINES_H__

Modified: cgm/branches/cubit/geom/CAEntityId.cpp
===================================================================
--- cgm/branches/cubit/geom/CAEntityId.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CAEntityId.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -19,6 +19,8 @@
 #include "GeometryQueryTool.hpp"
 #include "GSaveOpen.hpp"
 #include "CADeferredAttrib.hpp"
+#include "BasicTopologyEntity.hpp"
+#include "GeometryEntity.hpp"
 
 CubitAttrib* CAEntityId_creator(RefEntity* entity, CubitSimpleAttrib *p_csa)
 {
@@ -130,6 +132,14 @@
   RefEntity *other_entity = 
     GeometryQueryTool::instance()->get_ref_entity(attribOwnerEntity->class_name(), 
                                                   entityId+id_inc);
+
+  // Check to make sure the other entity has a valid topology bridge.  If 
+  // it doesn't it may be a ref entity hanging around that still needs
+  // to be cleaned up so don't consider it in the checks below.
+  TopologyEntity *te = dynamic_cast<TopologyEntity*>(other_entity);
+  if(te && !te->bridge_manager()->topology_bridge())
+    other_entity = NULL;
+
     // 2) already an entity with the new id;
   if (other_entity) {
       // 2a) if other entity has a CAMP attribute, this owner has one too,
@@ -225,7 +235,8 @@
     other_entity->find_cubit_attrib_type(CA_ENTITY_ID, att_list);
     CAEntityId *other_caeid = (att_list.size() ?  CAST_TO(att_list.get(), CAEntityId)
                                : NULL);
-    if ( other_caeid && other_caeid->id()+id_inc != entityId+id_inc) {
+    if (other_caeid && other_caeid->id()+id_inc != entityId+id_inc)
+    {
         // need to reset owner entity id first, so that we don't have
         // two identical ids active at the same time (messes up the
         // graphics)
@@ -276,6 +287,9 @@
     // ok, now set the id and return
   attribOwnerEntity->set_id (entityId+id_inc, CUBIT_FALSE);
   attribOwnerEntity->color(CUBIT_DEFAULT_COLOR);
+  BasicTopologyEntity *bte = CAST_TO( attribOwnerEntity, BasicTopologyEntity );
+  if( bte )
+    bte->get_geometry_entity_ptr()->set_saved_id(entityId+id_inc);
 
   hasActuated = CUBIT_TRUE;
 

Modified: cgm/branches/cubit/geom/CAMergePartner.cpp
===================================================================
--- cgm/branches/cubit/geom/CAMergePartner.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CAMergePartner.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -86,6 +86,12 @@
 
 CubitStatus CAMergePartner::actuate()
 {
+  hasActuated = CUBIT_TRUE;
+  return CUBIT_SUCCESS;
+  //We don't need to actuate this attribute here since the merging
+  //happens in GeometryQueryTool::check_mergeable_refentity.
+  
+  /*
   if (hasActuated == CUBIT_TRUE) return CUBIT_SUCCESS;
   
   BasicTopologyEntity * bte_ptr = CAST_TO(attribOwnerEntity,BasicTopologyEntity); 
@@ -93,7 +99,7 @@
     return CUBIT_FAILURE;
   
   DLIList<RefEntity*> merge_list;
-  merge_prepare(merge_list);
+  //merge_prepare(merge_list);
   merge_list.append_unique(attribOwnerEntity);
 
   CubitStatus result = CUBIT_SUCCESS;
@@ -107,7 +113,7 @@
     hasActuated = CUBIT_TRUE;
   }        
 
-  return result;
+  return result; */
 }
 
 void CAMergePartner::merge_prepare(DLIList<RefEntity*> &merge_list)
@@ -132,9 +138,15 @@
   }
   
     // now put those entities into the merge_list
-  for (i = td_list.size(); i > 0; i--) {
+  for (i = td_list.size(); i > 0; i--) 
+  {
     re_ptr = CAST_TO(td_list.get(), RefEntity);
-    if (re_ptr) merge_list.append(re_ptr);
+    if (re_ptr) 
+    {
+      CubitAttrib *tmp_attrib = re_ptr->get_cubit_attrib( CA_MERGE_PARTNER, CUBIT_FALSE );
+      if( tmp_attrib )
+        merge_list.append(re_ptr);
+    }
     td_list.step();
   }
   

Modified: cgm/branches/cubit/geom/CGMApp.cpp
===================================================================
--- cgm/branches/cubit/geom/CGMApp.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CGMApp.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -17,6 +17,7 @@
 
 #include "GeometryQueryTool.hpp"
 #include "GeometryModifyTool.hpp"
+#include "GeometryFeatureTool.hpp"
 #include "GeometryHealerTool.hpp"
 #include "BoundingBoxTool.hpp"
 #include "RefEntityName.hpp"
@@ -25,6 +26,7 @@
 #include "TDUniqueId.hpp"
 #include "MergeTool.hpp"
 #include "OldUnmergeCode.hpp"
+#include "ModelQueryEngine.hpp"
 
 // TODO - I'm not sure this is the place to include all the attributes
 #include "CADefines.hpp"
@@ -37,6 +39,9 @@
 #include "CAEntityColor.hpp"
 #include "CAMergeStatus.hpp"
 #include "CASourceFeature.hpp"
+#ifdef CAT
+#include "cat\CAProWeld.hpp"
+#endif
 
 CGMApp* CGMApp::instance_ = NULL;
 
@@ -92,11 +97,17 @@
 
 void CGMApp::shutdown()
 {
-   delete GeometryHealerTool::instance();
-   delete GeometryModifyTool::instance();
-   delete GeometryQueryTool::instance();
+   GeometryHealerTool::delete_instance();
+   GeometryModifyTool::delete_instance();
+   GeometryQueryTool::delete_instance();
+   GeometryFeatureTool::delete_instance();
+   AnalyticGeometryTool::delete_instance();
+   RefEntityName::delete_instance();
+   MergeTool::delete_instance();
+   ModelQueryEngine::delete_instance();
 
-mAppStarted = CUBIT_FALSE;
+   DAG::delete_instance();
+   mAppStarted = CUBIT_FALSE;
 }
 
 void CGMApp::initialize_settings()
@@ -169,6 +180,14 @@
                                                CUBIT_TRUE, CUBIT_TRUE, CUBIT_TRUE,
                                                CUBIT_TRUE, CUBIT_FALSE);
   assert (CUBIT_SUCCESS == result);
+#ifdef CAT
+  result = CGMApp::instance()->attrib_manager()->register_attrib_type(
+                                               CA_PRO_WELD, "pro weld", "PRO_WELD",
+                                               CAProWeld_creator, CUBIT_TRUE,
+                                               CUBIT_TRUE, CUBIT_TRUE, CUBIT_TRUE,
+                                               CUBIT_TRUE, CUBIT_FALSE);
+  assert (CUBIT_SUCCESS == result);
+#endif
 }
 
 CubitAttribManager* CGMApp::attrib_manager()

Modified: cgm/branches/cubit/geom/CGMApp.hpp
===================================================================
--- cgm/branches/cubit/geom/CGMApp.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CGMApp.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -40,6 +40,7 @@
 #include "CubitDefines.h"
 #include "CubitAttribManager.hpp"
 #include "CubitGeomConfigure.h"
+#include "DAG.hpp"
 
 class CUBIT_GEOM_EXPORT CGMApp
 {

Modified: cgm/branches/cubit/geom/CGMEngineDynamicLoader.cpp
===================================================================
--- cgm/branches/cubit/geom/CGMEngineDynamicLoader.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CGMEngineDynamicLoader.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -3,6 +3,7 @@
 #include "CGMEngineDynamicLoader.hpp"
 
 #include "CubitMessage.hpp"
+#include <string.h>
 
 extern "C"
 {
@@ -111,7 +112,17 @@
 }
 
 CubitStatus CGMEngineDynamicLoader::unload_engine()
-{
+{ 
+  return CUBIT_SUCCESS;
+
+  /*
+
+//don't unload cubitcatia.dll
+#ifdef CATIA 
+  if( mEngineName == "CATIA")
+    return CUBIT_SUCCESS;
+#endif 
+
   if(mLibraryHandle != CubitDynamicLoader::InvalidLibraryHandle)
   {
     CubitDynamicLoader::unload_library(mLibraryHandle);
@@ -119,8 +130,9 @@
     mLibraryHandle = CubitDynamicLoader::InvalidLibraryHandle;
     mQueryEngine = NULL;
     mModifyEngine = NULL;
-  }
+  } 
   return CUBIT_SUCCESS;
+  */
 }
 
 
@@ -154,7 +166,7 @@
 GeometryQueryEngine* CGMEngineDynamicLoader::get_gqe()
 {
   if(mQueryEngine)
-    return mQueryEngine;
+    return mQueryEngine;  
 
   if(mLoadAttempted == CUBIT_FALSE)
     load_engine();

Added: cgm/branches/cubit/geom/CGMHistory.cpp
===================================================================
--- cgm/branches/cubit/geom/CGMHistory.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/CGMHistory.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,157 @@
+
+#include "CGMHistory.hpp"
+#include "TopologyBridge.hpp"
+#include "CubitMessage.hpp"
+#include "RefEntity.hpp"
+
+const char* event_names[] = 
+{
+  "TOP_LEVEL_ENTITY_CREATED",
+  "TOP_LEVEL_ENTITY_DELETED",
+  "ENTITY_CREATED",
+  "ENTITY_DELETED",
+  "TOPOLOGY_CHANGED",
+  "GEOMETRY_CHANGED",
+  "GEOMETRY_TRANSFORMED",
+  "ENTITY_ID_CHANGED",
+  "ENTITY_NAME_CHANGED",
+  "ENTITY_COLOR_CHANGED",
+  "SUBDIVISION",
+  "ABSORPTION",
+  "SUBDIVISION_ABSORPTION",
+  "MERGE",
+  "COPY",
+  "CUT"
+};
+
+CGMHistory::CGMHistory()
+{
+  mTracking = false;
+  //mTracking = true;
+}
+
+CGMHistory::~CGMHistory()
+{
+}
+
+CGMHistory::Event::Event(CGMHistory::EventType type, RefEntity* refentity)
+{
+  eventType = type;
+  entities.push_back(refentity);
+}
+
+CGMHistory::Event::Event(CGMHistory::EventType type, const std::vector<RefEntity*>& refentity_list)
+{
+  eventType = type;
+  entities = refentity_list;
+}
+
+CGMHistory::Event::~Event()
+{
+}
+      
+CGMHistory::EventType CGMHistory::Event::get_event_type() const
+{
+  return eventType;
+}
+      
+const std::vector<RefEntity*>& CGMHistory::Event::get_entities() const
+{
+  return entities;
+}
+
+void CGMHistory::start_tracking()
+{
+  mTracking = true;
+}
+
+void CGMHistory::end_tracking()
+{
+  mTracking = false;
+}
+
+bool CGMHistory::is_tracking() const
+{
+  return mTracking;
+}
+
+int CGMHistory::get_number_of_events() const
+{
+  return eventList.size();
+}
+    
+const CGMHistory::Event* CGMHistory::get_event( int index ) const
+{
+  if(index < eventList.size())
+    return &eventList[index];
+  return NULL;
+}
+
+void CGMHistory::add_event( const CGMHistory::Event &event )
+{
+  if(mTracking)
+    eventList.push_back(event);
+}
+
+void CGMHistory::add_port_event( const CGMHistory::PortEvent &event )
+{
+  if(mTracking)
+    portEventList.push_back(event);
+}
+
+void CGMHistory::compress()
+{
+  // TODO
+}
+
+void CGMHistory::clear()
+{
+  eventList.clear();
+  portEventList.clear();
+}
+
+void CGMHistory::print_port_events() 
+{
+  
+  std::vector<PortEvent>::iterator iter = portEventList.begin();
+  for(; iter != portEventList.end(); iter++ )
+  {
+    PortEvent port_event = *iter;
+    PRINT_INFO("Event type = %s RefEntities ", event_names[ port_event.eventType ]);
+
+    int i;
+    for( i=0; i<port_event.RefEnts.size(); i++ )
+    {
+      RefEntity *ref_ent = port_event.RefEnts[i];
+      PRINT_INFO(" %s %d ", ref_ent->class_name(), ref_ent->id() );
+    }
+    PRINT_INFO(" ---> ");
+    for( i=0; i<port_event.TopologyBridges.size(); i++ )
+    {
+      TopologyBridge *tb = port_event.TopologyBridges[i];
+      PRINT_INFO(" %p", tb );
+    }
+    PRINT_INFO("\n"); 
+  }
+}
+
+CGMHistory::PortEvent::PortEvent(CGMHistory::EventType type )
+{
+  eventType = type;
+//  if( eventType != GEOMETRY_TRANSFORMED )
+//    TopologyBridges = new std::vector<TopologyBridge*>;
+//  else
+//    TopologyBridges = NULL;
+}
+
+CGMHistory::PortEvent::~PortEvent()
+{
+//  if( TopologyBridges )
+//    delete TopologyBridges;
+}
+
+CGMHistory::EventType CGMHistory::PortEvent::get_event_type() const
+{
+  return eventType;
+}
+

Added: cgm/branches/cubit/geom/CGMHistory.hpp
===================================================================
--- cgm/branches/cubit/geom/CGMHistory.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/CGMHistory.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,187 @@
+
+
+#ifndef CGMHistory_hpp
+#define CGMHistory_hpp
+
+#include <vector>
+#include "CubitTransformMatrix.hpp"
+#include "CubitGeomConfigure.h"
+class RefEntity;
+class TopologyBridge;
+
+class CUBIT_GEOM_EXPORT CGMHistory
+{
+  public:
+    CGMHistory();
+    ~CGMHistory();
+            
+    enum EventType
+    {
+      // Top level creation means an entity with no parent is created
+      // this could be bodies, surfaces, curves or vertices
+      TOP_LEVEL_ENTITY_CREATED,
+      
+      // Top level deleted means an entity no longer has top level status
+      // it may have been deleted or it may have been consumed into a higher
+      // dimensional entity
+      TOP_LEVEL_ENTITY_DELETED,
+      
+      // An entity has been created
+      ENTITY_CREATED,
+      
+      // An entity has been deleted
+      ENTITY_DELETED,
+      
+      // An entity's topology changes, meaning it has gained new child entities
+      // or lost old child entities.  This can result from solid modeling
+      // operations or from operations within cgm such as merging.
+      TOPOLOGY_CHANGED, 
+
+      // 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,
+
+      // A transformation happend to this entity, all child entities are
+      // transformed as well.  In this case, a GEOMETRY_CHANGED does not occur.
+      GEOMETRY_TRANSFORMED,
+
+      // The id of an entity changes
+      ENTITY_ID_CHANGED,
+      
+      // The name of an entity changes
+      ENTITY_NAME_CHANGED,
+      
+      // The name of an entity changes
+      ENTITY_COLOR_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,
+
+      // 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,
+
+      // An entity is merged into another
+      // this is a supplemental event such that other events completely
+      // describe the topology changes, but this event specifies where the
+      // merge occurred
+      MERGE,
+
+      // 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,
+      
+      // Cousin to SUBDIVISION.  Think of it as a 1-to-n subdivision where
+      // only 1 of the n actually survives, so it's really and 1-to-1
+      // modification.
+      CUT
+    };
+
+    //Event is a record of a change that occurred during an operation
+    class CUBIT_GEOM_EXPORT Event
+    {
+    public:
+      Event(EventType type, RefEntity* refentity);
+      Event(EventType type, const std::vector<RefEntity*>& refentity_list);
+      ~Event();
+
+      EventType get_event_type() const;
+      const std::vector<RefEntity*>& get_entities() const;
+
+    private:
+
+      // the type of event this is
+      EventType eventType;
+      // the entities this event applies to
+      std::vector<RefEntity*> entities;
+
+      // extra data associated with event
+      union 
+      {
+        std::vector<RefEntity*> *other_entities;
+        CubitTransformMatrix *matrix;
+        // TODO add data types for other events
+      };
+    };
+
+    
+    class CUBIT_GEOM_EXPORT PortEvent
+    {
+      public:
+        PortEvent(EventType type, std::vector<RefEntity*> &source_entities,
+                              std::vector<TopologyBridge*> &result_entities );
+        PortEvent( EventType type );
+        ~PortEvent();
+
+        EventType get_event_type() const;
+        const std::vector<RefEntity*>& get_entities() const;
+
+        EventType eventType;
+        // the entities this event applies to
+        std::vector<RefEntity*> RefEnts; 
+        std::vector<TopologyBridge*> TopologyBridges;
+
+        // extra data associated with event
+        //union 
+       // {
+        //  std::vector<TopologyBridge*> *TopologyBridges;
+        //  CubitTransformMatrix *matrix;
+          // TODO add data types for other events
+       // };
+    };
+
+
+
+    // get the number of events in this history
+    int get_number_of_events() const;
+    // get an event by index
+    const Event* get_event( int index ) const;
+
+    void print_port_events(); 
+
+    // add an event to this history
+    void add_event( const Event &new_event );
+    // compress the events in this history
+    // for example, if an event for volume 1 created and an event for volume 1
+    // deleted exists, both are removed
+
+    void add_port_event( const PortEvent &event );
+
+    void compress();
+    
+    // cleans out the history
+    void clear();
+
+    // start tracking events
+    void start_tracking();
+    // stop tracking events
+    void end_tracking();
+    // ask if tracking
+    bool is_tracking() const;
+
+  private:
+    // the list of events
+    std::vector<Event> eventList;
+    std::vector<PortEvent> portEventList;
+    bool mTracking;
+};
+
+#endif
+

Modified: cgm/branches/cubit/geom/CMakeLists.txt
===================================================================
--- cgm/branches/cubit/geom/CMakeLists.txt	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CMakeLists.txt	2010-01-06 19:22:14 UTC (rev 3423)
@@ -2,25 +2,52 @@
 
 PROJECT(cubit_geom)
 
+OPTION(CGM_FACET "Build CGM with Facet support" ON)
+IF(CGM_FACET)
+SUBDIRS(Cholla facetbool facet)
+ENDIF(CGM_FACET)
 
-SUBDIRS(Cholla facetbool facet virtual)
+OPTION(CGM_VIRTUAL "Build CGM with Virtual support" ON)
+IF(CGM_VIRTUAL)
+SUBDIRS(virtual)
+ENDIF(CGM_VIRTUAL)
 
-# build cgm with acis support, default to on
-OPTION(CGM_ACIS "Build CGM with ACIS support" ON)
+# build cgm with acis support, default to off
+OPTION(CGM_ACIS "Build CGM with ACIS support" OFF)
 IF(CGM_ACIS)
 SUBDIRS(ACIS)
 ENDIF(CGM_ACIS)
 
+
+OPTION(CGM_SMLIB "Build CGM with SMLIB support" OFF)
+IF(CGM_SMLIB)
+SUBDIRS(smlib)
+ENDIF(CGM_SMLIB)
+
+
 # build cgm with granite support, default to off
 OPTION(CGM_GRANITE "Build CGM with Granite support" OFF)
 IF(CGM_GRANITE)
   SUBDIRS(granite)
 ENDIF(CGM_GRANITE)
 
+OPTION(CGM_CATIA "Build CGM with CATIA support" OFF)
+IF(CGM_CATIA)
+  SET(CGM_ACIS OFF CACHE BOOL "ACIS not supported with CATIA" FORCE)
+  SET(FEATURE_OPTION OFF CACHE BOOL "Feature option not allowed with CATIA" FORCE)
+  SET(TOLERANT_TRI OFF CACHE BOOL "Geometry-tolerant meshing option not allowed with CATIA" FORCE)
+  SET(ACIS_IGES OFF CACHE BOOL "ACIS_IGES not allowed with CATIA" FORCE)
+  SET(ACIS_STEP OFF CACHE BOOL "ACIS_STEP not allowed with CATIA" FORCE)
+  SET(CUBIT_GEOM_BUILD_SHARED_LIBS ON CACHE BOOL "GEOM_LIBS need to be shared when CATIA is used" FORCE)
+  SET(CUBIT_UTIL_BUILD_SHARED_LIBS ON CACHE BOOL "UTIL_LIBS need to be shared when CATIA is used" FORCE)
+
+ENDIF(CGM_CATIA)
+
 INCLUDE(${cubit_geom_SOURCE_DIR}/../util/UseUtil.cmake)
 
 SET(GEOM_SRCS
     AnalyticGeometryTool.cpp
+    AutoMidsurfaceTool.cpp
     BasicTopologyEntity.cpp
     Body.cpp
     BodySM.cpp
@@ -38,6 +65,7 @@
     CAUniqueId.cpp
     CGMApp.cpp
     CGMEngineDynamicLoader.cpp
+    CGMHistory.cpp
     Chain.cpp
     CoEdge.cpp
     CoEdgeSM.cpp
@@ -58,9 +86,7 @@
     DagDrawingTool.cpp
     GeomDataObserver.cpp
     GeometryEntity.cpp
-    GeometryFeatureEngine.cpp
     GeometryFeatureTool.cpp
-    GeometryHealerEngine.cpp
     GeometryHealerTool.cpp
     GeometryModifyEngine.cpp
     GeometryModifyTool.cpp
@@ -68,6 +94,7 @@
     GeometryQueryTool.cpp
     GeometryUtil.cpp
     GeomMeasureTool.cpp
+    GfxPreview.cpp
     GroupingEntity.cpp
     GSaveOpen.cpp
     Loop.cpp
@@ -78,11 +105,11 @@
     MedialTool3D.cpp
     MergeToolAssistant.cpp
     MergeTool.cpp
-    MidPlaneTool.cpp
     ModelEntity.cpp
     ModelQueryEngine.cpp
     OffsetSplitTool.cpp
     OldUnmergeCode.cpp
+    PeriodicParamTool.cpp
     Point.cpp
     PointSM.cpp
     RefCollection.cpp
@@ -158,44 +185,27 @@
 
 IF(CUBIT_GEOM_BUILD_SHARED_LIBS)
   ADD_LIBRARY(cubit_geom SHARED ${GEOM_SRCS} ${EXTRA_GEOM_SRCS} ${GEOM_HEADERS} ${TEMPLATE_SRCS})
-
-  IF(CUBIT_COPY_DIR)
-    # The cubit copy dir should only be set on windows.
-    STRING(REGEX REPLACE "/" "\\\\" winbin "${CUBIT_COPY_DIR}")
-    IF(${CMAKE_GENERATOR} MATCHES "Visual Studio")
-      ADD_CUSTOM_COMMAND(TARGET cubit_geom POST_BUILD
-                         COMMAND ${CMAKE_COMMAND}
-                         ARGS -E copy
-                           $\(TargetPath\) ${winbin}\\$\(TargetName\).dll)
-    ELSE(${CMAKE_GENERATOR} MATCHES "Visual Studio")
-      STRING(REGEX REPLACE "/" "\\\\" winsrc "${LIBRARY_OUTPUT_PATH}")
-      ADD_CUSTOM_COMMAND(TARGET cubit_geom POST_BUILD
-                         COMMAND ${CMAKE_COMMAND}
-                         ARGS -E copy
-                           ${winsrc}\\cubit_geom.dll
-                           ${winlib}\\cubit_geom.dll)
-    ENDIF(${CMAKE_GENERATOR} MATCHES "Visual Studio")
-  ENDIF(CUBIT_COPY_DIR)
 ELSE(CUBIT_GEOM_BUILD_SHARED_LIBS)
   ADD_LIBRARY(cubit_geom ${GEOM_SRCS} ${EXTRA_GEOM_SRCS} ${GEOM_HEADERS} ${TEMPLATE_SRCS})
 ENDIF(CUBIT_GEOM_BUILD_SHARED_LIBS)
 
 TARGET_LINK_LIBRARIES(cubit_geom cubit_util)
 
-IF(UNIX)
-ADD_CUSTOM_TARGET(switch_acis 
-                  rm -f *Acis*.o &&
-                  rm -f attrib*.o &&
-                  rm -f *ACIS*.o &&
-                  rm -f GeometryCommands.o &&
-                  rm -f Feature*.o &&
-                  rm -f *App.o &&
-                  cd ACIS && ${CMAKE_MAKE_PROGRAM} switch_acis)
+IF(CUBIT_LIBRARY_PROPERTIES)
+  SET_TARGET_PROPERTIES(cubit_geom
+                        PROPERTIES ${CUBIT_LIBRARY_PROPERTIES})
+ENDIF(CUBIT_LIBRARY_PROPERTIES)
 
-ENDIF(UNIX)
+SET(CMAKE_INSTALL_BINARY_DIR "bin" CACHE PATH "Install directory for binaries")
 
-SET(CMAKE_INSTALL_BINARY_DIR "bin" CACHE PATH "Install directory for binaries")
 IF(CUBIT_GEOM_BUILD_SHARED_LIBS)
-  INSTALL_TARGETS(/${CMAKE_INSTALL_BINARY_DIR} cubit_geom)
+  INSTALL(TARGETS cubit_geom
+          RUNTIME DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+          LIBRARY DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+          )
 ENDIF(CUBIT_GEOM_BUILD_SHARED_LIBS)
 
+IF(BUILD_TESTING)
+  #ADD_SUBDIRECTORY(testing)
+ENDIF(BUILD_TESTING)
+

Modified: cgm/branches/cubit/geom/Cholla/CMakeLists.txt
===================================================================
--- cgm/branches/cubit/geom/Cholla/CMakeLists.txt	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CMakeLists.txt	2010-01-06 19:22:14 UTC (rev 3423)
@@ -8,6 +8,7 @@
     ChollaPoint.cpp
     ChollaSkinTool.cpp
     ChollaSurface.cpp
+    ChollaVolume.cpp
     ChordalAxis.cpp
     CubitFacet.cpp
     CubitFacetData.cpp
@@ -42,6 +43,7 @@
 IF(TEMPLATE_DEFS_INCLUDED)
 SET(TEMPLATE_SRCS
     FacetorTool.cpp
+    FacetorUtil.cpp
     TetFacetorTool.cpp
     TDDelaunay.cpp
     )

Modified: cgm/branches/cubit/geom/Cholla/Cholla.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/Cholla.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/Cholla.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1755,7 +1755,7 @@
 static void time_stamp( FILE *fp )
 {
   struct tm *newtime;
-  char am_pm[] = "AM";
+  char* am_pm = "AM";
   time_t long_time;
 
   time( &long_time );                /* Get time as long integer. */

Modified: cgm/branches/cubit/geom/Cholla/ChollaCurve.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaCurve.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaCurve.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -8,6 +8,7 @@
 #include "CubitVector.hpp"
 #include "ChollaCurve.hpp"
 #include "ChollaSurface.hpp"
+#include "ChollaPoint.hpp"
 #include "TDGeomFacet.hpp"
 #include "CastTo.hpp"
 #include "CubitFacet.hpp"
@@ -16,6 +17,8 @@
 #include "CubitFacetEdgeData.hpp"
 #include "debug.hpp"
 #include "GfxDebug.hpp"
+#include "CurveFacetEvalTool.hpp"
+#include "ChollaEngine.hpp"
 
 //===============================================================================
 //Function:  ChollaCurve (PUBLIC) (constructor)
@@ -29,7 +32,9 @@
   startPoint = NULL;
   endPoint = NULL;
   blockID = block_id;
+  myLength = MYLENGTH_UNINITIALIZED;
 }
+
 //===============================================================================
 //Function:  ~ChollaCurve (PUBLIC) (destructor)
 //===============================================================================
@@ -128,7 +133,6 @@
   int periodic = 0;
   int start_size = curveEdgeList.size();
   int icount = 0;
-  int mydebug = 0;
 
   curveEdgeList.reset();
   while( curveEdgeList.size() > 0)
@@ -160,92 +164,28 @@
       int block_id = (td_gm_edge == NULL) ? -1 : td_gm_edge->get_block_id();
       ChollaCurve *fcm_ptr = new ChollaCurve( block_id );
       new_curve_list.append( fcm_ptr );
-      fcm_ptr->set_start( start_point );
-      start_point->set_as_feature();
-
-      fcm_ptr->add_facet( start_edge_ptr );
-      curveEdgeList.remove( start_edge_ptr );
-      int iedgecount = 0;
-      CubitFacetEdge *edge_ptr = start_edge_ptr;
-      point0_ptr = start_point;
-      CubitPoint *end_point = NULL;
-      while(!end_point)
-      {
-        point1_ptr = edge_ptr->other_point( point0_ptr );
-        if ((edge_ptr = next_edge( point1_ptr, edge_ptr )) == NULL)
-        {
-          end_point = point1_ptr;
-        }
-        else
-        {
-          iedgecount++;
-          if (iedgecount > start_size)
-          {
-            PRINT_ERROR("ChollaCurve has start, but no end\n");
-            return CUBIT_FAILURE;
-          }
-
-          fcm_ptr->add_facet( edge_ptr );
-          curveEdgeList.remove( edge_ptr );
-          if (periodic && point1_ptr == start_point)
-            end_point = start_point;
-          point0_ptr = point1_ptr;
-        }
-      }
-      fcm_ptr->set_end( end_point );
-      end_point->set_as_feature();
-      start_size = curveEdgeList.size();
-      icount = 0;
-      periodic = 0;
-
-      // make sure all the edges are oriented correctly
-
-      int i;
+      
+      // assign the edges to the new curve in the correct order and orientation
+      
+      CubitStatus rv = fcm_ptr->build_curve_from_edges( start_point,  periodic, start_size, start_edge_ptr, this );
+      if (rv != CUBIT_SUCCESS)
+        return rv;
+      
+      // remove the edges in the new curve from this curve
+      
+      int ii;
       DLIList<FacetEntity *> flist = fcm_ptr->get_facet_list();
-      flist.reset();
       DLIList<CubitFacetEdge *> elist;
+      CubitFacetEdge *edge_ptr;
       CAST_LIST( flist, elist, CubitFacetEdge );
-      elist.reset();
-      CubitPoint *cur_pt = start_point, *tmp_pt;
-      for ( i = elist.size(); i > 0; i-- ) 
+      for ( ii = elist.size(); ii > 0; ii-- ) 
       {
         edge_ptr = elist.get_and_step();
-        point0_ptr = edge_ptr->point(0);
-        point1_ptr = edge_ptr->point(1);
-        if (point0_ptr != cur_pt)
-        {
-          assert( cur_pt == point1_ptr );
-          edge_ptr->flip();
-          tmp_pt = point0_ptr;
-          point0_ptr = point1_ptr;
-          point1_ptr = tmp_pt;
-          assert( point0_ptr == edge_ptr->point(0) &&
-                  point1_ptr == edge_ptr->point(1) );
-        }
-        cur_pt = point1_ptr;
+        curveEdgeList.remove( edge_ptr );
       }
-
-      if (mydebug)
-      {
-        int i;
-        DLIList<FacetEntity *> flist = fcm_ptr->get_facet_list();
-        flist.reset();
-        DLIList<CubitFacetEdge *> elist;
-        CAST_LIST( flist, elist, CubitFacetEdge );
-        elist.reset();
-        for ( i = elist.size(); i > 0; i-- ) {  
-          CubitFacetEdge *edge = elist.get_and_step();
-          CubitVector pt0_v = edge->point(0)->coordinates();
-          CubitVector pt1_v = edge->point(1)->coordinates();
-          GfxDebug::draw_point(pt0_v, CUBIT_GREEN );
-          GfxDebug::draw_point(pt1_v, CUBIT_RED );
-          GfxDebug::draw_line( pt0_v, pt1_v, CUBIT_YELLOW );
-          GfxDebug::flush();
-          int view = 0;
-          if (view)
-            dview();
-        }
-      }
+      start_size = curveEdgeList.size();
+      icount = 0;
+      periodic = 0;
     }
 
     // if we have gone through all of the edges without finding an end,
@@ -305,8 +245,218 @@
   return CUBIT_SUCCESS;
 }
 
+//=============================================================================
+//Function: build_curve_from_edges 
+//Description: insert the ordered and oriented edges into this cholla curve
+//Notes:  traverses starting at start_point and gathers facet edges until it 
+//        runs into another curve.
+//        start_point is an existing CubitPoint at either end of the curve
+//        max_edges is the maximum number of edges on this curve.  should be 
+//        known beforehand (used for error checking).
+//
+// ***this function used to be part of split_curve. ***
+//Author: sjowen
+//Return: 
+//Date: 09/07/2009
+//=============================================================================
+CubitStatus ChollaCurve::build_curve_from_edges( CubitPoint *start_point,
+                                                int periodic,
+                                                int max_edges,
+                                                CubitFacetEdge *start_edge_ptr,
+                                                ChollaCurve *parent_curve )
+{
+  
+  // find the first edge.  Match the chollacurve owner with this curve
+  // do this only if the start_edge_ptr was not passed in
+  
+  DLIList<CubitFacetEdge *> point_edge_list;
+  start_point->edges(point_edge_list);
+  CubitFacetEdge *edge_ptr;
+  if (start_edge_ptr == NULL)
+  {
+    for (int ii=0; ii<point_edge_list.size() && !start_edge_ptr; ii++)
+    {
+      edge_ptr = point_edge_list.get_and_step();
+      TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( edge_ptr );
+      
+      // assumes that the TDGeomFacet info has already been set up for the edges
+      assert(td_geom != NULL);
+      
+      DLIList<ChollaCurve *> cholla_curves;
+      td_geom->get_cholla_curves(cholla_curves);
+      
+      // currently should be only one-to-one relationship
+      // could also be edge on surface in which case no curves associated
+      assert(cholla_curves.size() <= 1);
+      if (cholla_curves.size())
+      {
+        if (cholla_curves.get() == this)
+          start_edge_ptr = edge_ptr;
+      }
+    }
+    assert(start_edge_ptr != NULL);  // didn't find an edge that marched this chollacurve
+  }
+  
+  // create a new curve to hold the edge info
+  
+  this->set_start( start_point );
+  start_point->set_as_feature();
+  
+  this->add_facet( start_edge_ptr );
+  int iedgecount = 0;
+  edge_ptr = start_edge_ptr;
+  CubitPoint *point0_ptr = start_point, *point1_ptr;
+  CubitPoint *end_point = NULL;
+  while(!end_point)
+  {
+    point1_ptr = edge_ptr->other_point( point0_ptr );
+    if ((edge_ptr = parent_curve->next_edge( point1_ptr, edge_ptr )) == NULL)
+    {
+      end_point = point1_ptr;
+    }
+    else
+    {
+      iedgecount++;
+      if (iedgecount > max_edges)
+      {
+        PRINT_ERROR("ChollaCurve has start, but no end\n");
+        return CUBIT_FAILURE;
+      }
+      
+      this->add_facet( edge_ptr );
+      if (periodic && point1_ptr == start_point)
+        end_point = start_point;
+      point0_ptr = point1_ptr;
+    }
+  }
+  this->set_end( end_point );
+  end_point->set_as_feature();
+  
+  // make sure all the edges are oriented correctly
+  
+  int i;
+  DLIList<FacetEntity *> flist = this->get_facet_list();
+  flist.reset();
+  DLIList<CubitFacetEdge *> elist;
+  CAST_LIST( flist, elist, CubitFacetEdge );
+  elist.reset();
+  CubitPoint *cur_pt = start_point, *tmp_pt;
+  for ( i = elist.size(); i > 0; i-- ) 
+  {
+    edge_ptr = elist.get_and_step();
+    point0_ptr = edge_ptr->point(0);
+    point1_ptr = edge_ptr->point(1);
+    if (point0_ptr != cur_pt)
+    {
+      assert( cur_pt == point1_ptr );
+      edge_ptr->flip();
+      tmp_pt = point0_ptr;
+      point0_ptr = point1_ptr;
+      point1_ptr = tmp_pt;
+      assert( point0_ptr == edge_ptr->point(0) &&
+             point1_ptr == edge_ptr->point(1) );
+    }
+    cur_pt = point1_ptr;
+  }
+  
+  int mydebug = 0;
+  if (mydebug)
+  {
+    int i;
+    DLIList<FacetEntity *> flist = this->get_facet_list();
+    flist.reset();
+    DLIList<CubitFacetEdge *> elist;
+    CAST_LIST( flist, elist, CubitFacetEdge );
+    elist.reset();
+    for ( i = elist.size(); i > 0; i-- ) {  
+      CubitFacetEdge *edge = elist.get_and_step();
+      CubitVector pt0_v = edge->point(0)->coordinates();
+      CubitVector pt1_v = edge->point(1)->coordinates();
+      GfxDebug::draw_point(pt0_v, CUBIT_GREEN );
+      GfxDebug::draw_point(pt1_v, CUBIT_RED );
+      GfxDebug::draw_line( pt0_v, pt1_v, CUBIT_YELLOW );
+      GfxDebug::flush();
+      int view = 0;
+      if (view)
+        dview();
+    }
+  }
+  return CUBIT_SUCCESS;
+}
 
 //=============================================================================
+//Function: length
+//Description: 
+//Author: sjowen
+//Date: 04/21/2009
+//============================================================================
+double ChollaCurve::length()
+{
+  if (myLength > MYLENGTH_UNINITIALIZED)
+    return myLength;
+  
+  CubitFacetEdge *edge;
+  FacetEntity *fent;
+  myLength = 0.0;
+  for (int iedge=0; iedge<curveEdgeList.size(); iedge++)
+  {
+    fent = curveEdgeList.get_and_step();
+    edge = dynamic_cast<CubitFacetEdge *> (fent);
+    myLength += edge->length();
+  }
+  
+  return myLength;
+}
+
+//=============================================================================
+//Function: find adjacent edges at a point that lie on the curve 
+//Description: determine the next edge from a given edge - return NULL if at the end
+//Author: william roshan quadros
+//Return: returns false if no adj_edges can be found
+//Date: 04/21/2009
+//=============================================================================
+bool ChollaCurve::adj_facet_edges( CubitPoint *node_ptr, CubitFacetEdge *&adj_edge1, CubitFacetEdge *&adj_edge2 )
+{
+  // initialize adj_edge1 and adj_edge2
+  adj_edge1 = adj_edge2 = NULL;
+
+  DLIList<CubitFacetEdge*> edge_list;
+  node_ptr->edges( edge_list );
+  int jj, kk;
+  for (jj=0; jj<edge_list.size(); jj++)
+  {
+    CubitFacetEdge *node_edge_ptr = edge_list.get_and_step();
+    TDGeomFacet *td_gm_edge = TDGeomFacet::get_geom_facet(node_edge_ptr);
+    if (td_gm_edge != NULL)
+    {
+      DLIList<ChollaCurve*> fcurve_list;
+      td_gm_edge->get_cholla_curves( fcurve_list );
+      if (fcurve_list.size() > 0)
+      { // match the curve to the edge to find the next edge
+        for (kk=0; kk<fcurve_list.size(); kk++)
+        {
+          ChollaCurve *fcm_ptr = fcurve_list.get_and_step();
+          if (fcm_ptr == this)
+          {
+            if( NULL == adj_edge1 )
+              adj_edge1 = node_edge_ptr;
+            else 
+              if( NULL == adj_edge2 )
+                adj_edge2 = node_edge_ptr;
+              else
+                assert( false ); // More than two adj_edges can't be incident on a curve
+          }
+        }
+      }
+    }    
+  }
+  if( NULL == adj_edge1 )
+    return false;
+  else
+    return true;
+}
+
+//=============================================================================
 //Function:  next_edge (PRIVATE)
 //Description: determine the next edge from a given edge - return NULL if at
 //             the end
@@ -591,5 +741,247 @@
   fclose(fp);
 }
 
+
+  //  disassociate from cholla points
+CubitStatus ChollaCurve::disassociate_from_points( void )
+{  
+
+  /*
+  if( startPoint )
+  {
+    startPoint->remove_curve( this );
+    startPoint = NULL;
+  }
+  if( endPoint )
+  {
+    endPoint->remove_curve( this );
+    endPoint = NULL;
+  }
+  */
+
+  int i; 
+  for( i = 0; i < pointList.size(); i++ )
+  {
+    pointList.get_and_step()->remove_curve( this );
+  }
+  pointList.clean_out();
+
+  return CUBIT_SUCCESS;
+}
+  
+  // disassociate from cholla surface
+CubitStatus ChollaCurve::disassociate_from_surfaces( void)
+{
+  int i;
+  for( i = 0; i < surfaceList.size(); i++ )
+  {
+    surfaceList.get_and_step()->remove_curve( this );
+  }
+  surfaceList.clean_out();
+  return CUBIT_SUCCESS;
+}
+
+
+CubitStatus ChollaCurve::replace_facet( FacetEntity *remove_edge, FacetEntity *replace_edge )
+{
+  curveEdgeList.move_to( remove_edge );
+  curveEdgeList.insert( replace_edge );
+  curveEdgeList.remove( remove_edge );
+  myLength = MYLENGTH_UNINITIALIZED;
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus ChollaCurve::build_curve_facet_eval_tool( void )
+{ 
+  //debug this function as point list is not valid
+
+  if( this->get_eval_tool() )
+  {
+    assert(false); //WARNING: Curve facet eval tool already exist!
+  }
+
+  CurveFacetEvalTool *curv_eval_tool_ptr = new CurveFacetEvalTool();
+
+  // Step 1: Initialize facet_edge_list and point_list
+  CubitStatus stat;
+  DLIList<CubitPoint *> point_list;
+  int i;
+  // insert start point of every facet_edge
+  curveEdgeList.reset();
+  for( i = 0; i < curveEdgeList.size(); i++ )
+  {
+    point_list.append( CAST_TO( curveEdgeList.get_and_step(), CubitFacetEdge )->point(0) );
+  }
+  // insert end point of last facet_edge
+  curveEdgeList.step( curveEdgeList.size() - 1 );
+  point_list.append( CAST_TO( curveEdgeList.get(), CubitFacetEdge )->point(1) );
+
+  DLIList<CubitFacetEdge *> edge_list;
+  CAST_LIST( curveEdgeList, edge_list, CubitFacetEdge );
+  stat = curv_eval_tool_ptr->initialize( edge_list, point_list );
+  if( stat != CUBIT_SUCCESS )
+  {
+    return stat;
+  }
+  
+ /*
+ // Step 2: find sense of curve_facet_eval_tool  /// this is done internally in next Step in initialize()
+  if( this->startPoint )
+  {
+    stat = curv_eval_tool_ptr->find_curv_sense( this->startPoint );
+    if( stat != CUBIT_SUCCESS )
+    {
+      return stat;
+    }  
+  }
+*/
+  // Step 2: Initialize adj_surface_facet_eval_tool with orientation_wrt_surface
+  if( surfaceList.size() )
+  {
+    CubitSense orientation_wrt_surface;
+    if( CUBIT_SUCCESS == ChollaEngine::determine_curve_orientation( surfaceList.get(), this, orientation_wrt_surface ) )
+    {
+      if( this->startPoint && this->endPoint )
+      {
+        stat = curv_eval_tool_ptr->initialize( surfaceList.get()->get_eval_tool(),
+                      this->startPoint,
+                      this->endPoint,
+                      orientation_wrt_surface);
+      }
+    }
+    else
+    {
+      assert(false);
+    }
+
+    if( stat != CUBIT_SUCCESS )
+    {
+      assert( false );
+      return stat;
+    }      
+  }
+  else
+  {
+    assert(false); //WARNING: No adjacent cholla surface available
+  }
+
+  // Step 4: assign the new curv_eval_tool to cholla_curve
+ assign_eval_tool( curv_eval_tool_ptr );
+
+  return stat;
+}
+
+//=============================================================================
+//Function:  is_in_volume (PUBLIC)
+//Description:  return whether this curve is contained within the specified volume
+//Author: sjowen
+//Date: 9/11/2009
+//=============================================================================
+CubitBoolean ChollaCurve::is_in_volume( ChollaVolume *chvol_ptr )
+{
+  for (int ii=0; ii<surfaceList.size(); ii++)
+  {
+    ChollaSurface *chsurf_ptr = surfaceList.get_and_step();
+    DLIList<ChollaVolume *> chvol_list;
+    chsurf_ptr->get_volumes(chvol_list);
+    for (int jj=0; jj<chvol_list.size(); jj++)
+    {
+      ChollaVolume *mychvol_ptr = chvol_list.get_and_step();
+      if (mychvol_ptr == chvol_ptr)
+        return CUBIT_TRUE;
+    }
+  }
+  return CUBIT_FALSE;
+}
+
+//=============================================================================
+//Function:  is_in_surface (PUBLIC)
+//Description:  return whether this curve is contained within the specified surface
+//Author: sjowen
+//Date: 9/18/2009
+//=============================================================================
+CubitBoolean ChollaCurve::is_in_surface( ChollaSurface *chsurf_ptr )
+{
+  for (int ii=0; ii<surfaceList.size(); ii++)
+  {
+    ChollaSurface *mysurf_ptr = surfaceList.get_and_step();
+    if (mysurf_ptr == chsurf_ptr)
+    {
+      return CUBIT_TRUE;
+    }
+  }
+  return CUBIT_FALSE;
+}
+
+
+//=============================================================================
+//Function:  get_facet_points (PUBLIC)
+//Description:  return the list of facet points on this chollacurve
+//Notes: inclusive = true will return end points as well, otherwise only
+//       interior points will be returned
+//Author: sjowen
+//Date: 9/11/2009
+//=============================================================================
+void ChollaCurve::get_facet_points( DLIList<CubitPoint *> &point_list, CubitBoolean inclusive)
+{
+  FacetEntity *fe_ptr;
+  CubitFacetEdge *edge_ptr;
+  CubitPoint *pts[2];
+  for (int ii=0; ii<curveEdgeList.size(); ii++)
+  {
+    fe_ptr = curveEdgeList.get_and_step();
+    edge_ptr = dynamic_cast<CubitFacetEdge *> (fe_ptr);
+    assert(edge_ptr != NULL);
+    for (int jj=0; jj<2; jj++)
+    {
+      pts[jj] = edge_ptr->point(jj);
+      if (inclusive)
+      {
+        point_list.append(pts[jj]);
+      }
+      else
+      {
+        if (pts[jj] != startPoint && pts[jj] != endPoint)
+        {
+          point_list.append(pts[jj]);
+        }
+      }
+    }
+  }
+  point_list.uniquify_ordered();
+}
+
+//=============================================================================
+//Function:  has_point (PUBLIC)
+//Description:  return whether the curve contains the gicen point
+//Notes: 
+//=============================================================================
+CubitBoolean ChollaCurve::has_point( ChollaPoint *chpt )
+{
+  for(int ii=0; ii<pointList.size(); ii++)
+  {
+    ChollaPoint *pt = pointList.get_and_step();
+    if (pt == chpt)
+      return CUBIT_TRUE;
+  }
+  return CUBIT_FALSE;
+}
+
+//=============================================================================
+//Function:  verify_points (PUBLIC)
+//Description:  verify that all points on this curve have this curve as an adjacency
+//Notes: 
+//=============================================================================
+CubitStatus ChollaCurve::verify_points()
+{
+  for(int ii=0; ii<pointList.size(); ii++)
+  {
+    ChollaPoint *pt = pointList.get_and_step();
+    if (!pt->is_in_curve(this))
+      return CUBIT_FAILURE;
+  }
+  return CUBIT_SUCCESS;
+}
+
 //EOF
 

Modified: cgm/branches/cubit/geom/Cholla/ChollaCurve.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaCurve.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaCurve.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -10,6 +10,8 @@
 #ifndef ChollaCurve_HPP
 #define ChollaCurve_HPP
 
+#define MYLENGTH_UNINITIALIZED -1.0
+
 #include "DLIList.hpp"
 #include "ChollaEntity.hpp"
 
@@ -18,6 +20,7 @@
 class CubitPoint;
 class ChollaPoint;
 class ChollaSurface;
+class ChollaVolume;
 class FacetEntity;
 class CurveFacetEvalTool;
 
@@ -35,15 +38,18 @@
   int flag;
   int blockID;
   int id;
+  double myLength;
 
   CubitStatus determine_ends();
     //- determine the end nodes for the curve (once the curvEdgeList is full)
 
   CubitFacetEdge *next_edge( CubitPoint *node_ptr, CubitFacetEdge *edge_ptr );
     //- return the next edge on the curve (NULL if at end)
-
+  
+  
 public:
 
+
   ChollaCurve( int block_id );
     //- default constructor
 
@@ -57,23 +63,43 @@
     // delete the asociativity of this curve with all edge's tool datas
 
   void add_facet(FacetEntity *exterior_edge)
-    {curveEdgeList.append(exterior_edge);}
+    {myLength = MYLENGTH_UNINITIALIZED;
+    curveEdgeList.append(exterior_edge);}
     //- add an edge to the curve
 
   int add_facet_unique(FacetEntity *exterior_edge)
-    {return curveEdgeList.append_unique(exterior_edge);}
+  {myLength = MYLENGTH_UNINITIALIZED;
+  return curveEdgeList.append_unique(exterior_edge);}
     //- add an edge to this curve - check to see if it already there before adding
 
+  void remove_facet( FacetEntity *facet_edge )
+  {myLength = MYLENGTH_UNINITIALIZED;
+  curveEdgeList.remove( facet_edge ); }
+    //- remove a facet_edge from underlying backing
+
+  CubitStatus replace_facet( FacetEntity *remove_edge, FacetEntity *replace_edge );
+    //- replace a facet_edge from underlying backing
+
   DLIList<FacetEntity*> &get_facet_list()
     {return curveEdgeList;}
     //- get the list of edges that make up this curve
   DLIList<FacetEntity*> *get_facet_list_ptr()
     {return &curveEdgeList;}
+  
+  //- return the length of the curve
+  double length();
+  
+  int num_edges() {return curveEdgeList.size();}
+    //- return the number of edges in the curve
 
   void add_surface( ChollaSurface *fsm_ptr )
     {surfaceList.append_unique( fsm_ptr );}
     //- associate a surface with this curve
 
+  inline void remove_surface( ChollaSurface *fsm_ptr)
+    {surfaceList.remove(fsm_ptr);}
+    //- remove a suface from the curve
+
   DLIList<ChollaSurface*> &get_surfaces()
     {return surfaceList;}
   void get_surfaces( DLIList<ChollaSurface *> &surf_list )
@@ -86,10 +112,23 @@
   void add_point( ChollaPoint *fpm_ptr )
     {pointList.append_unique( fpm_ptr );}
     //- associate a point with this curve
+   
+  inline void remove_point( ChollaPoint *fpm_ptr)
+    {pointList.remove(fpm_ptr);}
+    //- remove a point from the curve
 
   DLIList<ChollaPoint*> &get_points()
     {return pointList;}
     //- get the list of points attached to this curve
+  
+  void get_facet_points( DLIList<CubitPoint *> &point_list, CubitBoolean inclusive);
+    //- return the facet points on this chollacurve
+  
+  CubitBoolean is_in_volume( ChollaVolume *chvol_ptr );
+    //- return whether this curve is contained within the specified volume
+  
+  CubitBoolean is_in_surface( ChollaSurface *chsurf_ptr );
+    //- return whether this surface is contained within the specified surface
 
   void assign_geometric_curve(void *curv)
     {myCurve = curv;}
@@ -125,17 +164,44 @@
     //- split this curve into multiple ChollaCurve where there are
     //- discontinuous strings of edges.  Define start end end points
     //- for each curve while we are at it.
+  
+  CubitStatus build_curve_from_edges(CubitPoint *start_point,
+                                     int periodic, int max_edges,
+                                     CubitFacetEdge *start_edge_ptr,
+                                     ChollaCurve *parent_curve);
 
   CubitStatus feature_angle( double min_dot );
     //- compute angles at nodes on the curve to see if we need to split
     //- the curve.  Mark the node tooldata hitflag if the node will
     //- break the curve (this is refernced in next_edge) 
 
+  //  disassociate from cholla points
+  CubitStatus disassociate_from_points( void );
+  
+  // disassociate from cholla surface
+  CubitStatus disassociate_from_surfaces( void);
+
+  // build a new curve_facet_eval_tool and assign it to ChollaCurve
+  CubitStatus build_curve_facet_eval_tool( void );
+
   int get_flag( ) { return flag; }
   void set_flag( int flg ) { flag = flg; }
   int get_id() {return id;}
   void debug_draw();
   void print();
+
+  // find adjacent edges at a point that lie on the curve
+  bool adj_facet_edges( CubitPoint *cubit_pnt, CubitFacetEdge *&adj_edge1, CubitFacetEdge *&adj_edge2 );
+  
+  // return whether the curve contains the point
+  CubitBoolean has_point( ChollaPoint *pt );
+  
+  // verify that all points on this curve have this curve as an adjacency
+  CubitStatus verify_points();
+  
+  // clear the edge list
+  void clean_out_edges(){curveEdgeList.clean_out();};
+
 };
 
 #endif

Modified: cgm/branches/cubit/geom/Cholla/ChollaEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -3,12 +3,17 @@
 //- Owner:       Steven J. Owen
 //- Checked by:
 //- Version:
+//#include <list>
+#include <set>
+#include <map>
+#include <vector>
 #include "CubitDefines.h"
 #include "ChollaEngine.hpp"
 #include "DLIList.hpp"
 #include "TDGeomFacet.hpp"
 #include "CastTo.hpp"
 #include "ChollaSkinTool.hpp"
+#include "ChollaVolume.hpp"
 #include "ChollaSurface.hpp"
 #include "ChollaCurve.hpp"
 #include "ChollaPoint.hpp"
@@ -20,6 +25,7 @@
 #include "CubitPointData.hpp"
 #include "FacetEntity.hpp"
 #include "FacetEvalTool.hpp"
+#include "FacetDataUtil.hpp"
 #include "debug.hpp"
 #include "TDFacetBoundaryEdge.hpp"
 #include "TDFacetBoundaryPoint.hpp"
@@ -77,6 +83,50 @@
 }
 
 //============================================================================
+//Function:  ChollaEngine (PUBLIC) (constructor)
+//Notes: This case is used only when the cholla entities have been generated 
+//       directly rather than using create_geometry
+//       Does not use the TDGeomFacet Tooldatas
+//============================================================================
+ChollaEngine::ChollaEngine(DLIList<CubitFacet*>     &facet_list,
+                           DLIList<CubitFacetEdge*> &edge_list,
+                           DLIList<CubitPoint*>     &point_list,
+                           DLIList<ChollaVolume *>  &cholla_volumes,
+                           DLIList<ChollaSurface *> &cholla_surfaces,
+                           DLIList<ChollaCurve *>   &cholla_curves,
+                           DLIList<ChollaPoint *>   &cholla_points )
+{
+  CAST_LIST(facet_list, faceList, FacetEntity);
+  CAST_LIST(edge_list, edgeList, FacetEntity);
+  CAST_LIST(point_list, pointList, FacetEntity);
+  //set_up_tool_datas();  TDGeomFacet tooldatas should have already been added
+
+  hashCurveArray = NULL;
+  hashCurveSize = 0;
+  hashPointArray = NULL;
+  hashPointSize = 0;
+  doFlip = CUBIT_FALSE;
+  
+  chollaVolumeList = cholla_volumes;
+  chollaSurfaceList = cholla_surfaces;
+  chollaCurveList = cholla_curves;
+  chollaPointList = cholla_points;
+  
+  CubitBoolean use_feature_angle = CUBIT_FALSE; 
+  double min_dot = 0.0;                    
+  int interp_order = 0;                 
+  CubitBoolean smooth_non_manifold = CUBIT_FALSE;
+  CubitBoolean split_surfaces = CUBIT_FALSE;
+
+  build_eval_tools(chollaSurfaceList,
+                   chollaCurveList,
+                   interp_order, use_feature_angle, 
+                   min_dot, smooth_non_manifold,
+                   split_surfaces );
+}
+                          
+
+//============================================================================
 //Function:  set_up_tool_datas
 //============================================================================
 void ChollaEngine::set_up_tool_datas( )
@@ -368,7 +418,10 @@
     }
     // make a list of feature edges
 
- 
+    rv = chsurf_ptr->add_preexisting_feature_edges( feature_edge_list );
+		if (rv != CUBIT_SUCCESS)
+			return rv;
+		
     if (use_feature_angle)
     {
       rv = chsurf_ptr->feature_angle( min_dot, feature_edge_list );
@@ -984,7 +1037,7 @@
   CubitStatus stat = CUBIT_SUCCESS;
 
   if (stat == CUBIT_SUCCESS)
-    stat = build_surface_eval_tools( cholla_surface_list,
+    stat = build_surface_and_curve_eval_tools( cholla_surface_list,
                                    interp_order, min_dot );  
   if (stat == CUBIT_SUCCESS)
     stat = build_curve_eval_tools( cholla_curve_list, interp_order );
@@ -1051,10 +1104,11 @@
 //Function:  build_surface_eval_tools (PRIVATE)
 //Description:  From the facet surface list, create the FacetEvalTools
 //===============================================================================
-CubitStatus ChollaEngine::build_surface_eval_tools(
+CubitStatus ChollaEngine::build_surface_and_curve_eval_tools(
   DLIList<ChollaSurface*> &cholla_surface_list,
   int interp_order,
-  double min_dot )
+  double min_dot,
+  bool new_curv_tool)
 {
   CubitStatus stat = CUBIT_SUCCESS;
   int ii, kk;
@@ -1069,6 +1123,7 @@
 
   // now loop through surfaces and create them
 
+  int mydebug = 0;
   for ( kk = cholla_surface_list.size(); kk > 0; kk-- )
   {
     ChollaSurface *chsurf_ptr = cholla_surface_list.get_and_step();
@@ -1090,7 +1145,7 @@
     for (ii=0; ii<chcurv_list.size(); ii++)
     {
       ChollaCurve *chcurv_ptr = chcurv_list.get_and_step();
-      if (chcurv_ptr->get_eval_tool() == NULL)
+      if (chcurv_ptr->get_eval_tool() == NULL || new_curv_tool)
       {
         CubitSense orientation_wrt_surface;
         determine_curve_orientation( chsurf_ptr, chcurv_ptr, orientation_wrt_surface );
@@ -1123,6 +1178,7 @@
   // orientation of the curve with respect to the surface
 
   DLIList<FacetEntity*> facet_list = chcurv_ptr->get_facet_list();
+  facet_list.reset();
   FacetEntity *facet_ptr = facet_list.get();
   CubitFacetEdge *edge_ptr = CAST_TO( facet_ptr, CubitFacetEdge );
   if (!edge_ptr)
@@ -1136,14 +1192,20 @@
   int found = 0;int jj;
   for ( jj = 0; jj < adj_face_list.size() && !found; jj++ )
   {
-    face_ptr = adj_face_list.get_and_step();
+    face_ptr = adj_face_list.get_and_step();    
     TDGeomFacet *td_gm_face = TDGeomFacet::get_geom_facet(face_ptr); 
     DLIList<ChollaSurface*> chsurf_list;
-    td_gm_face->get_cholla_surfs( chsurf_list );
-    ChollaSurface *face_chsurf_ptr = chsurf_list.get();
-    if(face_chsurf_ptr == chsurf_ptr)
+    if(td_gm_face)
     {
-      found = 1;
+      td_gm_face->get_cholla_surfs( chsurf_list );
+      if (chsurf_list.size())
+      {
+        ChollaSurface *face_chsurf_ptr = chsurf_list.get();
+        if(face_chsurf_ptr == chsurf_ptr)
+        {
+          found = 1;
+        }
+      }
     }
   }
   if (!found)
@@ -1154,8 +1216,10 @@
   CubitPoint *start_ptr, *end_ptr;
   chcurv_ptr->get_ends( start_ptr, end_ptr );
   end_ptr = edge_ptr->other_point( start_ptr );
-  if (end_ptr == NULL)
+  if (end_ptr == NULL)    
+  {
     return CUBIT_FAILURE;  // the edge list may not be ordered correctly??
+  }
   CubitPoint *points[3];
   CubitFacet *tri_ptr = CAST_TO( face_ptr, CubitFacet );
   tri_ptr->points( points[0], points[1], points[2] );
@@ -1604,6 +1668,13 @@
       {
         partner_point_ptr = partner_point_list.get_and_step();
         td_partner = TDGeomFacet::get_geom_facet( partner_point_ptr );
+          //added mbrewer:  the check for a pointer here shouldn't
+          // be necessary, but I have a case where it fails.  I don't
+          // see where the logic is wrong.
+        if(!td_partner){
+          TDGeomFacet::add_geom_facet( partner_point_ptr , -1);
+          td_partner = TDGeomFacet::get_geom_facet( partner_point_ptr );
+        }
         td_partner->add_partner_point( new_point_ptr );
         td_new_point->add_partner_point( partner_point_ptr );
       }
@@ -2532,7 +2603,7 @@
 //Function:  dump (PUBLIC)
 //Description: debug
 //===============================================================================
-void ChollaEngine::dump( char *filename, double angle )
+void ChollaEngine::dump( const char *filename, double angle )
 {
   int include_results = 0;
   int num_face = faceList.size();
@@ -2611,14 +2682,12 @@
 
 //===============================================================================
 //Function:  mark_features (PUBLIC)
-//Description: is subject to change, may be modified, placed somewhere else
-//             added by Ved Vyas, 8-2003
+//Description: Calling this before ChollaEngine create geometry / topology
+// allows you to define features points. This can be used in conjunction
+// with the feature angle option or exclusively (original intention).
 //===============================================================================
 void ChollaEngine::mark_features (DLIList<CubitPoint*> &feature_points)
 {
-    // Calling this before ChollaEngine create geometry / topology
-    // allows you to define features points. This can be used in conjunction
-    // with the feature angle option or exclusively (original intention).
   int ii;
   TDGeomFacet *td_gm = NULL;
   CubitPoint *curr_pt = NULL;
@@ -2635,6 +2704,28 @@
     curr_pt->set_as_feature();
   }
 }
+
+//===============================================================================
+//Function:  mark_features (PUBLIC)
+//Description: Calling this before ChollaEngine create geometry / topology
+// allows you to define features points. This can be used in conjunction
+// with the feature angle option or exclusively (original intention).
+//===============================================================================
+void ChollaEngine::mark_features (DLIList<CubitFacetEdge*> &feature_edges)
+{
+  int ii;
+  CubitFacetEdge *curr_edge = NULL;
+	
+	// loop through supplied CubitFaceEdge*
+	// set the hit flag on each one
+
+  for (ii=0; ii < feature_edges.size(); ++ii)
+  {
+    curr_edge = feature_edges.get_and_step();
+    curr_edge->set_as_feature();
+  }
+}
+
   
 static CubitStatus create_tri_facets(int *face_list,int current_position,
                                      CubitPoint **point_list,
@@ -2709,9 +2800,16 @@
   }
   return CUBIT_SUCCESS;
 }
-  
+
+//===================================================================================
+// Description: given facets in the form of a GMem data structure create new
+//              CubitFacet and CubitPoint classes and return in lists
+// Notes: 
+// Author: 
+// Date: 
+//===================================================================================
 CubitStatus ChollaEngine::get_facets(GMem& gMem, DLIList<CubitFacet*> &facet_list, 
-                                DLIList<CubitPoint*> &dl_point_list)
+                                     DLIList<CubitPoint*> &dl_point_list)
 {
   if(gMem.fListCount == 0)
     return CUBIT_FAILURE;
@@ -2782,5 +2880,1256 @@
   return CUBIT_SUCCESS;
 }
 
+//=============================================================================
+//Function: collapses a given curve to a given point_to_keep
+//          
+//Description:
+//Note: the hashing and other data structures are not updated during collapse.
+//Author: william roshan quadros
+//Date:  12/15/08
+//=============================================================================
+CubitStatus ChollaEngine::collapse_curve( ChollaCurve *cholla_curve, ChollaPoint *point_to_keep )
+{
+  // Make sure there are no underlying facet edges connected with this curve
+  if( cholla_curve->get_facet_list().size() )
+    return CUBIT_FAILURE;
+  
+  // Disassociate from cholla_surfaces 
+  DLIList<ChollaSurface *> &ref_surfaces = cholla_curve->get_surfaces();
+  int i;
+  ChollaSurface *cholla_surface;
+  for( i = 0; i < ref_surfaces.size(); i++ )
+  {
+    cholla_surface = ref_surfaces.get_and_step();
+    cholla_surface->remove_curve( cholla_curve );
+  }
+  ref_surfaces.clean_out();
 
+  // Disassociate from cholla point_to_delete 
+  // Make sure curve has at least one point
+  DLIList<ChollaPoint *> &cholla_pnts = cholla_curve->get_points();
+  if( 0 == cholla_pnts.size()  )
+    return CUBIT_FAILURE;
 
+    // free eval tool
+  if( cholla_curve->get_eval_tool() )
+  {
+    delete cholla_curve->get_eval_tool(); 
+  }
+
+  // find the point to delete
+  ChollaPoint *first_pnt = cholla_pnts.get_and_step();
+  ChollaPoint *last_pnt = cholla_pnts.get();
+  ChollaPoint *point_to_del = NULL;
+  switch( cholla_pnts.size() )
+  {
+
+  case 2:    
+    if( point_to_keep == last_pnt )
+    {
+      point_to_del = first_pnt;
+    }
+    else
+    {
+      if( point_to_keep == first_pnt )
+      {
+        point_to_del = last_pnt;
+      }
+    }
+
+    // disassociate end points from cholla_curve
+    if( point_to_del )
+    {
+      point_to_del->remove_curve( cholla_curve );
+      cholla_pnts.remove( point_to_del );
+    }
+    if( point_to_keep )
+    {
+      point_to_keep->remove_curve( cholla_curve );
+      cholla_pnts.remove( point_to_keep );
+    }
+
+    // Merge two points 
+    merge_two_points( point_to_keep, point_to_del );
+
+    break;
+
+  case 1:
+    // disassociate end points from cholla_curve
+    point_to_del = first_pnt;
+    point_to_del->remove_curve( cholla_curve );
+    cholla_pnts.remove( point_to_del );
+    
+    if( 0 == point_to_del->get_curve_list_ptr()->size() )
+    {
+      // remove point_to_del from ChollaEngine
+      remove_point( point_to_del );
+
+      // free point_to_del
+      delete point_to_del;
+    }    
+    break;
+
+  default:
+    return CUBIT_FAILURE;
+  }
+
+
+  // Disassociate curve from chollaEngine
+  this->remove_curve( cholla_curve );
+
+  // free the cholla_curve
+  delete cholla_curve;
+
+  return CUBIT_SUCCESS;
+}
+
+  // Merge two points 
+CubitStatus ChollaEngine::merge_two_points( ChollaPoint *point_to_keep, ChollaPoint *point_to_del )
+{
+  // move cholla curves from point_to_del to point_to_keep
+  DLIList<ChollaCurve *> &del_pnt_curves = point_to_del->get_curves();
+  int i;
+  ChollaCurve *cholla_curve;
+  for( i = 0; i < del_pnt_curves.size(); i++ )
+  {
+    cholla_curve = del_pnt_curves.get_and_step();
+    
+    cholla_curve->remove_point( point_to_del );
+    cholla_curve->add_point( point_to_keep );
+    point_to_keep->add_curve( cholla_curve );
+  }
+  del_pnt_curves.clean_out();
+
+  // if point_to_keep facet is null use point_to_del's facet
+  if( NULL == point_to_keep->get_facets() && point_to_del->get_facets() )
+  {
+    point_to_keep->add_facet( point_to_del->get_facets() );
+  }
+  
+  // what we should do with data member id?  should we move if point_to_keep->get_id() !=  0?
+
+  // remove point_to_del from ChollaEngine
+  remove_point( point_to_del );
+
+  // free point_to_del
+  delete point_to_del;
+
+  return CUBIT_SUCCESS;
+}
+
+
+
+CubitStatus ChollaEngine::disassociate_surface( ChollaSurface *cholla_surf )
+{
+   // remove surface from volume
+  DLIList<ChollaVolume *> cholla_volumes;
+  cholla_surf->get_volumes(cholla_volumes);
+  int i;
+  ChollaVolume *cholla_volume;
+  for (i=0; i<cholla_volumes.size(); i++)
+  {
+    cholla_volume = cholla_volumes.get_and_step();
+    cholla_volume->remove_surface( cholla_surf );
+  }
+  
+   // Disassociate curves from suface
+  DLIList< ChollaCurve *> cholla_curves;
+  cholla_surf->get_curves( cholla_curves );
+  
+  ChollaCurve *cholla_curve;
+  for( i = 0; i < cholla_curves.size(); i++ )
+  {
+    cholla_curve = cholla_curves.get_and_step();
+    
+    cholla_curve->remove_surface( cholla_surf );
+    cholla_surf->remove_curve( cholla_curve );
+  }
+  cholla_curves.clean_out();
+
+  // Remove facet tool if available ?
+  if( cholla_surf->get_eval_tool() )
+  {
+#ifdef _DEBUG
+    PRINT_INFO("WARNING: delete ch_surf->facet_eval_tool safely \n");//   
+#endif
+    //delete cholla_surf->get_eval_tool();
+    // set eval tool to NULL
+  }
+  
+  // remove from ChollaEngine
+  remove_surface( cholla_surf );
+
+  return CUBIT_SUCCESS;
+
+}
+//=============================================================================
+//Function: collapses a given surface 
+//Description: currently it disassociates surface with its curves and ChollaEngine 
+//Note: make sure there are no underlying facets and model is automatically watertight when input cholla_surf is deleted
+//Author: william roshan quadros
+//Date:  12/15/08
+//=============================================================================
+
+CubitStatus ChollaEngine::collapse_surface( ChollaSurface *cholla_surf )
+{
+  // Make sure there are no facets 
+  if( cholla_surf->get_facet_list().size() )
+     return CUBIT_FAILURE; 
+
+  disassociate_surface( cholla_surf );
+  
+  // free cholla surface
+  delete cholla_surf;
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus ChollaEngine::remove_facet_entity( CubitFacet *facet, ChollaSurface *cholla_surf )
+{
+  this->faceList.remove( facet );
+
+  if( cholla_surf )
+    cholla_surf->remove_facet( facet );
+
+  return CUBIT_SUCCESS;
+}
+  
+CubitStatus ChollaEngine::remove_facet_entity( CubitFacetEdge *facet_edge, ChollaCurve *cholla_curve )
+{
+  this->edgeList.remove( facet_edge );
+
+  if( cholla_curve )
+    cholla_curve->remove_facet( facet_edge );
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus ChollaEngine::remove_facet_entity( CubitPoint *facet_pnt, ChollaPoint *cholla_point )
+{
+  this->pointList.remove( facet_pnt );
+
+  if( cholla_point )
+    cholla_point->remove_facet(/* facet_pnt */);
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus ChollaEngine::remove_facet_entity( CubitFacet *facet, std::set<ChollaEntity *> &cholla_surfs )
+{
+  std::set<ChollaEntity *>::iterator set_it;
+  for( set_it = cholla_surfs.begin(); set_it != cholla_surfs.end(); set_it++ )
+  {
+    if( dynamic_cast< ChollaSurface *>(*set_it) )
+    {
+      static_cast<ChollaSurface *>(*set_it)->remove_facet( facet );
+    }
+  }
+
+  this->faceList.remove( facet );
+
+  return CUBIT_SUCCESS;
+}
+  
+CubitStatus ChollaEngine::remove_facet_entity( CubitFacetEdge *facet_edge, std::set<ChollaEntity *> &cholla_curves )
+{
+  
+  std::set<ChollaEntity *>::iterator set_it;
+  ChollaEntity *ptr_entity;
+  ChollaCurve *ptr_curve;
+  for( set_it = cholla_curves.begin(); set_it != cholla_curves.end(); set_it++ )
+  {
+    ptr_entity = *set_it;
+    ptr_curve = dynamic_cast<ChollaCurve *>( ptr_entity );
+    if( dynamic_cast<ChollaCurve*>(*set_it) )
+    { 
+      dynamic_cast<ChollaCurve*>(*set_it)->remove_facet( facet_edge );
+    }
+  }
+
+  this->edgeList.remove( facet_edge );
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus ChollaEngine::replace_facet_entity( CubitFacetEdge *remove_edge, CubitFacetEdge *replace_edge, std::set<ChollaEntity *> cholla_curves )
+{
+  std::set<ChollaEntity *>::iterator set_it; 
+  for( set_it = cholla_curves.begin(); set_it != cholla_curves.end(); set_it++ )
+  {
+    if( dynamic_cast<ChollaCurve*>(*set_it) )
+    { 
+      static_cast<ChollaCurve*>(*set_it)->replace_facet( remove_edge, replace_edge );
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+
+CubitStatus ChollaEngine::remove_facet_entity( CubitPoint *facet_pnt, std::set<ChollaEntity *> &cholla_points )
+{
+  this->pointList.remove( facet_pnt );
+
+  std::set<ChollaEntity *>::iterator set_it;
+  for( set_it = cholla_points.begin(); set_it != cholla_points.end(); set_it++ )
+  {
+    if( dynamic_cast<ChollaPoint*>(*set_it) )
+    { 
+      static_cast<ChollaPoint*>(*set_it)->remove_facet( facet_pnt );
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+/*
+// disassoicate ch_entity from ch_points, ch_curve, ch_surf, and ch_engine
+CubitStatus ChollaEngine::disassociate_curve( ChollaCurve *ch_curve )
+{
+  
+  // disassociate from cholla points
+  ch_curve->disassociate_from_points();
+  
+  // disassociate from cholla surface
+  ch_curve->disassociate_from_surfaces();
+
+  // disassociate from cholla engine
+  remove_curve( ch_curve );
+
+  return CUBIT_SUCCESS;
+}
+*/
+
+CubitStatus ChollaEngine::create_surface( int block_id,
+                                          ChollaSurface *&new_ch_surf )
+{
+  new_ch_surf = new ChollaSurface( block_id );
+  
+  // add it to cholla engine
+  chollaSurfaceList.append( new_ch_surf ); 
+
+  return CUBIT_SUCCESS;
+}
+
+ // Create new ch_curve and associate with end ch_points.  Add ch_curve to chollaEngine
+CubitStatus ChollaEngine::create_curve(int block_id, 
+                                       ChollaPoint *new_ch_pnt0, 
+                                       ChollaPoint *new_ch_pnt1, 
+                                       ChollaCurve *&new_ch_curve
+                                    )
+{
+
+  
+  new_ch_curve = new ChollaCurve( block_id );
+
+  // associate with cholla points
+  new_ch_curve->add_point( new_ch_pnt0 );
+  new_ch_pnt0->add_curve( new_ch_curve );
+  new_ch_curve->add_point( new_ch_pnt1 );
+  new_ch_pnt1->add_curve( new_ch_curve );
+
+
+  // update start and end facet points
+  new_ch_curve->set_start( CAST_TO( new_ch_pnt0->get_facets(), CubitPointData) );
+  new_ch_curve->set_end( CAST_TO( new_ch_pnt1->get_facets(), CubitPointData) );
+
+  // add it to cholla engine
+  chollaCurveList.append( new_ch_curve ); 
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus ChollaEngine::create_point( CubitPoint *pnt, ChollaPoint * &new_ch_pnt )
+{
+  new_ch_pnt = new ChollaPoint();
+  new_ch_pnt->add_facet( pnt );
+  double *coordinate = new double[3];
+  CubitVector coord_vect = pnt->coordinates();
+  coordinate[0] = coord_vect[0];
+  coordinate[1] = coord_vect[1];
+  coordinate[2] = coord_vect[2];
+  new_ch_pnt->assign_geometric_point( (void*) coordinate );
+
+  return CUBIT_SUCCESS;
+}
+
+
+// disassoicate ch_curve from ch_points, ch_surfs, and ch_engine
+CubitStatus ChollaEngine::disassociate_curve( ChollaCurve *ch_curve, bool disassociate_with_vert, bool disassociate_with_surf, bool disassociate_with_model )
+{
+  // remove ch_curve from ch_point
+  int i;
+  if( disassociate_with_vert )
+  {
+    for( i = 0; i < ch_curve->get_points().size(); i++ )
+    {
+      ch_curve->get_points().get_and_step()->remove_curve( ch_curve );
+    }
+    // remove ch_points
+    ch_curve->get_points().clean_out();
+  }
+
+  if( disassociate_with_surf )
+  {
+    // remove ch_curve in ch_surface
+    ChollaSurface *ptr_ch_surf;   
+    for( i = 0; i < ch_curve->get_surfaces().size(); i++ )
+    {
+      ptr_ch_surf = ch_curve->get_surfaces().get_and_step();
+      ptr_ch_surf->remove_curve( ch_curve );
+    }
+    // remove ch_surface
+    ch_curve->get_surfaces().clean_out();
+  }
+
+  if( disassociate_with_model )
+  {
+    // remove from ch_engie
+    this->remove_curve( ch_curve );
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: detach_volumes 
+//Description: Create independent manifold volumes from the non-manifold set 
+//Note: 
+//Author:sjowen
+//Date:  09/10/09
+//=============================================================================
+CubitStatus ChollaEngine::detach_volumes()
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+ 
+  // define maps between the original entities and their copies so we can 
+  // use them for detaching the facets
+  
+  std::map<ChollaSurface *, ChollaSurface *> surf_map;
+  std::map<ChollaCurve *, ChollaCurve *> curve_map;
+  std::map<ChollaPoint *, ChollaPoint *> point_map;
+  
+  for (int isurf=0; isurf<chollaSurfaceList.size(); isurf++)
+  {
+    ChollaSurface *chsurf_ptr = chollaSurfaceList.get_and_step();
+    
+    // look for any surfaces that are associated with exactly two volumes
+    
+    if (chsurf_ptr->num_volumes() == 2)
+    {
+      rv = detach_surface( chsurf_ptr, surf_map, curve_map, point_map );
+      if (rv != CUBIT_SUCCESS)
+        return CUBIT_FAILURE;
+    }
+  }
+  
+  // create the evaluation tools on the new entities
+  
+  CubitBoolean use_feature_angle = CUBIT_FALSE; 
+  double min_dot = 0.0;                    
+  int interp_order = 0;                 
+  CubitBoolean smooth_non_manifold = CUBIT_FALSE;
+  CubitBoolean split_surfaces = CUBIT_FALSE;
+  DLIList<ChollaSurface *> cholla_surfaces;
+  DLIList<ChollaCurve *> cholla_curves;
+  
+  // get lists of new surfaces and curves from the maps
+  
+  std::map<ChollaSurface *, ChollaSurface *>::iterator smap_it;
+  for (smap_it=surf_map.begin(); smap_it != surf_map.end(); smap_it++)
+  {
+    cholla_surfaces.append(smap_it->second);
+  }
+  
+  std::map<ChollaCurve *, ChollaCurve *>::iterator cmap_it;
+  for (cmap_it=curve_map.begin(); cmap_it != curve_map.end(); cmap_it++)
+  {
+    cholla_curves.append(cmap_it->second);
+  }
+  
+  // rebuild the new curves so the edges are oriented correctly
+  
+  for (int ii=0; ii<cholla_curves.size(); ii++)
+  {
+    ChollaCurve *cholla_curve = cholla_curves.get_and_step();
+    DLIList<ChollaPoint *>  cholla_points = cholla_curve->get_points();
+    int periodic = 0;
+    if (cholla_points.size() == 1)
+      periodic = 1;
+    else
+      assert(cholla_points.size() == 2);  // assuming we have exactly two end points so far
+    CubitPoint *start_point, *end_point;
+    cholla_curve->get_ends(start_point, end_point);
+    int max_edges = cholla_curve->num_edges();
+    cholla_curve->clean_out_edges();  // edges will be added in build_curve_from_edges
+    rv = cholla_curve->build_curve_from_edges( start_point, periodic, max_edges, NULL, cholla_curve );
+    if (rv != CUBIT_SUCCESS)
+      return rv;
+  }
+  
+  // replace the facets on the existing eval tools on the curves and surfaces bounding the interface.
+  // for simplicity, just replace them on all the existing eval tools on 
+  
+  for (int icurv = 0; icurv < chollaCurveList.size(); icurv++)
+  {
+    ChollaCurve *chcurv_ptr = chollaCurveList.get_and_step();
+    CurveFacetEvalTool *ceval = chcurv_ptr->get_eval_tool();
+    if (ceval != NULL)
+    {
+      DLIList<FacetEntity *> fedges = chcurv_ptr->get_facet_list();
+      DLIList<CubitFacetEdge *> edges;
+      CAST_LIST( fedges, edges, CubitFacetEdge );
+      ceval->replace_facets(edges);
+    }
+  }
+  
+  for (int isurf=0; isurf<chollaSurfaceList.size(); isurf++)
+  {
+    ChollaSurface *chsurf_ptr = chollaSurfaceList.get_and_step();
+    FacetEvalTool *seval = chsurf_ptr->get_eval_tool();
+    if (seval != NULL)
+    {
+      DLIList<FacetEntity *> ffacets = chsurf_ptr->get_facet_list();
+      DLIList<CubitFacet *> facets;
+      CAST_LIST( ffacets, facets, CubitFacet );
+      seval->replace_facets(facets);
+    }
+  }
+  
+  // build the eval tools
+      
+  rv = build_eval_tools(cholla_surfaces,
+                        cholla_curves,
+                        interp_order, use_feature_angle, 
+                        min_dot, smooth_non_manifold,
+                        split_surfaces );
+    
+  return rv;
+}
+
+//=============================================================================
+//Function: detach_surface 
+//Description: given a non-manifold surface in a cholla model, create a copy
+//             and update child entities
+//Notes:  assumes that chsurf_ptr has exactly 2 adjacent volumes
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::detach_surface(ChollaSurface *chsurf_ptr,
+                                          std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                          std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                          std::map<ChollaPoint *, ChollaPoint *> &point_map)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+  DLIList<ChollaVolume *> chvol_list;
+  
+  // detach the surface from its volumes
+  
+  chsurf_ptr->get_volumes(chvol_list);
+  ChollaVolume *chvol1_ptr = chvol_list.get_and_step();
+  assert(chvol1_ptr != NULL);
+  ChollaVolume *chvol2_ptr = chvol_list.get();
+  assert(chvol2_ptr != NULL);
+  assert(chvol1_ptr != chvol2_ptr);
+  
+  // create a copy of the non-manifold surface and attach it to volume 2
+  
+  ChollaSurface *newchsurf_ptr = new ChollaSurface( chsurf_ptr->get_block_id() );
+  chollaSurfaceList.append(newchsurf_ptr);
+  surf_map.insert(std::pair<ChollaSurface *, ChollaSurface *>(chsurf_ptr, newchsurf_ptr));
+  
+  chvol2_ptr->remove_surface(chsurf_ptr);
+  chsurf_ptr->remove_volume(chvol2_ptr);
+  chvol2_ptr->add_surface(newchsurf_ptr);
+  newchsurf_ptr->add_volume(chvol2_ptr);
+  
+  chsurf_ptr->set_merge_partner(newchsurf_ptr);
+  newchsurf_ptr->set_merge_partner(chsurf_ptr);
+  
+  // detach the curves
+  
+  DLIList<ChollaCurve *> chcurv_list;
+  chsurf_ptr->get_curves(chcurv_list);
+  for(int icurv = 0; icurv < chcurv_list.size(); icurv++)
+  {
+    ChollaCurve *chcurv_ptr = chcurv_list.get_and_step();
+    rv = detach_curve( chcurv_ptr, newchsurf_ptr, chvol2_ptr, curve_map );
+    if (rv != CUBIT_SUCCESS)
+      return rv;
+  }
+  
+  // detach the chollapoints
+  
+  DLIList<ChollaPoint *> chpt_list;
+  chsurf_ptr->get_vertices( chpt_list );
+  for (int ipt = 0; ipt < chpt_list.size(); ipt++)
+  {
+    ChollaPoint *chpt_ptr = chpt_list.get_and_step();
+    
+    rv = detach_point( chpt_ptr, chvol2_ptr, curve_map, point_map );
+    if (rv != CUBIT_SUCCESS)
+      return rv;
+  }
+  
+  // create new facets for the new surface and detach vol 1 facets from vol 2 facets
+  
+  rv = detach_facets(chsurf_ptr, chvol2_ptr, surf_map, curve_map, point_map);
+  if (rv != CUBIT_SUCCESS)
+    return rv;
+  
+  // set the cubitpoints at the correct start/end locations on the cholla curves
+  
+  rv = set_curve_endpoints(chsurf_ptr, newchsurf_ptr, curve_map, point_map);
+  if (rv != CUBIT_SUCCESS)
+    return rv;
+  
+  return rv;
+}
+
+//=============================================================================
+//Function: detach_curve 
+//Description: given a non-manifold curve in a cholla model, create a copy
+//             and update child entities. updates the curve_map
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::detach_curve(ChollaCurve *chcurv_ptr,
+                                       ChollaSurface *newchsurf_ptr,
+                                       ChollaVolume *chvol2_ptr,
+                                       std::map<ChollaCurve *, ChollaCurve *> &curve_map)
+{
+  
+  // create a copy of the curve on the surface and add it to volume 2
+  
+  ChollaCurve *newchcurv_ptr = new ChollaCurve( chcurv_ptr->get_block_id() );
+  chollaCurveList.append( newchcurv_ptr );
+  curve_map.insert(std::pair<ChollaCurve *, ChollaCurve *>(chcurv_ptr, newchcurv_ptr));
+  newchsurf_ptr->add_curve(newchcurv_ptr);
+  newchcurv_ptr->add_surface(newchsurf_ptr);
+  
+  // any surfaces attached to this chcurv that are in vol2 are removed and the newchcurv is added
+  
+  DLIList<ChollaSurface *> chcsurf_list = chcurv_ptr->get_surfaces();
+  for (int icsurf = 0; icsurf < chcsurf_list.size(); icsurf++)
+  {
+    ChollaSurface *chcsurf_ptr = chcsurf_list.get_and_step();
+    if (chcsurf_ptr->is_in_volume(chvol2_ptr))
+    {
+      chcurv_ptr->remove_surface(chcsurf_ptr);
+      chcsurf_ptr->remove_curve(chcurv_ptr);
+      newchcurv_ptr->add_surface(chcsurf_ptr);
+      chcsurf_ptr->add_curve(newchcurv_ptr);
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: detach_point 
+//Description: given a non-manifold point in a cholla model, create a copy
+//             and update connectivity. updates the point_map
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::detach_point(ChollaPoint *chpt_ptr,
+                                       ChollaVolume *chvol2_ptr,
+                                       std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                       std::map<ChollaPoint *, ChollaPoint *> &point_map)
+{
+  // create a copy of the chollapoint on the interface surface
+  
+  ChollaPoint *newchpt_ptr = new ChollaPoint ();
+  chollaPointList.append( newchpt_ptr );
+  point_map.insert(std::pair<ChollaPoint *, ChollaPoint *>(chpt_ptr, newchpt_ptr));
+  
+  DLIList<ChollaCurve *> chptcurv_list = chpt_ptr->get_curves();
+  for (int iptcurv = 0; iptcurv < chptcurv_list.size(); iptcurv++)
+  {
+    ChollaCurve *chptcurv_ptr = chptcurv_list.get_and_step();
+    
+    // for curves that were copied (on the interface), add the new chollapoint to the new curve
+    
+    std::map<ChollaCurve *, ChollaCurve *>::iterator cmap_it;
+    cmap_it = curve_map.find(chptcurv_ptr);
+    if (cmap_it != curve_map.end())
+    {
+      ChollaCurve *newchcurv_ptr = cmap_it->second;
+      newchcurv_ptr->add_point(newchpt_ptr);
+      newchpt_ptr->add_curve(newchcurv_ptr);
+    }
+    else
+    {
+      // remove curve in vol 2 (not on interface) from the original point and add it to the new point
+      
+      if (chptcurv_ptr->is_in_volume(chvol2_ptr))
+      {
+        chpt_ptr->remove_curve(chptcurv_ptr);
+        chptcurv_ptr->remove_point(chpt_ptr);
+        newchpt_ptr->add_curve(chptcurv_ptr);
+        chptcurv_ptr->add_point(newchpt_ptr);
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+  
+
+//=============================================================================
+//Function: detach_facets 
+//Description: detach the individual facets to create a manifold representation
+//Note: makes a copy of the facets on the merged surface and its child entities
+//      and reconnects them locally
+//Author:sjowen
+//Date:  09/10/09
+//=============================================================================
+CubitStatus ChollaEngine::detach_facets(ChollaSurface *chsurf_ptr, ChollaVolume *chvol_ptr,
+                                        std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                        std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                        std::map<ChollaPoint *, ChollaPoint *> &point_map)
+{  
+  
+  CubitStatus rv = CUBIT_SUCCESS;
+  
+  std::vector<CubitPoint *> new_points;
+  std::vector<CubitFacetEdge *> new_edges;
+  
+  rv = copy_facets_at_interface( chsurf_ptr, new_points, new_edges, 
+                                 surf_map, curve_map, point_map );
+  if (rv != CUBIT_SUCCESS)
+    return rv;
+  
+  rv = connect_facets_at_interface( chsurf_ptr, chvol_ptr, new_points, new_edges );
+  if (rv != CUBIT_SUCCESS)
+    return rv;
+  
+  return rv;
+}
+  
+//=============================================================================
+//Function: copy_facets_at_interface 
+//Description: 
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::copy_facets_at_interface(ChollaSurface *chsurf_ptr, 
+                                                   std::vector<CubitPoint *> &new_points,
+                                                   std::vector<CubitFacetEdge *> &new_edges,
+                                                   std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                                   std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                                   std::map<ChollaPoint *, ChollaPoint *> &point_map)
+
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+  
+  // first set the marked flags on all facets entities on this surface to -1
+  
+  int ifacet;
+  DLIList<FacetEntity *> facet_list;
+  chsurf_ptr->get_facets( facet_list );
+  FacetDataUtil::mark_facets(facet_list, FACET_ENTITY_UNINITIALIZED);
+  
+  // create a copy of each of the facet entities on the surface.  The marked flag in the facet will
+  // keep track of the new entity created.  It will be a location in the new_points or new_edges
+  // array.  Once we are finished with creating points and edges, we can create the new facets
+  // given the references in the marked flags.
+  
+  // create new points
+  
+  rv = copy_points_at_interface(facet_list, new_points, surf_map, curve_map, point_map);
+  if (rv != CUBIT_SUCCESS)
+    return rv;
+  
+  // create new edges
+  
+  rv = copy_edges_at_interface(facet_list, new_points, new_edges, surf_map, curve_map, point_map);
+  if (rv != CUBIT_SUCCESS)
+    return rv;
+  
+  // create new facets
+  
+  DLIList<CubitFacet *> new_facets;
+  for (ifacet = 0; ifacet<facet_list.size(); ifacet++)
+  {
+    FacetEntity *facet_ptr = facet_list.get_and_step();
+    CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
+    CubitFacetEdge *fedge, *newfedges[3];
+    CubitFacet *newcfacet_ptr;
+    for (int ii=0; ii<3; ii++)
+    {
+      fedge = cfacet_ptr->edge(ii);
+      int idx = fedge->marked();
+      newfedges[ii] = new_edges[idx];
+    }
+    newcfacet_ptr = (CubitFacet *) new CubitFacetData(newfedges[0], newfedges[1], newfedges[2]);
+    new_facets.append( newcfacet_ptr );
+    FacetEntity *newfacet_ptr = dynamic_cast<FacetEntity *> (newcfacet_ptr);
+    set_new_facet_owners( 2, facet_ptr, newfacet_ptr, surf_map, curve_map, point_map );
+  }
+  
+  // make sure facets are oriented consistently on new volume
+  
+  CubitFacet *start_facet = new_facets.get(); 
+  CubitBoolean do_flip = CUBIT_TRUE;
+  int nfacets;
+  int mydebug = 0;
+  rv = check_facet_orientation(start_facet, do_flip, nfacets, mydebug );
+  
+  return rv;
+}
+
+//=============================================================================
+//Function: copy_points_at_interface 
+//Description: copy the points at the interface        
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::copy_points_at_interface(DLIList<FacetEntity *> &facet_list,
+                                                   std::vector<CubitPoint *> &new_points,
+                                                   std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                                   std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                                   std::map<ChollaPoint *, ChollaPoint *> &point_map)
+{
+  int iploc = 0;
+  
+  FacetEntity *fe_ptr, *newfe_ptr;
+  for (int ifacet = 0; ifacet<facet_list.size(); ifacet++)
+  {
+    FacetEntity *facet_ptr = facet_list.get_and_step();
+    CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
+    CubitPoint *point_ptr, *newpoint_ptr;
+    for (int ii=0; ii<3; ii++)
+    {
+      point_ptr = cfacet_ptr->point(ii);
+      if (point_ptr->marked() == FACET_ENTITY_UNINITIALIZED)
+      {
+        newpoint_ptr = (CubitPoint *) new CubitPointData( point_ptr->x(), point_ptr->y(), point_ptr->z() );
+        new_points.push_back(newpoint_ptr);
+        point_ptr->marked(iploc++);
+        fe_ptr = dynamic_cast<FacetEntity *> (point_ptr);
+        newfe_ptr = dynamic_cast<FacetEntity *> (newpoint_ptr);
+        set_new_facet_owners(0, fe_ptr, newfe_ptr, surf_map, curve_map, point_map );
+      }   
+    } 
+  } 
+  
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: copy_edges_at_interface 
+//Description: copy the edges at the interface        
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::copy_edges_at_interface(DLIList<FacetEntity *> &facet_list,
+                                                  std::vector<CubitPoint *> &new_points,
+                                                  std::vector<CubitFacetEdge *> &new_edges,
+                                                  std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                                  std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                                  std::map<ChollaPoint *, ChollaPoint *> &point_map)
+{
+  int ieloc = 0;
+  for (int ifacet = 0; ifacet<facet_list.size(); ifacet++)
+  {
+    FacetEntity *facet_ptr = facet_list.get_and_step();
+    CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
+    CubitFacetEdge *edge_ptr, *newedge_ptr;
+    for (int ii=0; ii<3; ii++)
+    {
+      edge_ptr = cfacet_ptr->edge(ii);
+      if (edge_ptr->marked() == FACET_ENTITY_UNINITIALIZED)
+      {
+        CubitPoint *p0 = edge_ptr->point( 0 );
+        CubitPoint *p1 = edge_ptr->point( 1 );
+        int idx0 = p0->marked();
+        int idx1 = p1->marked();
+        CubitPoint *newp0 = new_points[idx0];
+        CubitPoint *newp1 = new_points[idx1];
+        newedge_ptr = (CubitFacetEdge *) new CubitFacetEdgeData( newp0, newp1 );
+        new_edges.push_back(newedge_ptr);
+        edge_ptr->marked(ieloc++);
+        FacetEntity *fe_ptr = dynamic_cast<FacetEntity *> (edge_ptr);
+        FacetEntity *newfe_ptr = dynamic_cast<FacetEntity *> (newedge_ptr);
+        set_new_facet_owners( 1, fe_ptr, newfe_ptr, surf_map, curve_map, point_map );
+      }  
+    } 
+  }
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: connect_facets_at_interface 
+//Description: detach the facets from original points and edges and reattach to new copy         
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::connect_facets_at_interface(ChollaSurface *chsurf_ptr, 
+                                                      ChollaVolume *chvol_ptr,
+                                                      std::vector<CubitPoint *> &new_points,
+                                                      std::vector<CubitFacetEdge *> &new_edges)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+  
+  DLIList<ChollaCurve *> chcurv_list;
+  chsurf_ptr->get_curves(chcurv_list);
+  for (int icrv = 0; icrv < chcurv_list.size(); icrv++)
+  {
+    ChollaCurve *chcurv_ptr = chcurv_list.get_and_step();
+    
+    rv = connect_points_at_interface( chcurv_ptr, chvol_ptr, new_points );
+    if (rv != CUBIT_SUCCESS)
+      return rv;
+    
+    rv = connect_edges_at_interface( chcurv_ptr, chvol_ptr, new_edges );
+    if (rv != CUBIT_SUCCESS)
+      return rv;
+  } 
+
+  return rv;
+}
+
+//=============================================================================
+//Function: connect_points_at_interface 
+//Description: detach the facet points from original facets and reattach to new copy  
+//Notes: chcurv_ptr is a curve at the interface on the original volume
+//       chvol_ptr is the second volume (new (copied) entities belong to vol 2)
+//       new_points is a list of new points on vol 2
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::connect_points_at_interface(ChollaCurve *chcurv_ptr,
+                                                      ChollaVolume *chvol_ptr,
+                                                      std::vector<CubitPoint *> &new_points)
+{
+  DLIList<CubitPoint *> cp_list;
+  chcurv_ptr->get_facet_points(cp_list, CUBIT_TRUE);
+  for (int ip = 0; ip<cp_list.size(); ip++)
+  {
+    CubitPoint *cp_ptr = cp_list.get_and_step();
+    CubitPoint *newcp_ptr = new_points[cp_ptr->marked()];
+    
+    // set the point into edges that are on volume 2.
+    // Note that there is no direct reference from points to edges in our data structure 
+    // so no need to add/remove the edge from the point
+    
+    DLIList<CubitFacetEdge *> pedge_list;
+    cp_ptr->edges(pedge_list);
+    for (int iedge=0; iedge<pedge_list.size(); iedge++)
+    {
+      CubitFacetEdge *edge_ptr = pedge_list.get_and_step();
+      TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( edge_ptr );
+      if (td_geom->is_in_volume( chvol_ptr ))
+      {
+        CubitPoint *p0 = edge_ptr->point(0);
+        CubitPoint *p1 = edge_ptr->point(1);
+        CubitFacetEdgeData *cfed_ptr = dynamic_cast<CubitFacetEdgeData *> (edge_ptr);
+        if (p0 == cp_ptr)
+          cfed_ptr->set_point( newcp_ptr, 0 );
+        else if (p1 == cp_ptr)
+          cfed_ptr->set_point( newcp_ptr, 1 );
+      }
+    }    
+    
+    // remove facets in volume 2 from the point and add the to the new point
+    // update the point reference on the facet
+    
+    DLIList<CubitFacet *> pfacet_list;
+    cp_ptr->facets(pfacet_list);
+    for (int ifacet = 0; ifacet < pfacet_list.size(); ifacet++)
+    {
+      CubitFacet *facet_ptr = pfacet_list.get_and_step();
+      TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( facet_ptr );
+      if (td_geom->is_in_volume( chvol_ptr ))
+      {
+        cp_ptr->remove_facet( facet_ptr );        
+        newcp_ptr->add_facet( facet_ptr );
+        int ptidx = facet_ptr->point_index(cp_ptr);
+        CubitFacetData *cfd_ptr = dynamic_cast<CubitFacetData *> (facet_ptr);
+        cfd_ptr->set_point(newcp_ptr, ptidx);
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: connect_edges_at_interface 
+//Description: detach the facet edges from original facets and reattach to new copy         
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::connect_edges_at_interface(ChollaCurve *chcurv_ptr,
+                                                     ChollaVolume *chvol_ptr,
+                                                     std::vector<CubitFacetEdge *> &new_edges)
+{
+  DLIList<FacetEntity *> fe_list = chcurv_ptr->get_facet_list();
+  for (int ie=0; ie<fe_list.size(); ie++)
+  {
+    FacetEntity *fe_ptr = fe_list.get_and_step();
+    CubitFacetEdge *edge_ptr = dynamic_cast<CubitFacetEdge *> (fe_ptr);
+    assert(edge_ptr != NULL);
+    DLIList<CubitFacet *> efacet_list;
+    edge_ptr->facets(efacet_list);
+    for (int ifacet=0; ifacet<efacet_list.size(); ifacet++)
+    {
+      CubitFacet *facet_ptr = efacet_list.get_and_step();
+      TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( facet_ptr );
+      if (td_geom->is_in_volume( chvol_ptr ))
+      {
+        edge_ptr->remove_facet( facet_ptr );
+        CubitFacetEdge *newedge_ptr = new_edges[edge_ptr->marked()];
+        newedge_ptr->add_facet( facet_ptr );
+        int edidx = facet_ptr->edge_index(edge_ptr);
+        CubitFacetData *cfd_ptr = dynamic_cast<CubitFacetData *> (facet_ptr);
+        cfd_ptr->edge(newedge_ptr, edidx);
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: set_new_facet_owners 
+//Description: update the ownenrship of the new detached facet entity based upon
+//             the map set up in detach_volumes
+//            
+//Author:sjowen
+//Date:  09/14/09
+//=============================================================================
+CubitStatus ChollaEngine::set_new_facet_owners(int type, //0, 1, or 2 based on dimension of facet entity
+                                               FacetEntity *fe_ptr, FacetEntity *newfe_ptr, 
+                                               std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                               std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                               std::map<ChollaPoint *, ChollaPoint *> &point_map )
+{
+  
+  // The tooldata on the original facet entity should tell us what cholla entity it belongs
+  // to.  Using the map, we can then determine its new cholla entity partner.  With the
+  // new merge partner, set the ownership of the new facet.  Note that this manages one-to-many
+  // ownership cases where a facet lies on (or is owned by) any number of geometric entities
+  
+  TDGeomFacet *td_geom = TDGeomFacet::get_geom_facet( fe_ptr );
+  TDGeomFacet::add_geom_facet(newfe_ptr, td_geom->get_block_id());
+  
+  // the original facet entity is owned by one or more surfaces
+  
+  DLIList<ChollaSurface *> surf_list;
+  td_geom->get_cholla_surfs( surf_list );
+  for (int jj=0; jj<surf_list.size(); jj++)
+  {
+    ChollaSurface *surf_ptr = surf_list.get_and_step();
+    std::map<ChollaSurface *, ChollaSurface *>::iterator map_it;
+    map_it = surf_map.find( surf_ptr );
+    assert(map_it != surf_map.end());
+    ChollaSurface *newsurf_ptr = map_it->second;
+    TDGeomFacet *newtdgeom = TDGeomFacet::get_geom_facet( newfe_ptr );
+    newtdgeom->add_cholla_surf( newsurf_ptr );
+    
+    // add this facet entity to the cholla surface only if this is a facet
+    
+    if (type == 2)
+      newsurf_ptr->add_facet(newfe_ptr);
+  }
+
+  
+  // the original facet entity is owned by one or more curves
+  
+  DLIList<ChollaCurve *> curv_list;
+  td_geom->get_cholla_curves( curv_list );
+  for (int jj=0; jj<curv_list.size(); jj++)
+  {
+    ChollaCurve *curv_ptr = curv_list.get_and_step();
+    std::map<ChollaCurve *, ChollaCurve *>::iterator map_it;
+    map_it = curve_map.find( curv_ptr );
+    assert(map_it != curve_map.end());
+    ChollaCurve *newcurv_ptr = map_it->second;
+    TDGeomFacet *newtdgeom = TDGeomFacet::get_geom_facet( newfe_ptr );
+    newtdgeom->add_cholla_curve( newcurv_ptr );
+    
+    // add this facet entity to the cholla curve only if this is a facetedge
+    
+    if (type == 1)
+      newcurv_ptr->add_facet(newfe_ptr);
+      
+  }
+  
+  // the original facet entity is owned by one or more points (vertices)
+  
+  DLIList<ChollaPoint *> point_list;
+  td_geom->get_cholla_points( point_list );
+  for (int jj=0; jj<point_list.size(); jj++)
+  {
+    ChollaPoint *point_ptr = point_list.get_and_step();
+    std::map<ChollaPoint *, ChollaPoint *>::iterator map_it;
+    map_it = point_map.find( point_ptr );
+    assert(map_it != point_map.end());
+    ChollaPoint *newchpoint_ptr = map_it->second;
+    TDGeomFacet *newtdgeom = TDGeomFacet::get_geom_facet( newfe_ptr );
+    newtdgeom->add_cholla_point( newchpoint_ptr );
+    
+    // add this facet entity to the cholla point only if this is a cubitpoint
+    
+    if (type == 0)
+      newchpoint_ptr->add_facet(newfe_ptr);
+  }
+  return CUBIT_SUCCESS;
+
+}
+
+//=============================================================================
+//Function: verify_points_to_curves 
+//Description: verify the connectivity between points and curves           
+//Author:sjowen
+//Date:  09/16/09
+//=============================================================================
+CubitStatus ChollaEngine::verify_points_to_curves()
+{
+  for (int ii=0; ii<chollaPointList.size(); ii++)
+  {
+    ChollaPoint *chpt = chollaPointList.get_and_step();
+    if (!chpt->verify_curves())
+    {
+      PRINT_ERROR("ChollaPoint %d not associated with one of its curves.\n", chpt->get_id());
+      return CUBIT_FAILURE;
+    }
+  }
+  for (int ii=0; ii<chollaCurveList.size(); ii++)
+  {
+    ChollaCurve *chcrv = chollaCurveList.get_and_step();
+    if (!chcrv->verify_points())
+    {
+      PRINT_ERROR("ChollaCurve %d not associated with one of its points.\n", chcrv->get_id());
+      return CUBIT_FAILURE;
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+//=============================================================================
+//Function: set_curve_endpoints 
+//Description:   set the end points of the curves that are adjacent to the interface surface         
+//Author:sjowen
+//Date:  09/18/09
+//=============================================================================
+CubitStatus ChollaEngine::set_curve_endpoints(ChollaSurface *chsurf_ptr,
+                                              ChollaSurface *newchsurf_ptr,
+                                              std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                              std::map<ChollaPoint *, ChollaPoint *> &point_map )
+{
+
+  // start with the curves on the interface surface.
+  // use the same orientation on the new curves as the original
+  
+  DLIList<ChollaPoint *> chpt_list;
+  chsurf_ptr->get_vertices( chpt_list );
+  for (int ipt = 0; ipt < chpt_list.size(); ipt++)
+  {
+    ChollaPoint *chpt_ptr = chpt_list.get_and_step();
+    std::map<ChollaPoint *, ChollaPoint *>::iterator pmap_it;
+    pmap_it = point_map.find( chpt_ptr );
+    assert(pmap_it != point_map.end());
+    ChollaPoint *newchpt_ptr = pmap_it->second;
+    CubitPoint *newcp = dynamic_cast<CubitPoint *> (newchpt_ptr->get_facets());
+    DLIList<ChollaCurve *> chptcurv_list = chpt_ptr->get_curves();
+    for (int iptcurv = 0; iptcurv < chptcurv_list.size(); iptcurv++)
+    {
+      ChollaCurve *chptcurv_ptr = chptcurv_list.get_and_step();
+      std::map<ChollaCurve *, ChollaCurve *>::iterator cmap_it;
+      cmap_it = curve_map.find(chptcurv_ptr);
+      if (cmap_it == curve_map.end())
+        continue;  // only visit curves at the interface
+      
+      ChollaCurve *newchcurv_ptr = cmap_it->second;
+      CubitPoint *start, *end, *cp;
+      chptcurv_ptr->get_ends(start, end);
+      cp = dynamic_cast<CubitPoint *> (chpt_ptr->get_facets());
+      assert(cp != NULL);
+      assert(start!= NULL);
+      assert(end != NULL);
+
+      if ( cp == start )
+      {
+        newchcurv_ptr->set_start(newcp);
+      }
+      else if ( cp == end )
+      {
+        newchcurv_ptr->set_end(newcp);
+      }
+      else
+      {
+        assert (1);
+      }
+    }
+  }
+  
+  // get the rest of the curves on volume 2 that contain one of the points at the interface
+  
+  chpt_list.clean_out();
+  newchsurf_ptr->get_vertices( chpt_list );
+  for (int ipt = 0; ipt < chpt_list.size(); ipt++)
+  {
+    ChollaPoint *chpt_ptr = chpt_list.get_and_step();
+    DLIList<ChollaCurve *> chptcurv_list = chpt_ptr->get_curves();
+    for (int iptcurv = 0; iptcurv < chptcurv_list.size(); iptcurv++)
+    {
+      ChollaCurve *chptcurv_ptr = chptcurv_list.get_and_step();
+      if (!chptcurv_ptr->is_in_surface(newchsurf_ptr))
+      {
+        DLIList<ChollaPoint *> chpts_on_curve = chptcurv_ptr->get_points();
+        
+        // one point on the curve assumes a periodic curve.  set both ends the same
+        
+        if (chpts_on_curve.size() == 1)
+        {
+          ChollaPoint *chpt_on_crv = chpts_on_curve.get();
+          CubitPoint *cp = dynamic_cast<CubitPoint *> (chpt_on_crv->get_facets());
+          chptcurv_ptr->set_start(cp);
+          chptcurv_ptr->set_end(cp);
+        }
+        
+        // standard case. one point of curve is on the interface and one is not.
+        // In this case, one of the points has been replaced with a new point.
+        // so one of the end point pointers are out of date.  Determine which one
+        // and then set it.
+        
+        else if (chpts_on_curve.size() == 2)
+        {
+          ChollaPoint *chpt1_on_crv = chpts_on_curve.get_and_step();
+          ChollaPoint *chpt2_on_crv = chpts_on_curve.get();
+          CubitPoint *cp1 = dynamic_cast<CubitPoint *> (chpt1_on_crv->get_facets());
+          CubitPoint *cp2 = dynamic_cast<CubitPoint *> (chpt2_on_crv->get_facets());
+          CubitPoint *curstart, *curend;
+          chptcurv_ptr->get_ends(curstart, curend);
+          assert(curstart != NULL);
+          assert(curend != NULL);
+          assert(curstart != curend);
+          if (curstart == cp1)
+          {
+            chptcurv_ptr->set_end(cp2);
+          }
+          else if (curstart == cp2)
+          {
+            chptcurv_ptr->set_end(cp1);
+          }
+          else if (curend == cp2)
+          {
+            chptcurv_ptr->set_start(cp1);
+          }
+          else if (curend == cp1)
+          {
+            chptcurv_ptr->set_start(cp2);
+          }
+          else
+          {
+            assert(0);
+          }
+        }
+        else
+          assert(0);
+      }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+// EOF

Modified: cgm/branches/cubit/geom/Cholla/ChollaEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -17,9 +17,15 @@
 #ifndef CHOLLAENGINE_HPP
 #define CHOLLAENGINE_HPP
 
+#include <set>
+#include <map>
+#include <vector>
 #include "DLIList.hpp"
 
+#define FACET_ENTITY_UNINITIALIZED -1
+
 class FacetEntity;
+class ChollaVolume;
 class ChollaCurve;
 class ChollaSurface;
 class ChollaPoint;
@@ -27,6 +33,8 @@
 class CubitFacetEdge;
 class CubitFacet;
 class GMem;
+class ChollaEntity;
+class FacetEvalTool;
 
 class ChollaEngine
 {
@@ -42,17 +50,28 @@
                DLIList<CubitFacetEdge*> &edge_list,
                DLIList<CubitPoint*> &point_list );
   
+  //! Constructor
+  ChollaEngine(DLIList<CubitFacet*>     &facet_list,
+               DLIList<CubitFacetEdge*> &edge_list,
+               DLIList<CubitPoint*>     &point_list,
+               DLIList<ChollaVolume *>  &cholla_volumes,
+               DLIList<ChollaSurface *> &cholla_surfaces,
+               DLIList<ChollaCurve *>   &cholla_curves,
+               DLIList<ChollaPoint *>   &cholla_points );
+  
     //! Destructor
   ~ChollaEngine();
   void delete_me();
 
   //! Creates the geometry infrastructure based on the given mesh data.
-  CubitStatus create_geometry(CubitBoolean use_feature_angle = CUBIT_TRUE,
+  CubitStatus create_geometry (CubitBoolean use_feature_angle = CUBIT_TRUE,
                               double angle = 135.0,
                               int interp_order = 0,
                               CubitBoolean smooth_non_manifold = CUBIT_TRUE,
                               CubitBoolean split_surfaces = CUBIT_FALSE);
 
+  void get_volumes( DLIList<ChollaVolume *> & cholla_volume_list )
+    { cholla_volume_list += chollaVolumeList; }
   void get_surfaces( DLIList<ChollaSurface *> & cholla_surface_list )
     { cholla_surface_list += chollaSurfaceList; }
   void get_curves( DLIList<ChollaCurve *> & cholla_curve_list )
@@ -65,6 +84,27 @@
   void delete_eval_tools_but_not_facets();
     
 
+  // collapses a cholla curve
+  CubitStatus collapse_curve( ChollaCurve *cholla_curve, ChollaPoint *point_to_keep );
+  
+  // disassociate cholla surface
+  CubitStatus disassociate_surface( ChollaSurface *cholla_surf );
+
+  // collase a cholla surface
+  CubitStatus collapse_surface( ChollaSurface *cholla_surface );
+
+  // remove functions to update facet entities
+  CubitStatus remove_facet_entity( CubitFacet *facet, ChollaSurface *cholla_surf = NULL );
+  CubitStatus remove_facet_entity( CubitFacetEdge *facet_edge, ChollaCurve *cholla_curve = NULL);
+  CubitStatus remove_facet_entity( CubitPoint *facet_pnt, ChollaPoint *cholla_point = NULL );
+  CubitStatus remove_facet_entity( CubitFacet *facet, std::set<ChollaEntity *> &cholla_surfs );
+  CubitStatus remove_facet_entity( CubitFacetEdge *facet_edge, std::set<ChollaEntity *> &cholla_curves );
+  CubitStatus remove_facet_entity( CubitPoint *facet_pnt, std::set<ChollaEntity *> &cholla_points );
+
+  // replace funcctions to update facet entities in cholla entities
+  CubitStatus replace_facet_entity( CubitFacetEdge *remove_edge, CubitFacetEdge *replace_edge, std::set<ChollaEntity *> cholla_curves );
+
+
     //! Create the new features by cracking the facets at feature edges.
     //! Creates new edges and points and updates connectivity
 
@@ -80,8 +120,9 @@
 #endif
     //! assumes that valid CubitPoint* are supplied
     //! marks the CubitPoints as features to manually break up curves
-    // added by Ved Vyas 8-2003
+    //! and surfaces
   static void mark_features (DLIList<CubitPoint*> &feature_points);
+	static void mark_features (DLIList<CubitFacetEdge*> &feature_edges);
 
     //! fix the control points so they are C-zero          
   static CubitStatus fix_geometry( CubitBoolean smooth_non_manifold,
@@ -105,19 +146,53 @@
 
     //set the ChollaEngine to actually flip facets, or to just set a flag
     // when facets need to be reoriented
-  void set_flip_flag(CubitBoolean flip)
-    {
-      doFlip = flip;
-    }
+  void set_flip_flag(CubitBoolean flip){ doFlip = flip; }
     
   void print_me();
-  void dump( char *filename, double angle );
+  void dump( const char *filename, double angle );
+
+  // create cholla curve
+  //CubitStatus create_curve( int block_id, ChollaPoint *new_ch_pnt0, ChollaPoint *new_ch_pnt1, ChollaCurve *&new_ch_curve );
+  CubitStatus create_curve( int block_id, 
+                            ChollaPoint *new_ch_pnt0, 
+                            ChollaPoint *new_ch_pnt1, 
+                            ChollaCurve *&new_ch_curve
+                            );
+
+
+
+  CubitStatus create_point( CubitPoint *pnt, ChollaPoint *&new_ch_pnt );
+
+  CubitStatus create_surface( int block_id,
+                              ChollaSurface *&new_ch_surf );
+
+  // disassoicate ch_curve from ch_points, ch_curve, ch_surf, and ch_engine
+  CubitStatus disassociate_curve( ChollaCurve *ch_curve, 
+                                  bool disassociate_with_vert = true,
+                                  bool disassociate_with_surf = true,
+                                  bool disassociate_with_model = true );
+  // remove a cholla sub-entities 
+  void remove_curve( ChollaCurve *ch_curve ){ chollaCurveList.remove( ch_curve ); }
+  void remove_surface( ChollaSurface *ch_surface ){ chollaSurfaceList.remove( ch_surface ); }
+  void remove_point( ChollaPoint *ch_pnt ){ chollaPointList.remove( ch_pnt ); }
+  
+  // Create independent manifold volumes from the non-manifold set
+  CubitStatus detach_volumes();
+  
+  //! From the facet surface list, create geometric surface,
+  //! loops and coedges for each surface in the list
+  CubitStatus build_surface_and_curve_eval_tools( DLIList<ChollaSurface*> &cholla_surface_list,
+                                                 int interp_order, double min_dot, bool new_curve_eval_tool = false );
+  
+  // verify the connectivity between points and curves
+  CubitStatus verify_points_to_curves();
    
 private:
 
   DLIList<FacetEntity*> faceList;
   DLIList<FacetEntity*> edgeList;
   DLIList<FacetEntity*> pointList;
+  DLIList<ChollaVolume*> chollaVolumeList;
   DLIList<ChollaSurface*> chollaSurfaceList;
   DLIList<ChollaCurve*> chollaCurveList;
   DLIList<ChollaPoint*> chollaPointList;
@@ -177,11 +252,7 @@
   CubitStatus build_curve_eval_tools( DLIList<ChollaCurve*> &cholla_curve_list,
                                     int interp_order );
 
-    //! From the facet surface list, create geometric surface,
-    //! loops and coedges for each surface in the list
-  CubitStatus build_surface_eval_tools( DLIList<ChollaSurface*> &cholla_surface_list,
-                                      int interp_order, double min_dot );
-
+  
     //! functions for hashing curves - to speed up edge classification
   CubitStatus init_hash_curves( );
   void delete_hash_curves( );
@@ -245,6 +316,73 @@
     //! set the normals on two points so they are the same
   static CubitStatus merge_normals( CubitPoint *pt0, CubitPoint *pt1);
 
+  // merges two points 
+  CubitStatus merge_two_points( ChollaPoint *point_to_keep, ChollaPoint *point_to_del );
+  
+  // given a non-manifold surface in a cholla model, create a copy and update child entities
+  CubitStatus detach_surface(ChollaSurface *chsurf_ptr,
+                              std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                              std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                              std::map<ChollaPoint *, ChollaPoint *> &point_map);
+  CubitStatus detach_curve(ChollaCurve *chcurv_ptr,
+                           ChollaSurface *newchsurf_ptr,
+                           ChollaVolume *chvol2_ptr,
+                           std::map<ChollaCurve *, ChollaCurve *> &curve_map);
+  CubitStatus detach_point(ChollaPoint *chpt_ptr,
+                           ChollaVolume *chvol2_ptr,
+                           std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                           std::map<ChollaPoint *, ChollaPoint *> &point_map);
+  
+  
+  // Create independent manifold volumes from the non-manifold set
+  CubitStatus detach_facets(ChollaSurface *chsurf_ptr, ChollaVolume *chvol_ptr,
+                             std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                             std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                             std::map<ChollaPoint *, ChollaPoint *> &point_map);
+  
+  CubitStatus copy_facets_at_interface(ChollaSurface *chsurf_ptr, 
+                                       std::vector<CubitPoint *> &new_points,
+                                       std::vector<CubitFacetEdge *> &new_edges,
+                                       std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                       std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                       std::map<ChollaPoint *, ChollaPoint *> &point_map);
+  CubitStatus copy_points_at_interface(DLIList<FacetEntity *> &facet_list,
+                                       std::vector<CubitPoint *> &new_points,
+                                       std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                       std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                       std::map<ChollaPoint *, ChollaPoint *> &point_map);
+  CubitStatus copy_edges_at_interface(DLIList<FacetEntity *> &facet_list,
+                                      std::vector<CubitPoint *> &new_points,
+                                      std::vector<CubitFacetEdge *> &new_edges,
+                                      std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                      std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                      std::map<ChollaPoint *, ChollaPoint *> &point_map);
+  
+  // detach the facets from original points and edges and reattach to new copy
+  CubitStatus connect_facets_at_interface(ChollaSurface *chsurf_ptr, 
+                                          ChollaVolume *chvol_ptr,
+                                          std::vector<CubitPoint *> &new_points,
+                                          std::vector<CubitFacetEdge *> &new_edges);
+  CubitStatus connect_points_at_interface(ChollaCurve *chcurv_ptr,
+                                          ChollaVolume *chvol_ptr,
+                                          std::vector<CubitPoint *> &new_points);
+  CubitStatus connect_edges_at_interface(ChollaCurve *chcurv_ptr,
+                                         ChollaVolume *chvol_ptr,
+                                         std::vector<CubitFacetEdge *> &new_edges);
+  
+  // update the ownenrship of the new detached facet entity based uponthe map set up in detach_volumes
+  CubitStatus set_new_facet_owners(int type, //0, 1, or 2 based on dimension of facet entity
+                                   FacetEntity *fe_ptr, FacetEntity *newfe_ptr, 
+                                   std::map<ChollaSurface *, ChollaSurface *> &surf_map,
+                                   std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                   std::map<ChollaPoint *, ChollaPoint *> &point_map );
+  
+  // set the end points of the curves that are adjacent to the interface surface
+  CubitStatus set_curve_endpoints(ChollaSurface *chsurf_ptr,
+                                  ChollaSurface *newchsurf_ptr,
+                                  std::map<ChollaCurve *, ChollaCurve *> &curve_map,
+                                  std::map<ChollaPoint *, ChollaPoint *> &point_map );
+
 };
 
 #endif

Modified: cgm/branches/cubit/geom/Cholla/ChollaPoint.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaPoint.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaPoint.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -49,7 +49,35 @@
   }
 }
 
+//===============================================================================
+//Function:  is_in_curve (PUBLIC) 
+//===============================================================================
+CubitBoolean ChollaPoint::is_in_curve( ChollaCurve *chcurve )
+{
+  for (int ii=0; ii<curveList.size(); ii++)
+  {
+    ChollaCurve *curv = curveList.get_and_step();
+    if (curv == chcurve)
+      return CUBIT_TRUE;
+  }
+  return CUBIT_FALSE;
+}
 
+//=============================================================================
+//Function:  verify_curves (PUBLIC)
+//Description:  verify that all curves at this point have this point as an adjacency
+//Notes: 
+//=============================================================================
+CubitStatus ChollaPoint::verify_curves()
+{
+  for(int ii=0; ii<curveList.size(); ii++)
+  {
+    ChollaCurve *crv = curveList.get_and_step();
+    if (!crv->has_point(this))
+      return CUBIT_FAILURE;
+  }
+  return CUBIT_SUCCESS;
+}
 
 //EOF
 

Modified: cgm/branches/cubit/geom/Cholla/ChollaPoint.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaPoint.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaPoint.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -35,9 +35,18 @@
     // destructor
 
   void add_facet(FacetEntity *exterior_node)
-    {myCubitPoint = exterior_node; }
+  { myCubitPoint = exterior_node; }
     //- define the node associated with this point
 
+  void remove_facet( void )
+  {myCubitPoint = NULL;}
+   //- sets myCubitPoint to NULL
+
+  void remove_facet( FacetEntity *facet_pnt )
+  {if( myCubitPoint == facet_pnt ) myCubitPoint = NULL;}
+   //- sets myCubitPoint to NULL only if specified facet_pnt matches with myCubitPoint
+
+
   FacetEntity *get_facets()
     {return myCubitPoint;}
     //- get the point
@@ -46,6 +55,10 @@
     {curveList.append_unique( fcm_ptr );}
     //- associate a curve with this point
 
+  inline void remove_curve( ChollaCurve *fcm_ptr )
+  { curveList.remove( fcm_ptr ); }
+  //- removes a curve attached with it
+
   DLIList<ChollaCurve*> &get_curves()
     {return curveList;}
     //- get the list of curves attached to this point
@@ -66,6 +79,13 @@
 
   void get_surfaces(DLIList<ChollaSurface *> &surf_list);
     //- get list of associated cholla surfaces
+  
+  CubitBoolean is_in_curve( ChollaCurve *chcurve );
+    // return whether this point is in the given curve
+  
+  CubitStatus verify_curves();
+    //- verify that all curves at this point have this point as an adjacency
+
 };
 
 #endif

Modified: cgm/branches/cubit/geom/Cholla/ChollaSurface.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaSurface.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaSurface.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -19,6 +19,7 @@
 #include "TDFacetBoundaryEdge.hpp"
 #include "GfxDebug.hpp"
 #include "FacetEvalTool.hpp"
+#include "FacetDataUtil.hpp"
 
 //===============================================================================
 //Function:  ChollaSurface (PUBLIC) (constructor)
@@ -27,9 +28,11 @@
 {
   static int count = 100;
   id = count++;
+  myFlag = CUBIT_FALSE;
   mySurface = NULL;
   myEvalTool = NULL;
   blockId = block_id;
+  myMergePartner = NULL;
 }
 //===============================================================================
 //Function:  ~ChollaSurface (PUBLIC) (destructor)
@@ -58,7 +61,8 @@
 //Date: 12/22/00
 //=============================================================================
 CubitStatus ChollaSurface::split_surface( 
-  DLIList<ChollaSurface*> &facet_surface_list )
+  DLIList<ChollaSurface*> &facet_surface_list 
+  )
 {
   DLIList<ChollaSurface*> new_surface_list;
   CubitStatus stat = CUBIT_SUCCESS;
@@ -134,6 +138,7 @@
   return CUBIT_SUCCESS;
 }
 
+
 #if 0
 //=============================================================================
 //Function:  get_adj_facets (PRIVATE)
@@ -215,7 +220,9 @@
 CubitStatus ChollaSurface::get_adj_facets( 
   FacetEntity *start_face_ptr,
   DLIList<FacetEntity*> &face_list,
-  int mydebug)
+  int mydebug,
+  bool bound_check,
+  bool feature_edge_check)
 {
   //int found = 0;
   int ii;
@@ -269,7 +276,7 @@
         // of a feature angle.  Don't traverse past a feature angle edge
     
         TDGeomFacet *td_gm_edge = TDGeomFacet::get_geom_facet(edge_ptr);
-        if (td_gm_edge == NULL)
+        if (td_gm_edge == NULL || !feature_edge_check )
         {
           adj_face_list.clean_out();
           edge_ptr->get_parents( adj_face_list );
@@ -277,21 +284,31 @@
           // keep traversing only if there are two adjacent faces to this edge,
           // otherwise, this is a boundary
 
-          if (adj_face_list.size() == 2)
+          if (adj_face_list.size() != 2)
           {
-            adj_face_ptr = adj_face_list.get_and_step();
-            if (adj_face_ptr == face_ptr)
-              adj_face_ptr = adj_face_list.get();
+            continue;
+          }
 
-            // go to its neighbor if it is part of the surface
+          if( bound_check )
+          {
+            TDFacetBoundaryEdge *td_facet_bnd_edge = TDFacetBoundaryEdge::get_facet_boundary_edge( edge_ptr );
+            if( td_facet_bnd_edge )
+              continue;
+          }
+            
+          adj_face_ptr = adj_face_list.get_and_step();
+          if (adj_face_ptr == face_ptr)
+            adj_face_ptr = adj_face_list.get();
 
-            td_gm_face = TDGeomFacet::get_geom_facet(adj_face_ptr); 
-            if (td_gm_face->get_hit_flag() == id)
-            {
-              temp_list.append( adj_face_ptr );
-              td_gm_face->set_hit_flag( 0 );
-            }
+          // go to its neighbor if it is part of the surface
+
+          td_gm_face = TDGeomFacet::get_geom_facet(adj_face_ptr); 
+          if (td_gm_face->get_hit_flag() == id)
+          {
+            temp_list.append( adj_face_ptr );
+            td_gm_face->set_hit_flag( 0 );
           }
+          
         }
       }
     }
@@ -299,6 +316,8 @@
   return stat;
 }
 
+
+
 //=============================================================================
 //Function:  feature_angle (PRIVATE)
 //Description: mark all edges that exceed the specified feature angle
@@ -446,6 +465,32 @@
 }
 
 //=============================================================================
+//Function:  add_preexisting_feature_edges (PRIVATE)
+//Description: edges that were marked previously in function ChollaEngine::mark_features
+//             are added to the feature edge list
+//Author: sjowen
+//Date: 01/08
+//=============================================================================
+CubitStatus ChollaSurface::add_preexisting_feature_edges( 
+	DLIList<CubitFacetEdge *> &feature_edge_list)
+{
+	DLIList<CubitFacetEdge *> edge_list;
+	DLIList<CubitFacet *> facet_list;
+	CAST_LIST( surfaceElemList, facet_list, CubitFacet );
+	FacetDataUtil::get_edges( facet_list, edge_list );
+	int iedge;
+	CubitFacetEdge *edge;
+	for (iedge=0; iedge < edge_list.size(); iedge++)
+	{
+		edge = edge_list.get_and_step();
+		if (edge->is_feature())
+			feature_edge_list.append(edge);
+	}
+	return CUBIT_SUCCESS;
+}
+	
+
+//=============================================================================
 //Function:  non_manifold_edges (PRIVATE)
 //Description: mark all edges that are non-manifold (have more than 2 adj
 //             facets)
@@ -717,5 +762,62 @@
   dldraw(surfaceElemList);
 }
 
+//=============================================================================
+//Function:  flip_facets (PUBLIC)
+//Description: invert all facets on this surface 
+//Author: sjowen
+//Date: 09/10/09
+//=============================================================================
+void ChollaSurface::flip_facets()
+{
+  FacetEntity *facet_entity;
+  CubitFacet *facet_ptr;
+  for (int ii=0; ii<surfaceElemList.size(); ii++)
+  {
+    facet_entity = surfaceElemList.get_and_step();
+    facet_ptr = dynamic_cast<CubitFacet *> (facet_entity);
+    assert( facet_ptr != NULL );
+    facet_ptr->flip();
+  }
+}
+
+//=============================================================================
+//Function:  is_in_volume (PUBLIC)
+//Description: return whether this surface is in a particular volume 
+//Author: sjowen
+//Date: 09/11/09
+//=============================================================================
+CubitBoolean ChollaSurface::is_in_volume( ChollaVolume *chvol_ptr )
+{
+  ChollaVolume *mychvol_ptr;
+  for (int ii=0; ii<volList.size(); ii++)
+  {
+    mychvol_ptr = volList.get_and_step();
+    if (mychvol_ptr == chvol_ptr)
+      return CUBIT_TRUE;
+  }
+  return CUBIT_FALSE;
+}
+
+//=============================================================================
+//Function:  get_vertices (PUBLIC)
+//Description: get the list of ChollaPoints on this surface
+//Author: sjowen
+//Date: 09/11/09
+//=============================================================================
+void ChollaSurface::get_vertices( DLIList<ChollaPoint *> &chpt_list )
+{
+  chpt_list.clean_out();
+  ChollaCurve *chcurv_ptr;
+  for (int ii=0; ii<curveList.size(); ii++)
+  {
+    chcurv_ptr = curveList.get_and_step();
+    DLIList<ChollaPoint *> chc_pts = chcurv_ptr->get_points(); 
+    chpt_list += chc_pts;
+  }
+  chpt_list.uniquify_unordered();
+}
+
+
 //EOF
 

Modified: cgm/branches/cubit/geom/Cholla/ChollaSurface.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaSurface.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/ChollaSurface.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -13,7 +13,9 @@
 #include "DLIList.hpp"
 #include "ChollaEntity.hpp"
 
+class ChollaVolume;
 class ChollaCurve;
+class ChollaPoint;
 class FacetEntity;
 class CubitFacet;
 class CubitPoint;
@@ -22,22 +24,17 @@
 
 class ChollaSurface : public ChollaEntity
 {
-private:
-   
+private:   
   int id;
   int blockId;
+  CubitBoolean myFlag;
 
   DLIList<FacetEntity*> surfaceElemList;
   DLIList<ChollaCurve*> curveList;
+  DLIList<ChollaVolume*> volList;
   void *mySurface;
   FacetEvalTool *myEvalTool;
-
-  CubitStatus get_adj_facets( FacetEntity *start_face_ptr, 
-                             DLIList<FacetEntity*> &face_list,
-                             int mydebug = 0);
-    // recursive function that creates a list of all faces connected
-    // the passed in face that are part of this surface (or shell)
-
+  ChollaSurface *myMergePartner;
   void check_faceting();
   
 public:
@@ -57,15 +54,28 @@
     {myEvalTool = eval_tool_ptr;}
   FacetEvalTool* get_eval_tool()
     {return myEvalTool;}
+  
+  ChollaSurface *merge_parter(){ return myMergePartner; }
+  void set_merge_partner( ChollaSurface *merge_partner )
+    { myMergePartner = merge_partner;}
+  
+  CubitBoolean get_flag(){ return myFlag; }
+  void set_flag( CubitBoolean stat ){ myFlag = stat; }                       
 
   void add_facet(FacetEntity *exterior_face)
     {surfaceElemList.append(exterior_face);}
+
   int add_mesh_unique(FacetEntity *exterior_face)
     {return surfaceElemList.append_unique(exterior_face);} 
+  
+  void remove_facet( FacetEntity *facet )
+  {surfaceElemList.remove( facet );}
+
   DLIList<FacetEntity*> &get_facet_list()
     {return surfaceElemList;}
   DLIList<FacetEntity*> *get_facet_list_ptr()
     {return &surfaceElemList;}
+  void get_vertices( DLIList<ChollaPoint *> &chpt_list );
   void get_curves( DLIList<ChollaCurve*> &bcm_list )
     {bcm_list = curveList; }
   void add_curve( ChollaCurve *bcm_ptr )
@@ -74,6 +84,17 @@
     {curveList.append_unique(bcm_ptr);}
   void remove_curve( ChollaCurve *bcm_ptr)
     {curveList.remove(bcm_ptr);}
+  void get_volumes( DLIList<ChollaVolume*> &cholla_vol_list )
+    {cholla_vol_list = volList; }
+  void add_volume( ChollaVolume *cholla_vol_ptr )
+    {volList.append(cholla_vol_ptr);}
+  void add_volume_unique( ChollaVolume *cholla_vol_ptr )
+    {volList.append_unique(cholla_vol_ptr);}
+  void remove_volume( ChollaVolume *cholla_vol_ptr)
+    {volList.remove(cholla_vol_ptr);}
+  int num_volumes(){return volList.size();}
+  CubitBoolean is_in_volume( ChollaVolume *chvol_ptr );
+  
   int get_block_id()
     {return blockId;}
   void set_block_id(int flag)
@@ -81,6 +102,15 @@
 
   int get_id(){return id;}
 
+  CubitStatus get_adj_facets( FacetEntity *start_face_ptr, 
+                             DLIList<FacetEntity*> &face_list,
+                             int mydebug = 0,
+                             bool bound_check = false,
+                             bool feature_edge_check = true);
+    // recursive function that creates a list of all faces connected
+    // the passed in face that are part of this surface (or shell)
+
+
   CubitStatus split_surface( DLIList<ChollaSurface*> &block_surface_list );
     // split this surface into multiple ChollaSurface where there are
     // discontinuous faces.
@@ -89,6 +119,10 @@
                              DLIList<CubitFacetEdge *> &feature_edge_list);
     // mark all edges that exceed the specified feature angle
     // min_dot is the minimum dot product between adjacent face normals
+	
+	CubitStatus add_preexisting_feature_edges( DLIList<CubitFacetEdge *> &feature_edge_list);
+	  // edges that were marked previously in function ChollaEngine::mark_features
+	  // are added to the feature edge list
 
   CubitStatus non_manifold_edges( DLIList<CubitFacetEdge *> &feature_edge_list );
     // mark all edges that are non-manifold (have more than 2 adj facets
@@ -112,7 +146,10 @@
 
   DLIList<DLIList<CubitFacetEdge *>*> *get_loop_edges( );
     // return the ordered list of edges on the boundary of this surface 
-
+  
+  void flip_facets();
+    // invert all the facets on this surface
+  
   void debug_draw();
 };
 

Added: cgm/branches/cubit/geom/Cholla/ChollaVolume.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaVolume.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/Cholla/ChollaVolume.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,32 @@
+//- Class:       ChollaVolume
+//- Description: Temporary class for constructing the facet-based geometry
+//-              
+//- Owner:       Steven J. Owen
+//- Checked by:
+//- Version:
+#include "ChollaVolume.hpp"
+#include "ChollaSurface.hpp"
+
+
+//===============================================================================
+//Function:  ChollaVolume (PUBLIC) (constructor)
+//===============================================================================
+ChollaVolume::ChollaVolume(int block_id)
+{
+  static int count = 100;
+  id = count++;
+  myVolume = NULL;
+  blockId = block_id;
+}
+
+//===============================================================================
+//Function:  ~ChollaVolume (PUBLIC) (destructor)
+//===============================================================================
+ChollaVolume::~ChollaVolume()
+{
+}
+
+
+
+//EOF
+

Added: cgm/branches/cubit/geom/Cholla/ChollaVolume.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/ChollaVolume.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/Cholla/ChollaVolume.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,57 @@
+//- Class: ChollaVolume
+//- Owner: Steven J. Owen
+//- Description: volume representation for the Cholla entities
+//- Created: 8/30/2009
+//- Checked By:
+//- Version:
+
+#ifndef ChollaVolume_HPP
+#define ChollaVolume_HPP
+
+#include "DLIList.hpp"
+#include "ChollaEntity.hpp"
+
+class ChollaSurface;
+
+class ChollaVolume : public ChollaEntity
+{
+private:   
+  int id;
+  int blockId;
+  
+  DLIList<ChollaSurface*> surfaceList;
+  void *myVolume;
+  
+public:
+   
+  ChollaVolume(int block_id);
+  ~ChollaVolume();
+
+  void assign_geometric_volume(void *vol)
+    {myVolume = vol;}
+  void* get_geometric_volume()
+    {return myVolume;}
+  void get_surfaces( DLIList<ChollaSurface*> &cholla_surf_list )
+    {cholla_surf_list = surfaceList; }
+  void add_surface( ChollaSurface *cholla_surf_ptr )
+    {surfaceList.append(cholla_surf_ptr);}
+  void add_surface_unique( ChollaSurface *cholla_surf_ptr )
+    {surfaceList.append_unique(cholla_surf_ptr);}
+  void remove_surface( ChollaSurface *cholla_surf_ptr)
+    {surfaceList.remove(cholla_surf_ptr);}
+  int get_block_id()
+    {return blockId;}
+  void set_block_id(int flag)
+    { blockId = flag; }
+
+  int get_id(){return id;}
+
+  void debug_draw();
+};
+
+#endif
+
+
+
+
+

Modified: cgm/branches/cubit/geom/Cholla/CubitFacet.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CubitFacet.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CubitFacet.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1168,3 +1168,20 @@
 
   edge->add_facet( this );
 }
+
+
+CubitPoint *CubitFacet::opposite_point( CubitFacetEdge *edge )
+{
+  int i;
+  for( i = 0; i < 3; i++ )
+    if( point(i) != edge->point(0) && point(i) != edge->point(1) )
+      return point(i);
+
+  return NULL;
+}
+
+CubitVector CubitFacet::update_normal( void )
+{
+   this->update_plane();
+   return normal();
+}

Modified: cgm/branches/cubit/geom/Cholla/CubitFacet.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CubitFacet.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CubitFacet.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -85,9 +85,13 @@
  
   virtual ~CubitFacet(); 
  
-  CubitVector normal(); 
+  CubitVector normal();  
     //- Returns the normal to this facet. 
- 
+
+  CubitVector update_normal( void );
+  //- update the plane and return the new normal
+
+
   const CubitBox& bounding_box() {return bBox;}; 
   void bounding_box( CubitBox &box ) 
   { bBox = box; } 
@@ -234,7 +238,13 @@
     //- Get the edge on the triangle opposite of the passed point. 
     //- p1 and p2 will be passed back as NULL if point is not a 
     //- point on this triangle. 
+
+  
+  CubitPoint *opposite_point( CubitFacetEdge *edge );
+  //- returns the opposite point of input edge.  Input edge should be incident on facet. 
+  //- If input edge is not incident on facet then any of the one point can be returned
  
+  
   void points( CubitPoint *&p0, CubitPoint *&p1, CubitPoint *&p2 ) 
     { p0 = point(0); p1 = point(1); p2 = point(2); } 
   void tri_nodes( CubitPoint *&p0, CubitPoint *&p1, CubitPoint *&p2 )  

Modified: cgm/branches/cubit/geom/Cholla/CubitFacetData.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CubitFacetData.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CubitFacetData.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -135,19 +135,21 @@
 //Description:  destructor 
 //=========================================================================== 
 CubitFacetData::~CubitFacetData() 
-{ 
-  int ii = 3;
- 
+{
+  destruct_facet_internals();
+}
+
+void CubitFacetData::destruct_facet_internals()
+{
+  int ii = 3; 
   for (ii = 2; ii>=0; ii--){
     //remove this triangle-point association at the points. 
     CubitPoint *current_point = point(ii);
     if (current_point)
-      current_point->remove_facet(this);
+      current_point->remove_facet(this);     
+
+    pointArray[ii] = NULL;
     
-    DLIList <CubitFacet *> facet_list;
-    current_point->facets(facet_list);
-     
-     
      //remove edge-point association at the edges
      
      CubitFacetEdge *current_edge = edgeArray[ii];
@@ -155,10 +157,11 @@
      CubitStatus status;
      if (current_edge)
        status = current_edge->remove_facet(this);
-     
+     edgeArray[ii] = NULL;
   }
 }
 
+
 //=========================================================================== 
 //Function Name: closest_point 
 // 
@@ -229,13 +232,33 @@
     if ( edge->point(0) == edge1_pt ) {
       edge_d->set_point(new_pt, 1);
       if ( !new_edge )
+      {
         new_edge = new CubitFacetEdgeData( new_pt, edge2_pt );
+        DLIList<ToolData*> tds;
+        edge->get_all_TDs(&tds);
+        for (int i=0; i<tds.size(); i++)
+        {
+          ToolData* new_td = tds.get_and_step()->propogate(new_edge);
+          if (new_td)
+            new_edge->add_TD(new_td);
+        }
+      }
       else if( new_edge->point(0) != new_pt )
         new_edge->flip();
     } else {
       edge_d->set_point(new_pt, 0);
       if ( !new_edge )
+      {
         new_edge = new CubitFacetEdgeData( edge2_pt, new_pt );
+        DLIList<ToolData*> tds;
+        edge->get_all_TDs(&tds);
+        for (int i=0; i<tds.size(); i++)
+        {
+          ToolData* new_td = tds.get_and_step()->propogate(new_edge);
+          if (new_td)
+            new_edge->add_TD(new_td);
+        }
+      }
       else if( new_edge->point(1) != new_pt )
         new_edge->flip();
     }
@@ -274,6 +297,17 @@
       new_facet = new CubitFacetData( other_pt, edge2_pt, new_pt );
     else
       new_facet = new CubitFacetData( other_pt, new_pt, edge2_pt );
+
+    DLIList<ToolData*> td_list;
+    facet->get_all_TDs(&td_list);
+    for (int i=0; i< td_list.size(); i++)
+    {
+      ToolData* new_td = td_list.get_and_step()->propogate(new_facet);
+      if (new_td)
+      {
+        new_facet->add_TD(new_td);
+      }
+    }
    
     if ( new_edge ) {
       assert(!new_facet->edge(0));
@@ -546,8 +580,23 @@
     return CUBIT_FAILURE;
   
     // get other facet
-  CubitFacetData* other_facet = dynamic_cast<CubitFacetData*>(pt_facets.next());
-  assert(!!other_facet);
+  CubitFacetData* other_facet = NULL;
+  if( pt_facets.get() == this )
+  {
+    other_facet = dynamic_cast<CubitFacetData*>(pt_facets.next());
+  }
+  else
+    if( pt_facets.next() == this )
+    {
+      other_facet = dynamic_cast<CubitFacetData*>( pt_facets.get() );
+    }
+    else
+    {
+      assert(0);
+      return CUBIT_FAILURE;
+    }
+
+  assert(other_facet);
   
     // get indices on other facet
   int other_pt1_index = other_facet->point_index(point1);
@@ -572,9 +621,20 @@
     // get the opposite points on facets
   CubitPoint* this_other_pt = this->point(this_edge_index);
   CubitPoint* other_other_pt = other_facet->point(other_edge_index);
+  if(this_other_pt == other_other_pt){
+    PRINT_WARNING("Unable to perform flip.\n");
+    return CUBIT_FAILURE;
+  }
   
+  
     // get the edge that is to be moved from this to the other facet
   CubitFacetEdge* this_trade_edge = this->edge(this_pt2_index);
+    // get the edge thatis to be moved from the other facet to this
+  CubitFacetEdge* other_trade_edge = other_facet->edge(other_pt1_index);
+  if(this_trade_edge == other_trade_edge){
+    PRINT_WARNING("Unable to perform flip (2).\n");
+    return CUBIT_FAILURE;
+  }
   int this_trade_use = this->edge_use(this_pt2_index);
   if ( this_trade_edge )
   {
@@ -582,8 +642,6 @@
     this_trade_edge->add_facet(other_facet);
   }
   
-    // get the edge thatis to be moved from the other facet to this
-  CubitFacetEdge* other_trade_edge = other_facet->edge(other_pt1_index);
   int other_trade_use = other_facet->edge_use(other_pt1_index);
   if ( other_trade_edge )
   {

Modified: cgm/branches/cubit/geom/Cholla/CubitFacetData.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CubitFacetData.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CubitFacetData.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -35,7 +35,10 @@
                   CubitPoint *p3, int *tool_data);
   CubitFacetData( CubitFacetEdge *e1, CubitFacetEdge *e2, 
                   CubitFacetEdge *e3);
-  ~CubitFacetData(); 
+  ~CubitFacetData();
+  
+  void destruct_facet_internals();
+  
   virtual int id(){return entityId;} 
   virtual void set_id( int ii ) { entityId = ii; }
        

Modified: cgm/branches/cubit/geom/Cholla/CubitFacetEdge.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CubitFacetEdge.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CubitFacetEdge.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -231,6 +231,16 @@
                                   double w[2] );
 
   double angle_between_facets();
+
+  inline int less_than(CubitFacetEdge*& e1, CubitFacetEdge*& e2)
+  {
+    double len1 = e1->length();
+    double len2 = e2->length();
+  
+    if (len1 == len2) return 0;
+    return (len1 < len2) ? -1 : 1;
+  }
+
 };
 
 inline void CubitFacetEdge::control_points(

Modified: cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -255,7 +255,7 @@
 {
   CubitStatus stat = CUBIT_SUCCESS;
   int ii, jj;
-  int mydebug = 0;  
+  int mydebug = DEBUG_FLAG(181);  
   CubitBoolean done = CUBIT_FALSE;
   DLIList<CubitFacetEdge*> *facet_loop;
   CubitFacetEdge *edge, *startedge = NULL;
@@ -375,6 +375,10 @@
   {
     stat = CUBIT_FAILURE;
     PRINT_WARNING("Can't define curve representation in mesh-based geometry\n");
+    PRINT_INFO("  Hint: Try importing as a free mesh and examining nodes and attached\n");
+    PRINT_INFO("        elements near the following locations:\n");
+    PRINT_INFO("        Start curve = %f %f %f\n", start_pt->x(), start_pt->y(), start_pt->z());
+    PRINT_INFO("        End curve = %f %f %f\n", end_pt->x(), end_pt->y(), end_pt->z());
     if (mydebug)
     {
       surfFacetEvalTool->debug_draw_facets( CUBIT_YELLOW );
@@ -1934,7 +1938,7 @@
 {
   CubitFacetEdge* this_edge;
   CubitFacetEdge* next_edge;
-  CubitPoint *this_pt0, *this_pt1;
+  CubitPoint *this_pt1;
   CubitPoint *next_pt0, *next_pt1;
   
   this_edge = myEdgeList.get_and_step();
@@ -1996,3 +2000,50 @@
 {
   draw_edges(color);
 }
+
+CubitBoolean CurveFacetEvalTool::replace_point( CubitPoint *del_pnt, CubitPoint *keep_pnt )
+{
+  CubitPoint *point_ptr;
+  int npoints = myPointList.size();
+  myPointList.reset();
+  CubitBoolean istat = CUBIT_FALSE;
+  int i;
+  for ( i = 0; i < npoints; i++ )
+  {
+    point_ptr = myPointList.get();
+    
+    if( point_ptr == del_pnt )
+    {
+      myPointList.remove();
+      myPointList.insert( keep_pnt );
+      istat = CUBIT_TRUE;
+    }
+    myPointList.step();
+  }
+  
+  return istat;
+}
+
+
+CubitBoolean CurveFacetEvalTool::replace_facets( DLIList< CubitFacetEdge *> &curv_edges )
+{
+
+  // replace edges 
+  this->myEdgeList = curv_edges;
+
+  // replace points
+  DLIList<CubitPoint *> point_list;
+  int i;
+  // insert start point of every facet_edge
+  curv_edges.reset();
+  for( i = 0; i < curv_edges.size(); i++ )
+  {
+    point_list.append( CAST_TO( curv_edges.get_and_step(), CubitFacetEdge )->point(0) );
+  }
+  // insert end point of last facet_edge
+  curv_edges.step( curv_edges.size() - 1 );
+  point_list.append( CAST_TO( curv_edges.get(), CubitFacetEdge )->point(1) );
+  this->myPointList = point_list;
+
+  return CUBIT_TRUE;
+}

Modified: cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/CurveFacetEvalTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -59,7 +59,8 @@
     CubitSense owrts );
     // generate a list of edges and points from the loop list
     // for this curve
-/*
+  
+  /*
   CubitStatus project_to_facet_edge(CubitVector &this_point,
                                     CubitVector &closest_point,
                                     CubitVector *tangent_ptr,
@@ -151,6 +152,11 @@
     //- lies outside this set, the closest point will be on the plane
     //- of the closest facet.  The closest_point is set to be that point.
 
+  // replace del_pnt with keep_pnt in point list
+  CubitBoolean replace_point( CubitPoint *del_pnt, CubitPoint *keep_pnt );
+
+  CubitBoolean replace_facets( DLIList< CubitFacetEdge *> &curv_edges );
+
   CubitStatus position_from_fraction( double fraction, // between 0 and 1
                                       CubitVector &location_on_curve );
     //- computes the location on the curve based on a fraction of the
@@ -183,6 +189,8 @@
   CubitBoolean has_good_curve_data(){return goodCurveData;}
   
   void debug_draw_facet_edges(int color = -1 );
+
+   
 };
 
 #endif // CURVE_FACET_EVAL_TOOL_HPP

Modified: cgm/branches/cubit/geom/Cholla/FacetDataUtil.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetDataUtil.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/FacetDataUtil.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1251,8 +1251,7 @@
 //  Date:     11/28/2002
 //  Author:   sjowen
 //===========================================================================
-CubitStatus FacetDataUtil::write_facets( char *file_name,
-                                         DLIList<CubitFacet *> &facet_list)
+CubitStatus FacetDataUtil::write_facets( const char *file_name, DLIList<CubitFacet *> &facet_list)
 {
   FILE *fp = fopen(file_name, "w");
   if (!fp)
@@ -1301,6 +1300,8 @@
   CubitBoolean &is_water_tight)
 {
   CubitStatus stat = CUBIT_SUCCESS;
+    //need to init this variable otherwise the caller must have.
+  is_water_tight = CUBIT_TRUE;
 
   // combine the quads and tri lists
 
@@ -1745,6 +1746,9 @@
         shell_list.back();
         shell_list.change_to(NULL);
 
+        if(!delete_shell_ptr)
+          return CUBIT_FAILURE;
+
         // mark all the points on the delete_shell as now being part of
         // the other shell.
 
@@ -1766,6 +1770,7 @@
         for (ll=0; ll<pt_shell_id; ll++)
           shell_ptr = shell_list.get_and_step();
         *shell_ptr += (*delete_shell_ptr);
+        delete delete_shell_ptr;
       }
 
       // set the marked flag to negative to indicate that it has been
@@ -1774,7 +1779,7 @@
       del_points.append(new_pt);
       new_pt->marked( -new_pt->marked() );
       pt->marked( -pt->marked() );
-    }
+    } // close_edges
 
     if (!was_merged)
     {
@@ -1801,7 +1806,7 @@
         pt = pt;
       }
     }
-  }
+  } // merge_point_list
 
   // compress the shell list
 
@@ -1838,6 +1843,7 @@
 
   // merge the points
   pt0->merge_points( pt1, CUBIT_TRUE );
+  //pt0->set_as_feature();
 
   if (mydebug)
   {
@@ -1880,6 +1886,7 @@
           {   
             nemerge++;
             edge_merged = true;
+            dedge->set_as_feature();
           }
         }
       }
@@ -2061,6 +2068,8 @@
         }
         if (on_boundary)
         {
+            //PRINT_INFO("Merging 'boundary' points.\n");
+            //if (pt->marked() > 0) pt->marked( -pt->marked() );
           unmerged_points.append(pt);
         }
         else
@@ -2199,6 +2208,42 @@
 
 }
 
+
+void FacetDataUtil::destruct_facet_no_delete(CubitFacet *facet_ptr)
+{
+  CubitFacetData* facet_d_ptr = dynamic_cast<CubitFacetData*>(facet_ptr);
+  if(!facet_d_ptr){
+    PRINT_ERROR("Can't work with Facet pointer that isn't a facet data object.\n");
+    return;
+  }
+  
+  DLIList<CubitPoint *>point_list;
+  DLIList<CubitFacetEdge *>edge_list;
+  facet_ptr->points(point_list);
+  facet_ptr->edges(edge_list);
+  
+  facet_d_ptr->destruct_facet_internals();
+
+  CubitFacetEdge *edge_ptr;
+  CubitPoint *point_ptr;
+  int ii;
+
+  for (ii=0; ii<edge_list.size(); ii++)
+  {
+    edge_ptr = edge_list.get_and_step();
+    if (edge_ptr->num_adj_facets() == 0)
+      delete edge_ptr;
+  }
+
+  for (ii=0; ii<3; ii++)
+  {
+    point_ptr = point_list.get_and_step();
+    if (point_ptr->num_adj_facets() == 0)
+      delete point_ptr;
+  }
+
+}
+
 //=============================================================================
 //Function:  intersect_facet (PUBLIC)
 //Description: determine intersection of a segment with a facet
@@ -2213,7 +2258,8 @@
   CubitVector &start, CubitVector &end, // start and end points of vector
   CubitFacet *facet_ptr,      // the facet to intersect
   CubitVector &qq,            // return the intersection point
-  CubitVector &ac)    // area coordinates of qq if is in or on facet
+  CubitVector &ac,    // area coordinates of qq if is in or on facet
+  CubitBoolean bound) // if true, only check for intersections between the end points.
 {
 
   CubitPlane fplane = facet_ptr->plane();
@@ -2240,14 +2286,13 @@
   }
 
   // points are both on the same side of the plane
-
-  else if(dstart*dend > 0.0)
+  else if(dstart*dend > 0.0 &&
+          (bound || fabs(dstart-dend) < CUBIT_RESABS) )
   {
     return CUBIT_PNT_OUTSIDE;
   }
+  // points are on opposite sides of plane: if bound == false then compute intersection with plane
 
-  // points ae on opposite sides of plane - compute intersection with plane
-
   else
   {
     CubitVector dir = end-start;
@@ -2256,13 +2301,25 @@
   }
 
   FacetEvalTool::facet_area_coordinate( facet_ptr, qq, ac );
-
-  if (fabs(ac.x()) < GEOMETRY_RESABS ||
-      fabs(ac.y()) < GEOMETRY_RESABS ||
-      fabs(ac.z()) < GEOMETRY_RESABS)
-  {
+   
+//mod mbrewer ... the original code would call a point
+    // on the boundary if any area coordinate was near
+    // zero, regardless of whether another area coordinate
+    // was negative... making it outside.
+//   if (fabs(ac.x()) < GEOMETRY_RESABS ||
+//       fabs(ac.y()) < GEOMETRY_RESABS ||
+//       fabs(ac.z()) < GEOMETRY_RESABS)
+//   {
+//     return CUBIT_PNT_BOUNDARY;
+//   }
+  if ( (fabs(ac.x()) < GEOMETRY_RESABS && (ac.y() > -GEOMETRY_RESABS &&
+                                           ac.z() > -GEOMETRY_RESABS) )||
+       (fabs(ac.y()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS &&
+                                           ac.z() > -GEOMETRY_RESABS) )||
+       (fabs(ac.z()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS &&
+                                           ac.y() > -GEOMETRY_RESABS) ) ){
     return CUBIT_PNT_BOUNDARY;
-  }
+  }   
   else if (ac.x() < 0.0 || ac.y() < 0.0 || ac.z() < 0.0)
   {
     return CUBIT_PNT_OUTSIDE;
@@ -2340,6 +2397,199 @@
   return p0 + (t/DdD)*(p1 - p0);
 }
 
+//=============================================================================
+//Function:  get_bbox_intersections (PUBLIC)
+//Description: Get the intersection of the line defined by point1 and point2 with
+//bbox.  Returns 0,1 or 2 for the number of intersections.  A line
+//in one of the planes of the box will return 0.  Returns -1 for failure.
+//Author mborden
+//Date: 04/05/07
+//=============================================================================
+int FacetDataUtil::get_bbox_intersections(CubitVector& point1,
+                                          CubitVector& point2,
+                                          const CubitBox& bbox,
+                                          CubitVector& intersection_1,
+                                          CubitVector& intersection_2)
+{
+  int debug = 0;
+  if( debug )
+  {
+    GfxDebug::draw_point( point1, CUBIT_RED );
+    GfxDebug::draw_point( point2, CUBIT_BLUE );
+    GfxDebug::flush();
+  }
+  
+  double coords[6];
+  coords[0] = bbox.min_x();
+  coords[1] = bbox.max_x();
+  coords[2] = bbox.min_y();
+  coords[3] = bbox.max_y();
+  coords[4] = bbox.min_z();
+  coords[5] = bbox.max_z();
 
+  DLIList<CubitVector*> intersections;
+  
+  int ii;
+  for( ii = 0; ii < 3; ii++ )
+  {
+      //Define four points for each plane.
+    double box_points[4][3];
+
+      //ii = 0 -> x-planes
+      //ii = 1 -> y_planes
+      //ii = 2 -> z_planes
+
+      //Only the coordinates for the plane we are in
+      //change.  The other two are constant for the
+      //jj loops below.
+    box_points[0][(ii + 1) % 3] = coords[((ii*2)+2) % 6];
+    box_points[1][(ii + 1) % 3] = coords[((ii*2)+3) % 6];
+    box_points[2][(ii + 1) % 3] = coords[((ii*2)+3) % 6];
+    box_points[3][(ii + 1) % 3] = coords[((ii*2)+2) % 6];
+
+    box_points[0][(ii + 2) % 3] = coords[((ii*2)+4) % 6];
+    box_points[1][(ii + 2) % 3] = coords[((ii*2)+4) % 6];
+    box_points[2][(ii + 2) % 3] = coords[((ii*2)+5) % 6];
+    box_points[3][(ii + 2) % 3] = coords[((ii*2)+5) % 6];
+      
+    int jj;
+    for( jj = 0; jj < 2; jj++ )
+    {
+      CubitPoint* points[4];
+      int kk;
+      for( kk = 0; kk < 4; kk++ )
+      {
+        box_points[kk][ii] = coords[(ii*2)+jj];
+        points[kk] = new CubitPointData( box_points[kk][0], box_points[kk][1], box_points[kk][2] );
+      }
+      
+        //Create two facets for this plane to check for intersections.
+      CubitFacet* facets[2];
+      facets[0] = new CubitFacetData( points[0], points[1], points[3] );
+      facets[1] = new CubitFacetData( points[1], points[2], points[3] );
+
+      for( kk = 0; kk < 2; kk++ )
+      {
+        CubitVector intersection;
+        CubitVector area_coord;
+
+          //Make sure the points are not parrellel with the facet.
+        CubitVector dir = point2 - point1;
+        CubitVector normal = facets[kk]->normal();
+        if( fabs(dir % normal) < CUBIT_RESABS )
+            continue;
+        
+        CubitPointContainment contain = intersect_facet( point1, point2, facets[kk],
+                                                         intersection, area_coord, CUBIT_FALSE );
+        if( CUBIT_PNT_UNKNOWN == contain )
+        {
+            //The points are in a plane.  Return 0.
+          delete facets[0];
+          delete facets[1];
+          int ll;
+          for( ll = 0; ll < 4; ll++ )
+              delete points[ll];
+          for( ll = intersections.size(); ll > 0; ll-- )
+              delete intersections.get_and_step();
+
+          return 0;
+        }
+        if( CUBIT_PNT_BOUNDARY == contain ||
+            CUBIT_PNT_INSIDE == contain )
+        {
+            //The point intersects the facet so it's inside the box's surface.
+          CubitVector* new_intersection = new CubitVector;
+          *new_intersection = intersection;
+          intersections.append( new_intersection );
+
+          if( debug )
+          {
+            GfxDebug::draw_point( *new_intersection, CUBIT_CYAN );
+            GfxDebug::flush();
+          }
+          
+          break;          
+        }
+      }
+      
+      delete facets[0];
+      delete facets[1];
+      for( kk = 0; kk < 4; kk++ )
+          delete points[kk];      
+    }
+  }
+
+    //Check for duplicate intersections.
+  intersections.reset();
+  for( ii = 0; ii < intersections.size(); ii++ )
+  {
+    CubitVector* base_vec = intersections.next(ii);
+    if( NULL == base_vec )
+        continue;
+    
+    int jj;
+    for( jj = ii+1; jj < intersections.size(); jj++ )
+    {
+      CubitVector* compare_vec = intersections.next(jj);
+      if( NULL != compare_vec )
+      {
+        if( base_vec->distance_between_squared( *compare_vec ) < GEOMETRY_RESABS * GEOMETRY_RESABS )
+        {
+          intersections.step(jj);
+          delete intersections.get();
+          intersections.change_to( NULL );
+          intersections.reset();
+        }
+      }
+    }
+  }
+  intersections.remove_all_with_value( NULL );
+
+  
+  if( intersections.size() > 2 )
+  {
+    assert( intersections.size() <= 2 );
+    return -1;
+  }
+  else if( intersections.size() > 0 )
+  {
+    intersection_1 = *intersections.get();
+    if( intersections.size() > 1 )
+        intersection_2 = *intersections.next();
+  }
+  
+    //Delete memory.
+  for( ii = intersections.size(); ii > 0; ii-- )
+      delete intersections.get_and_step();
+  
+  return intersections.size();
+}
+
+
+//=============================================================================
+//Function:  mark_facets (PUBLIC)
+//Description: mark facets and their children.  assumes facets have points and edges
+//Author sjowen
+//Date: 09/18/09
+//=============================================================================
+void FacetDataUtil::mark_facets( DLIList<FacetEntity *> &facet_list, int mark_value )
+{
+  int ifacet;
+  FacetEntity *facet_ptr;
+  CubitFacet *cfacet_ptr;
+  for (ifacet = 0; ifacet<facet_list.size(); ifacet++)
+  {
+    facet_ptr = facet_list.get_and_step();
+    cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
+    cfacet_ptr->marked(mark_value);
+    for (int ii=0; ii<3; ii++)
+    {
+      cfacet_ptr->point(ii)->marked(mark_value);
+      cfacet_ptr->edge(ii)->marked(mark_value);
+    }
+  }
+  
+}
+
 //EOF
 

Modified: cgm/branches/cubit/geom/Cholla/FacetDataUtil.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetDataUtil.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/FacetDataUtil.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -110,7 +110,7 @@
   static bool ray_intersects_boundingbox(CubitVector& point, CubitVector& ray, const CubitBox& bbox);
 
   // write a facet list to a facet file
-  static CubitStatus write_facets( char *file_name,
+  static CubitStatus write_facets( const char *file_name,
                                    DLIList<CubitFacet *> &facet_list);
 
   // group facets into continuous lists
@@ -128,6 +128,8 @@
   static void delete_facets(DLIList<DLIList<CubitFacet*>*> &shell_list);
   static void delete_facets(DLIList<CubitFacet*> &facet_list);
   static void delete_facet(CubitFacet *facet_ptr);
+  static void destruct_facet_no_delete(CubitFacet *facet_ptr);
+  
 
   // determine intersection of a segment with a facet
   // returns CUBIT_PNT_UNKNOWN: if segment is in plane of facet
@@ -135,9 +137,10 @@
   //         CUBIT_PNT_INSIDE: if segment intersects inside facet
   //         CUBIT_PNT_BOUNDARY: if segment intersects a vertex or edge
   static CubitPointContainment intersect_facet(CubitVector &start, CubitVector &end,
-                                                CubitFacet *facet_ptr,
-                                                CubitVector &qq,
-                                                CubitVector &ac);
+                                               CubitFacet *facet_ptr,
+                                               CubitVector &qq,
+                                               CubitVector &ac,
+                                               CubitBoolean bound = CUBIT_TRUE);
 
    //  get axis-aligned bounding box of list of points
   static CubitStatus get_bbox_of_points(DLIList<CubitPoint*>& point_list, CubitBox& bbox);
@@ -148,7 +151,19 @@
                                                   CubitVector &p0, 
                                                   CubitVector &p1,
                                                   double &distance2);
+
+  //  Get the intersection of the line defined by point1 and point2 with
+  //  bbox.  Returns 0,1 or 2 for the number of intersections.  A line
+  //  in one of the planes of the box will return 0.
+  static int get_bbox_intersections(CubitVector& point1,
+                                    CubitVector& point2,
+                                    const CubitBox& bbox,
+                                    CubitVector& intersection_1,
+                                    CubitVector& intersection_2);
   
+  // mark facets and their children
+  static void mark_facets( DLIList<FacetEntity *> &facet_list, int mark_value );
+  
 private:
 
  // used with split_into_shells to group facets

Modified: cgm/branches/cubit/geom/Cholla/FacetEvalTool.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetEvalTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/FacetEvalTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -23,6 +23,7 @@
 #include "debug.hpp"
 #include "TDFacetBoundaryEdge.hpp"
 #include "TDFacetBoundaryPoint.hpp"
+#include "TDGeomFacet.hpp"
 #include "GfxDebug.hpp"
 //#include "FacetParamTool.hpp"
 #include "KDDTree.hpp"
@@ -529,7 +530,6 @@
 //===========================================================================
 CubitStatus FacetEvalTool::mark_edge_pairs(CubitPoint* point)
 {
-  CubitStatus status = CUBIT_SUCCESS;
   int i,j;
   DLIList<CubitFacetEdge*> edge_list;
   DLIList<CubitFacetEdge*> edge_list_init;
@@ -1319,7 +1319,7 @@
 CubitStatus FacetEvalTool::project_to_patch(
   CubitFacet *facet,     // (IN) the facet where the patch is defined                                                
   CubitVector &ac,       // (IN) area coordinate initial guess (from linear facet)
-  CubitVector &pt,       // (IN) point we are projecting to patch
+  const CubitVector &pt,       // (IN) point we are projecting to patch
   CubitVector &eval_pt,  // (OUT) The projected point
   CubitVector *eval_norm, // (OUT) normal at evaluated point
   CubitBoolean &outside, // (OUT) the closest point on patch to pt is on an edge
@@ -1606,7 +1606,7 @@
 //===========================================================================
 CubitBoolean FacetEvalTool::is_at_vertex( 
   CubitFacet *facet,  // (IN) facet we are evaluating 
-  CubitVector &pt,    // (IN) the point
+  const CubitVector &pt,    // (IN) the point
   CubitVector &ac,    // (IN) the ac of the point on the facet plane
   double compare_tol, // (IN) return TRUE of closer than this
   CubitVector &eval_pt, // (OUT) location at vertex if TRUE
@@ -2033,7 +2033,7 @@
                                        //      4 = b-spline patches
   double compare_tol,                  // (IN) tolerance for projection - 
                                        //      should be about 1e-3*edge
-  CubitVector &this_point,             // (IN) point we are projecting
+  const CubitVector &this_point,       // (IN) point we are projecting
   CubitBoolean trim,                   // (IN) trim to facet (always trimmed 
                                        //      if b-spline patch)
   CubitBoolean *outside,               // (OUT) TRUE if projected outside 
@@ -2539,7 +2539,7 @@
 //              a starting guess.
 //===========================================================================
 CubitStatus FacetEvalTool::project_to_facet( CubitFacet *facet, 
-                                       CubitVector &pt,
+                                       const CubitVector &pt,
                                        CubitVector &areacoord, 
                                        CubitVector &close_point,
                                        CubitBoolean &outside_facet,
@@ -2596,7 +2596,7 @@
 //===========================================================================
 CubitStatus FacetEvalTool::project_to_facetedge( CubitFacet *facet, 
                                       int vert0, int vert1,
-                                      CubitVector &the_point,
+                                      const CubitVector &the_point,
                                       CubitVector &pt_on_plane, 
                                       CubitVector &close_point,
                                       CubitBoolean &outside_facet,
@@ -2999,7 +2999,7 @@
 //===========================================================================
 void FacetEvalTool::project_to_facet_plane(
   CubitFacet *facet,
-  CubitVector &pt,
+  const CubitVector &pt,
   CubitVector &point_on_plane,
   double &dist_to_plane)
 {
@@ -3029,7 +3029,7 @@
 //===========================================================================
 void FacetEvalTool::facet_area_coordinate( 
   CubitFacet *facet,
-  CubitVector &pt_on_plane,
+  const CubitVector &pt_on_plane,
   CubitVector &areacoord )
 {
   double area2;
@@ -3924,16 +3924,16 @@
 //===========================================================================
 CubitBoolean FacetEvalTool::is_boundary_facet( CubitFacet *facet_ptr )
 {
-  TDFacetBoundaryEdge *td_fbe = NULL;
-  TDFacetBoundaryPoint *td_fbp = NULL;
+  TDGeomFacet *td_fbe = NULL;
+  TDGeomFacet *td_fbp = NULL;
   int ii;
   for (ii=0; ii<3; ii++)
   {
-    td_fbe = TDFacetBoundaryEdge::get_facet_boundary_edge( facet_ptr->edge( ii ) );
-    if (td_fbe != NULL)
+    td_fbe = TDGeomFacet::get_geom_facet( facet_ptr->edge( ii ) );
+    if ( td_fbe->on_boundary() )
       return CUBIT_TRUE;
-    td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( facet_ptr->point( ii ) );
-    if (td_fbp != NULL)
+    td_fbp = TDGeomFacet::get_geom_facet( facet_ptr->point( ii ) );
+    if ( td_fbe->on_boundary() )
       return CUBIT_TRUE;
   }
   return CUBIT_FALSE;
@@ -4338,3 +4338,255 @@
 
   return CUBIT_SUCCESS;
 }
+
+CubitStatus FacetEvalTool::get_intersections(CubitVector point1,
+                                             CubitVector point2,
+                                             DLIList<CubitVector*>& intersection_list,
+                                             bool bounded)
+{
+    //Find the points were the line intersects the bounding box.
+  CubitVector intersect_1;
+  CubitVector intersect_2;
+  CubitBox bbox = *myBBox;
+
+    //Increase the size of the box in each direction.
+    //Don't use scale because the box may be too thin (planar surface).
+  double offset = 2.0 * (point1 - point2).length();
+  
+  CubitVector min;
+  min.x( bbox.min_x() - offset );
+  min.y( bbox.min_y() - offset );
+  min.z( bbox.min_z() - offset );
+  CubitVector max;
+  max.x( bbox.max_x() + offset );
+  max.y( bbox.max_y() + offset );
+  max.z( bbox.max_z() + offset );
+
+  bbox.reset( min, max );
+  int box_intersections = FacetDataUtil::get_bbox_intersections( point1, point2, bbox,
+                                                                 intersect_1, intersect_2 );
+
+    //The bounding box is larger than the surface we are checking.
+    //This means that if there are less than two intersections
+    //the line will not intersect the surface.
+  if( 2 > box_intersections )
+      return CUBIT_SUCCESS;
+
+  bbox.reset( intersect_1 );
+  bbox |= intersect_2;
+  
+    //Find the facets that are intersected by the bbox that was just created.
+  DLIList<CubitFacet*> search_facets;
+  if( aTree )
+  {
+      //Get the facets from the tree.
+    aTree->find( bbox, search_facets );
+  }
+  else
+      search_facets = myFacetList;
+
+  int ii;
+  for( ii = search_facets.size(); ii > 0; ii-- )
+  {
+    CubitFacet* test_facet = search_facets.get_and_step();
+
+    CubitVector intersection;
+    CubitVector area_coord;
+    CubitPointContainment contain = FacetDataUtil::intersect_facet( intersect_1, intersect_2, test_facet,
+                                                                    intersection, area_coord );
+
+    if( bounded )
+    {
+      CubitVector dir1 = point2 - point1;
+      CubitVector dir2 = intersection - point1;
+
+      if( dir2.length_squared() > (GEOMETRY_RESABS * GEOMETRY_RESABS) )
+      {
+        if( dir1 % dir2 < 0 ||
+            ( ( dir2.length_squared() - dir1.length_squared() ) >
+              ( GEOMETRY_RESABS * GEOMETRY_RESABS ) ) )
+        {
+            //The inserction point is not between the two end points.
+          contain = CUBIT_PNT_OUTSIDE;
+        }
+      }
+    }
+    
+    if( CUBIT_PNT_BOUNDARY == contain ||
+        CUBIT_PNT_INSIDE == contain )
+    {
+        //The point intersects the facets.
+      CubitVector* new_intersection = new CubitVector;
+      *new_intersection = intersection;
+      intersection_list.append( new_intersection );
+    }
+  }
+
+    //Remove duplicate intersections.
+  intersection_list.reset();
+  for( ii = 0; ii < intersection_list.size(); ii++ )
+  {
+    CubitVector* base_vec = intersection_list.next(ii);
+    if( NULL == base_vec )
+        continue;
+    
+    int jj;
+    for( jj = ii+1; jj < intersection_list.size(); jj++ )
+    {
+      CubitVector* compare_vec = intersection_list.next(jj);
+      if( NULL != compare_vec )
+      {
+        if( base_vec->distance_between_squared( *compare_vec ) < GEOMETRY_RESABS * GEOMETRY_RESABS )
+        {
+          intersection_list.step(jj);
+          delete intersection_list.get();
+          intersection_list.change_to( NULL );
+          intersection_list.reset();
+        }
+      }
+    }
+  }
+  intersection_list.remove_all_with_value( NULL );
+  
+  return CUBIT_SUCCESS;
+}
+
+int FacetEvalTool::intersect_ray( CubitVector &origin, CubitVector &direction, CubitFacet* facet, CubitVector* point, double &distance )
+{
+	// This algorithm can be found at http://geometryalgorithms.com/
+
+	CubitVector n;           // triangle vectors
+    CubitVector w0, w;       // ray vectors
+    double a, b;             // params to calc ray-plane intersect
+
+    // get triangle edge vectors and plane normal
+	CubitVector normal = facet->normal();
+	CubitPoint *pt0 = facet->point(0);
+	CubitPoint *pt1 = facet->point(1);
+	CubitPoint *pt2 = facet->point(2);
+	double tol = GEOMETRY_RESABS;
+	
+	CubitVector u( pt1->x() - pt0->x(),
+					pt1->y() - pt0->y(),
+					pt1->z() - pt0->z()); //(*p1-*p0);
+	CubitVector v( pt2->x() - pt0->x(),
+					pt2->y() - pt0->y(),
+					pt2->z() - pt0->z()); // = (*p2-*p0);
+
+	//u = T.V1 - T.V0;
+    //v = T.V2 - T.V0;
+    n = u * v;             // cross product
+    if (n.length_squared() == 0)   // triangle is degenerate
+        return -1;                 // do not deal with this case
+
+    //dir = R.P1 - R.P0;             // ray direction vector
+    //w0 = R.P0 - T.V0;
+	w0 = CubitVector(origin.x() - pt0->x(),
+		origin.y() - pt0->y(),
+		origin.z() - pt0->z());
+
+    a = -(n%w0);
+    b = (n%direction);
+    if (fabs(b) < tol) {     // ray is parallel to triangle plane
+        if (a == 0)                // ray lies in triangle plane
+            return 2;
+        else return 0;             // ray disjoint from plane
+    }
+
+    // get intersect point of ray with triangle plane
+    distance = a / b;
+    if (distance < 0.0)                   // ray goes away from triangle
+        return 0;                  // => no intersect
+    // for a segment, also test if (r > 1.0) => no intersect
+
+    point->set(origin + distance * direction);           // intersect point of ray and plane
+
+    // the distance we want to return is real distance, not distance/magnitude
+    distance *= direction.length();
+
+    // is point inside facet?
+    double uu, uv, vv, wu, wv, D;
+    uu = u%u;
+    uv = u%v;
+    vv = v%v;
+    //w = *I - T.V0;
+	w = CubitVector(point->x() - pt0->x(),
+					point->y() - pt0->y(),
+					point->z() - pt0->z());
+    wu = w%u;
+    wv = w%v;
+    D = uv * uv - uu * vv;
+
+    // get and test parametric coords
+    double s, t;
+    s = (uv * wv - vv * wu) / D;
+    if (s < 0.0 || s > 1.0)        // point is outside facet
+        return 0;
+    t = (uv * wu - uu * wv) / D;
+    if (t < 0.0 || (s + t) > 1.0)  // point is outside facet
+        return 0;
+
+    return 1;                      // point is in facet
+
+}
+
+int FacetEvalTool::intersect_ray( CubitVector &origin, CubitVector &direction, CubitFacetEdge* facet_edge, CubitVector* point, double &hit_distance )
+{
+	// This algorithm can be found at http://geometryalgorithms.com/
+	double tol = GEOMETRY_RESABS;
+
+	CubitPoint* p0 = facet_edge->point(0);
+	CubitPoint* p1 = facet_edge->point(1);
+	CubitVector u0 = CubitVector(p0->x(), p0->y(), p0->z());
+    CubitVector u1 = CubitVector(p1->x(), p1->y(), p1->z());
+	
+	CubitVector u = CubitVector(u0, u1);
+	CubitVector v = direction;
+	v.normalize();
+
+	CubitVector w = CubitVector(origin, u0);
+
+	double sc, tc;         // sc is fraction along facet edge, tc is distance along ray
+	
+	double a = u%u;        // always >= 0
+    double b = u%v;
+    double c = v%v;        // always >= 0
+    double d = u%w;
+    double e = v%w;
+    double D = a*c - b*b;  // always >= 0
+
+    // compute the line parameters of the two closest points
+    if (D < tol)
+	{
+		// the lines are almost parallel
+        sc = 0.0;
+        tc = (b>c ? d/b : e/c);   // use the largest denominator
+    }
+    else
+	{
+        sc = (b*e - c*d) / D;
+        tc = (a*e - b*d) / D;
+    }
+
+    // get the difference of the two closest points
+    CubitVector dP = CubitVector(w + (sc * u) - (tc * v));  // = <0 0 0> if intersection
+
+    double distance = sqrt(dP % dP); // return the closest distance (0 if intersection)
+
+	point->set(u0 + (sc * u));
+	hit_distance = tc; //distance from origin to intersection point
+
+	if (distance < tol)
+	{
+		//check if parallel (infinite intersection)
+		if (D < tol)
+			return 2;
+		//check if on edge
+		if (sc <= 1.0 && sc >= 0.0)
+			return 1;
+		else
+			return 0;
+	}
+
+	return 0;
+}

Modified: cgm/branches/cubit/geom/Cholla/FacetEvalTool.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetEvalTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/FacetEvalTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -79,8 +79,6 @@
                                     DLIList<CubitFacetEdge*> &edge_list );
     //- populates the edge_list with edges contained by the given facets
 
-  CubitStatus get_loops_from_facets(DLIList<CubitFacetEdge*> &all_edge_list,
-                                    DLIList<DLIList<CubitFacetEdge*>*> &loop_list );
     //- populates the loop_list with edges contained by the given edge list
   void destroy_facets();
     //- Destroys the facets, and points.
@@ -152,7 +150,7 @@
                                 CubitVector Nijk[10] );
   static CubitStatus project_to_patch( CubitFacet *facet,                                                
                                 CubitVector &ac,
-                                CubitVector &pt,
+                                const CubitVector &pt,
                                 CubitVector &eval_pt,
                                 CubitVector *eval_norm,
                                 CubitBoolean &outside,
@@ -169,7 +167,7 @@
     //- determine the area coordinate of the facet at the edge
 
   static CubitBoolean is_at_vertex( CubitFacet *facet,
-                                    CubitVector &pt,
+                                    const CubitVector &pt,
                                     CubitVector &ac,
                                     double compare_tol,
                                     CubitVector &eval_pt,
@@ -270,7 +268,7 @@
     //- the facet area coordinates
 
   static CubitStatus project_to_facet( CubitFacet *facet, 
-                                       CubitVector &pt,
+                                       const CubitVector &pt,
                                        CubitVector &areacoord,
                                        CubitVector &close_point,
                                        CubitBoolean &outside,
@@ -282,7 +280,7 @@
                                  CubitFacet *&last_facet,
                                  int interp_order,
                                  double compare_tol,
-                                 CubitVector &this_point,
+                                 const CubitVector &this_point,
                                  CubitBoolean trim,
                                  CubitBoolean *outside,
                                  CubitVector *closest_point_ptr,
@@ -296,7 +294,7 @@
                          CubitVector &close_point);
   static CubitStatus project_to_facetedge( CubitFacet *facet, 
                          int vert0, int vert1,
-                         CubitVector &the_point,
+                         const CubitVector &the_point,
                          CubitVector &pt_on_plane, 
                          CubitVector &close_point,
                          CubitBoolean &outside_facet, 
@@ -315,13 +313,13 @@
     //- evaluate the normal on a facet (use the interpOrder)
 
   static void project_to_facet_plane( CubitFacet *facet,
-                               CubitVector &pt,
+                               const CubitVector &pt,
                                CubitVector &point_on_plane,
                                double &dist );
     //- project a point to the plane of a facet
 
   static void facet_area_coordinate( CubitFacet *facet,
-                                     CubitVector &pt_on_plane,
+                                     const CubitVector &pt_on_plane,
                                      CubitVector &areacoord );
     //- define the area coordinates of a point on a plane of the facet
 
@@ -405,6 +403,39 @@
   static CubitFacetEdge *next_boundary_edge( CubitFacetEdge *this_edge, CubitPoint *p0 );
     //- return the next edge on the boundary
 
+  CubitStatus get_intersections(CubitVector point1,
+                                CubitVector point2,
+                                DLIList<CubitVector*>& intersection_list,
+                                bool bounded = CUBIT_FALSE);
+
+
+  // The following copyright applies to the following two functions...
+  //
+  // Copyright 2001, softSurfer (www.softsurfer.com)
+  //
+  // This code may be freely used and modified for any purpose
+  // providing that this copyright notice is included with it.
+  // SoftSurfer makes no warranty for this code, and cannot be held
+  // liable for any real or imagined damage resulting from its use.
+  // Users of this code must verify correctness for their application.
+
+  static int intersect_ray( CubitVector &origin, CubitVector &direction, CubitFacet* facet, CubitVector* point, double &distance );
+    //- Find intersection point of a ray and a facet
+    //    Return: -1 = triangle is degenerate (a segment or point)
+    //             0 = disjoint (no intersect)
+    //             1 = intersect at unique point
+    //             2 = are in the same plane
+
+  static int intersect_ray( CubitVector &origin, CubitVector &direction, CubitFacetEdge* facet, CubitVector* point, double &distance );
+    //- Find intersection point of a ray and a facet edge
+    //    Return: -1 = edge is degenerate (a point)
+    //             0 = disjoint (no intersect)
+    //             1 = intersect at unique point
+    //             2 = are the same line (infinite points)
+
+  
+  CubitStatus get_loops_from_facets(DLIList<CubitFacetEdge*> &all_edge_list,
+                                    DLIList<DLIList<CubitFacetEdge*>*> &loop_list );
 };
 
 #endif // SMOOTH_FACET_EVAL_TOOL_HPP

Modified: cgm/branches/cubit/geom/Cholla/FacetorTool.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetorTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/FacetorTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -18,6 +18,7 @@
 #endif
 
 #include "FacetorTool.hpp"
+#include "FacetorUtil.hpp"
 #include "TDDelaunay.hpp"
 #include "BoundaryConstrainTool.hpp"
 #include "CubitPoint.hpp"
@@ -31,9 +32,7 @@
      ((q3)*((p2)-(p1)) + (q2)*((p1)-(p3)) + (q1)*((p3)-(p2)))
 #define SQR(x) ((x) * (x))
 #define FT_INSIDE_TOL 1.0e-6
-#define NUM_SORT_LISTS 64
 #define QUALITY_ANGLE 0.361283155162   /* 20.7 degrees */
-#define INTERVAL (QUALITY_ANGLE/(NUM_SORT_LISTS-1))
 #define ALPHA 0.70228615
 
 //-------------------------------------------------------------------------
@@ -62,9 +61,7 @@
   sizingFunction = sizing_function;
 
   curVisitFlag = INT_MIN+1;
-  lastTriLocated = NULL;
   boxNodes[0] = boxNodes[1] = boxNodes[2] = boxNodes[3] = NULL;
-  triSortArray = NULL;
 }
 
 
@@ -78,8 +75,6 @@
 FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::~FacetorTool()
 {
   numBoundaryEdges = 0;
-  if (triSortArray != NULL)
-    delete [] triSortArray;
 }
 
 
@@ -305,129 +300,8 @@
   return CUBIT_SUCCESS;
 }
 
-//-------------------------------------------------------------------------
-// Function:    circumcenter
-// Description: get the circumcenter of the triangle
-// Author:      chynes
-// Date:        6/6/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitVector &FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::circumcenter( TRI *tri_ptr )
-{
-	ToolData *td = tri_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
-	TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
-	if(td_del == NULL) {
-		td_del = new TDDelaunay<TRI, NODE>();
-		tri_ptr->add_TD( td_del );
-	}
-	return td_del->circumcenter2d( tri_ptr );
-}
 
-
 //-------------------------------------------------------------------------
-// Function:    radius
-// Description: get the radius squared of the triangle circumcircle
-// Author:      chynes
-// Date:        6/6/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-double FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::radius( TRI *tri_ptr )
-{
-  ToolData *td = tri_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
-  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
-  if (td_del == NULL)
-  {
-    td_del = new TDDelaunay< TRI, NODE >();
-    tri_ptr->add_TD( td_del );
-  }
-  return td_del->radius2d( tri_ptr );
-}
-
-//-------------------------------------------------------------------------
-// Function:    tri_visited
-// Description: set the tri_visited flag
-// Author:      chynes
-// Date:        6/6/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitBoolean FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_visited( TRI *tri_ptr )
-{
-  ToolData *td = tri_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
-  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
-  if (td_del == NULL)
-  {
-    td_del = new TDDelaunay< TRI, NODE >();
-    tri_ptr->add_TD( td_del );
-  }
-  return (td_del->visit_flag() == curVisitFlag);
-}
-
-//-------------------------------------------------------------------------
-// Function:    tri_visited
-// Description: set the tri_visited flag
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-void FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::
-tri_visited( TRI *facet_ptr, CubitBoolean visited )
-{
-  ToolData *td = facet_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
-  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
-  if (td_del == NULL)
-  {
-    td_del = new TDDelaunay< TRI, NODE >();
-    facet_ptr->add_TD( td_del );
-  }
-  if (visited)
-    td_del->visit_flag(curVisitFlag);
-  else
-    td_del->visit_flag(INT_MIN);
-}
-
-
-//-------------------------------------------------------------------------
-// Function:    tri_sort_list
-// Description: set the tri sort list index
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-void FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_sort_list( TRI *facet_ptr, 
-                                     int sort_list_index )
-{
-  ToolData *td = facet_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
-  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
-  if (td_del == NULL)
-  {
-    td_del = new TDDelaunay<TRI, NODE>();
-    facet_ptr->add_TD( td_del );
-  }
-  td_del->tri_sort_list(sort_list_index);
-}
-
-
-//-------------------------------------------------------------------------
-// Function:    tri_sort_list
-// Description: get the tri sort list index
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-int FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_sort_list( TRI *facet_ptr )
-{
-  ToolData *td = facet_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
-  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
-  if (td_del == NULL)
-  {
-    td_del = new TDDelaunay<TRI, NODE>();
-    facet_ptr->add_TD( td_del );
-  }
-  return td_del->tri_sort_list();
-}
-
-
-//-------------------------------------------------------------------------
 // Function:    insert_nodes
 // Description: insert nodes into Delaunay mesh
 // Author:      chynes
@@ -440,9 +314,13 @@
   CubitStatus rv = CUBIT_SUCCESS;
   int ii;
   NODE *point_ptr;
+  TRI* start_tri = NULL;
   for (ii=0; ii<bounding_nodes->size() && rv == CUBIT_SUCCESS; ii++){
     point_ptr = bounding_nodes->get_and_step();
-    rv = insert_node( point_ptr );
+    rv = FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::insert_node(
+                                                                point_ptr, *facetList,
+                                                                refFacePtr, curVisitFlag,
+                                                                start_tri);
   }
 
   
@@ -451,463 +329,6 @@
 
 
 //-------------------------------------------------------------------------
-// Function:    insert_node
-// Description: insert one node into Delaunay mesh
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::insert_node( NODE *node_ptr )
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-  // get a list of all triangles whose circumcircle contain the point
-  
-  DLIList<TRI *> tri_list;
-  CubitVector the_point = node_ptr->coordinates();
-  rv = natural_neighbor_tris( the_point, tri_list );
-
-
-  // Use a Bowyer-Watson insertion 
-  
-  if (rv == CUBIT_SUCCESS)
-  {
-    rv = bowyer_watson_insert( node_ptr, tri_list );
-  }
-
-  return rv;
-}
-
-
-//-------------------------------------------------------------------------
-// Function:    bowyer_watson_insert
-// Description: Bowyer-Watson insertion into an existing Delaunay Mesh
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::bowyer_watson_insert( NODE *point_ptr,
-					       DLIList<TRI *> &tri_list)
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-   // mark the tris in the list so we can distinguish them from their 
-  // neighbors
-
-  curVisitFlag++;
-  int ii, jj;
-  TRI *tri_ptr;
-  for (ii=0; ii<tri_list.size(); ii++)
-  {
-    tri_ptr = tri_list.get_and_step();
-    tri_visited( tri_ptr, CUBIT_TRUE );
-  }
-    //MBREWER:  This is not an optimal test.  But, we need need to 
-    //do some tests to try to ensure that the void is valid for what
-    //we need.  This is attempting to avoid crashes by not allowing nodes
-    //to be inserted when the mesh starts diverging from the Delaunay
-    //criteria.
-  rv = valid_void( point_ptr, tri_list );
-  if(!rv)
-    return rv;
-  
-  // find all edges at the boundary of the visited triangles and create
-  // new triangles with them
-
-  // create a new triangle with this edge and the node
-  TRI *adjtri_ptr;
-  TRI *new_tri = NULL;
-  EDGE *edge_ptr;
-  DLIList<EDGE *> edge_list;
-  for (ii=0; ii<tri_list.size(); ii++)
-  {
-    tri_ptr = tri_list.get_and_step();
-    for (jj=0; jj<3; jj++){
-      
-      int kk = jj;
-        // - if TRI == CubitFacet
-        // - kk will be corrected in adjacent() to 
-        // - give the correct EDGE index
-      adjtri_ptr = tri_ptr->adjacent( kk, refFacePtr );
-      if (!adjtri_ptr || !tri_visited( adjtri_ptr ))
-      {
-        edge_ptr = tri_ptr->edge(kk);
-        assert(edge_list.append_unique( edge_ptr ));
-        if(tri_ptr->sense(kk) == CUBIT_FORWARD)
-          new_tri = (TRI *) new TRICHILD( edge_ptr->start_node(), edge_ptr->end_node(), point_ptr, refFacePtr);
-        else
-          new_tri = (TRI *) new TRICHILD( edge_ptr->end_node(), edge_ptr->start_node(), point_ptr, refFacePtr);
-        facetList->append(new_tri);
-      }
-    }
-  }
-  lastTriLocated = new_tri;
-
-  // delete the triangles in the original triangle list
-
-  EDGE *del_edge_ptr;
-  DLIList<EDGE *> del_edge_list;
-  for (ii=0; ii<tri_list.size(); ii++)
-  {
-    tri_ptr = tri_list.get_and_step();
-    del_edge_list.clean_out();
-    facetList->move_to(tri_ptr);
-    facetList->extract();
-    tri_ptr->edges( del_edge_list );
-    delete tri_ptr;
-
-      // delete the unused edges
-    for (jj=0; jj<del_edge_list.size(); jj++)
-    {
-      del_edge_ptr = del_edge_list.get_and_step();
-      if (del_edge_ptr->number_tris() == 0 && del_edge_ptr->number_faces() == 0 )
-        delete del_edge_ptr;
-    }
-  }
-
-  return rv;
-}
-/************************************************************/
-//author:  mbrewer
-//This function performs tests on the void created by a point's
-//insertion to make sure that invalid connectivities are not
-//being created.  
-/************************************************************/
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::valid_void( NODE * /*point_ptr*/,
-					       DLIList<TRI *> &tri_list)
-{
-  int temp_i, temp_j;
-  DLIList<EDGE*> boundary_edge_list;
-  DLIList<NODE*> boundary_node_list;
-  TRI *adjtri_ptr;
-  TRI *tri_ptr;
-  EDGE *edge_ptr;
-  DLIList<EDGE *> edge_list;
-    //loop over the tri's in tri_list and find all of the curves
-    //on the boundary of the set (ie, on the boundary of the void). 
-  for (temp_i=0; temp_i<tri_list.size(); temp_i++)
-  {
-    tri_ptr = tri_list.get_and_step();
-      //check each edge to see whether it is a boundary edge or not
-    for (temp_j=0; temp_j<3; temp_j++){
-      
-      int kk = temp_j;
-        // - if TRI == CubitFacet
-        // - kk will be corrected in adjacent() to 
-        // - give the correct EDGE index
-      adjtri_ptr = tri_ptr->adjacent( kk, refFacePtr );
-      if (!adjtri_ptr || !tri_visited( adjtri_ptr ))
-      {
-        edge_ptr = tri_ptr->edge(kk);
-        boundary_edge_list.append(edge_ptr);
-      }
-    }
-  }
-  int list_size = boundary_edge_list.size();
-    //uniquify the boundary edge list
-  boundary_edge_list.uniquify_unordered();
-    //the list shouldn't have changed size during the uniquify.
-    //if it did, there is a problem.
-  if(list_size != boundary_edge_list.size()){
-    PRINT_WARNING("Unexpected result.  Edge was duplicated on boundary.\n");
-    return CUBIT_FAILURE;
-  }
-    //loop over the boundary edges and get the nodes in the boundary loop
-  for(temp_i=0; temp_i<list_size; ++temp_i){
-    edge_ptr=boundary_edge_list.get_and_step();
-    boundary_node_list.append(edge_ptr->end_node());
-    boundary_node_list.append(edge_ptr->start_node());
-  }
-  list_size = boundary_node_list.size();
-    //each node should be in exactly two edges.  First make sure that there
-    //are the correct number of nodes.
-  if(list_size%2){
-    PRINT_WARNING("Unexpected result.  Node not listed twice.\n");
-    return CUBIT_FAILURE;
-  }
-    //now uniquify to make sure that the nodes were listed the correct number
-    //of times.  
-  boundary_node_list.uniquify_unordered();
-  if( (list_size/2) != boundary_node_list.size()){
-    PRINT_WARNING("Unexpected result.  Node was listed an incorrect number of times.\n");
-    return CUBIT_FAILURE;
-  }
-  return CUBIT_SUCCESS;
-  
-}
-
-//-------------------------------------------------------------------------
-// Function:    natural_neighbor_tris
-// Description: get a list of all triangles whose circumcircle contain 
-//              the point
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::natural_neighbor_tris(
-  CubitVector &the_point,
-  DLIList <TRI *> &tri_list)
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-  // find the triangle the point is contained in
-
-  //CubitVector areacoord;
-  TRI *tri_ptr;
-  rv = locate_point( the_point, tri_ptr );
-
-  // keep track of visitation to triangles by incrementing curVisitFlag
-  // and comparing with the visit flag stored with the triangle
-
-  curVisitFlag++;
-
-  // Recursively search, (starting with the tri the point is in)
-  // search for all tris whose circumcircle contain the point and place 
-  // in the tri_list 
-
-  if (rv == CUBIT_SUCCESS)
-  {
-    tri_list.append( tri_ptr );
-    tri_visited( tri_ptr, CUBIT_TRUE );
-    int iedge;
-    TRI *adjtri_ptr;
-    for (iedge=0; iedge<3 && rv == CUBIT_SUCCESS; iedge++)
-	{
-      int ii = iedge;
-      adjtri_ptr = tri_ptr->adjacent( ii, refFacePtr );
-      if (adjtri_ptr != NULL && !tri_visited( adjtri_ptr )){
-		rv = point_in_circumcircle( the_point, adjtri_ptr, tri_list );
-      }
-    }
-  }
-  return rv;
-}
-
-
-//-------------------------------------------------------------------------
-// Function:    locate_point
-// Description: return the triangle the point is located in
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::locate_point( CubitVector &the_point,
-				       TRI *&tri_ptr )
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-  // start with the last one found
-
-  if (lastTriLocated != NULL)
-    tri_ptr = lastTriLocated;
-
-  // otherwise use the first one on the list
-
-  else
-  {
-    tri_ptr = facetList->get();
-  }
-
-
-  // loop until we find something
-
-  NODE *n0, *n1, *n2;
-  double aa, bb, cc;
-  CubitBoolean found = CUBIT_FALSE;
-
-  //avoiding infinite loop
-  int counter = 0;
-  int max_count = facetList->size();
-  
-  while(!found && rv == CUBIT_SUCCESS)
-  {
-    tri_ptr->tri_nodes( n0, n1, n2 );
-    aa = DETERM(the_point.x(), the_point.y(),
-                n1->coordinates().x(), n1->coordinates().y(),
-                n2->coordinates().x(), n2->coordinates().y());
-    bb = DETERM(n0->coordinates().x(), n0->coordinates().y(),
-                the_point.x(), the_point.y(),
-                n2->coordinates().x(), n2->coordinates().y());
-    cc = DETERM(n0->coordinates().x(), n0->coordinates().y(),
-                n1->coordinates().x(), n1->coordinates().y(),
-                the_point.x(), the_point.y());
-    if (aa > -FT_INSIDE_TOL &&
-        bb > -FT_INSIDE_TOL &&
-        cc > -FT_INSIDE_TOL)
-    {
-      found = CUBIT_TRUE;  // this is the one
-    }
-    else
-    {
-      // set up to check the next logical neighbor
-      if (aa <= bb && aa <= cc) 
-	  {
-		int edge_index = 1;
-		tri_ptr = tri_ptr->adjacent( edge_index, refFacePtr );
-      }
-      else if (bb <= aa && bb <= cc) 
-	  {
-		int edge_index = 2;
-		tri_ptr = tri_ptr->adjacent( edge_index, refFacePtr );
-      }
-      else 
-	  {
-		int edge_index = 0;
-		tri_ptr = tri_ptr->adjacent( edge_index, refFacePtr );
-      }
-      // check to see if we've left the triangulation
-      // also make sure that we are not stuck in a cycle
-      if (tri_ptr == NULL || counter > max_count)
-      {
-        if(counter>max_count){
-          PRINT_WARNING("Encountered problem locating a triangle; going to exhaustive search.\n");
-        }
-        rv = exhaustive_locate_point(the_point, tri_ptr );
-        found = CUBIT_TRUE;
-      }
-    }
-    ++counter;
-  }
-  
-  lastTriLocated = tri_ptr;
-
-  return rv;
-}
-
-//-------------------------------------------------------------------------
-// Function:    exhaustive_locate_point
-// Description: return the triangle the point is located in by checking 
-//              all triangles
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::exhaustive_locate_point(
-  CubitVector &the_point,
-  TRI *&tri_ptr )
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-  
-  // loop until we find something
-
-  int ii;
-  NODE *n0, *n1, *n2;
-  double aa, bb, cc;
-  CubitBoolean found = CUBIT_FALSE;
-  for (ii=0; ii<facetList->size() && !found; ii++)
-  {
-    tri_ptr = facetList->get_and_step();
-    tri_ptr->tri_nodes( n0, n1, n2 );
-    aa = DETERM(the_point.x(), the_point.y(),
-                n1->coordinates().x(), n1->coordinates().y(),
-                n2->coordinates().x(), n2->coordinates().y());
-    bb = DETERM(n0->coordinates().x(), n0->coordinates().y(),
-                the_point.x(), the_point.y(),
-                n2->coordinates().x(), n2->coordinates().y());
-    cc = DETERM(n0->coordinates().x(), n0->coordinates().y(),
-                n1->coordinates().x(), n1->coordinates().y(),
-                the_point.x(), the_point.y());
-    if (aa > -FT_INSIDE_TOL &&
-        bb > -FT_INSIDE_TOL &&
-        cc > -FT_INSIDE_TOL)
-    {
-      found = CUBIT_TRUE;  // this is the one
-    }
-  }
-  if (!found)
-  {
-    rv = CUBIT_FAILURE;
-    tri_ptr = NULL;
-  }
-
-  return rv;
-}
-
-//-------------------------------------------------------------------------
-// Function:    are_nodes_colinear
-// Description: determine if the TRI is valid
-// Author:      mbrewer
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitBoolean FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::are_nodes_colinear( TRI *tri_ptr )
-{
-  NODE *nodes[3];
-  tri_ptr->tri_nodes( nodes[0], nodes[1], nodes[2] );
-  double det = DETERM( nodes[0]->coordinates().x(),
-                       nodes[0]->coordinates().y(),
-                       nodes[1]->coordinates().x(),
-                       nodes[1]->coordinates().y(),
-                       nodes[2]->coordinates().x(),
-                       nodes[2]->coordinates().y());
-    //PRINT_INFO("Det = %f\n",det);
-  
-  if(fabs(det) > CUBIT_DBL_MIN){
-    return CUBIT_TRUE;
-  }
-  return CUBIT_FALSE;
-                       
-}
-
-//-------------------------------------------------------------------------
-// Function:    point_in_circumcircle
-// Description: determine if the point is inside the circumcircle of the
-//              triangle and recurse to the adjacent triangles
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::point_in_circumcircle(
-  CubitVector &the_point,
-  TRI *tri_ptr,
-  DLIList <TRI *> &tri_list)
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-  // check this triangle.  If the nodes are colinear do not try to calculate
-    //the circumcenter.
-  if(!are_nodes_colinear(tri_ptr))
-  {
-    PRINT_ERROR("Can't evaluate center of circumcircle\n");
-    return CUBIT_FAILURE;
-  }
-     
-  CubitVector cc = circumcenter( tri_ptr );
-  tri_visited( tri_ptr, CUBIT_TRUE );
-  double dist2 = SQR(the_point.x() - cc.x()) + SQR(the_point.y() - cc.y());
-  double r2 = radius( tri_ptr );
-  double tol_factor = CUBIT_MAX(CUBIT_MAX(tri_ptr->edge(0)->length(),
-                                          tri_ptr->edge(1)->length()),
-                                tri_ptr->edge(2)->length());
-    //PRINT_INFO("Tolerance factor = %f\n", tol_factor);
-  
-  
-  
-  if (r2-dist2 > -(tol_factor*FT_INSIDE_TOL*FT_INSIDE_TOL))// inside or on circle
-  {
-    tri_list.append( tri_ptr );
-
-    // go to its neighbors
-
-    int iedge;
-    TRI *adjtri_ptr;
-    for (iedge=0; iedge<3 && rv == CUBIT_SUCCESS; iedge++){
-     
-      int ii = iedge;
-      adjtri_ptr = tri_ptr->adjacent( ii, refFacePtr );
-      if (adjtri_ptr != NULL && !tri_visited( adjtri_ptr ))
-      {
-        rv = point_in_circumcircle( the_point, adjtri_ptr, tri_list );
-      }
-    }
-  }
-  return rv;
-}
-
-
-//-------------------------------------------------------------------------
 // Function:    constrain_boundary
 // Description: recover the boundary edges from the mesh
 // Author:      chynes
@@ -1121,19 +542,33 @@
 
   // classify the triangles based on their minimum angle
 
-  //rv = 
-  classify_triangles(tri_list);
+  //rv =
+  const int num_lists = 64;
+  const double interval = QUALITY_ANGLE / double( num_lists - 1 );
+  DLIList<TRI*>* tri_sort_array = new DLIList<TRI *> [num_lists];
+  classify_triangles(tri_list, tri_sort_array, num_lists, interval );
 
   // process each of the triangles until done
 
   TRI *tri_ptr;
-  while ((tri_ptr = next_triangle()) != NULL && rv == CUBIT_SUCCESS) 
+  TRI* start_tri = NULL;
+  while ((tri_ptr = next_triangle(tri_sort_array, num_lists)) != NULL && rv == CUBIT_SUCCESS) 
   {
-    rv = insert_at_circumcenter( tri_ptr );
+    rv = FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::insert_at_circumcenter(tri_ptr,
+                                                                                             *facetList,
+                                                                                             start_tri,
+                                                                                             curVisitFlag,
+                                                                                             refFacePtr,
+                                                                                             tri_sort_array,
+                                                                                             num_lists,
+                                                                                             interval,
+                                                                                             QUALITY_ANGLE,
+                                                                                             sizingFunction,
+                                                                                             pTool);
   }
 
-  delete [] triSortArray;
-  triSortArray = NULL;
+  delete [] tri_sort_array;
+  tri_sort_array = NULL;
 
   return rv;
 }
@@ -1145,7 +580,10 @@
 // Date:        6/3/2002
 //-------------------------------------------------------------------------
 template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::classify_triangles(DLIList<TRI *> &tri_list)
+CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::classify_triangles(DLIList<TRI *> &tri_list,
+                                                                                                  DLIList<TRI*>* sorted_lists,
+                                                                                                  const int num_lists,
+                                                                                                  const double interval)
 {
   CubitStatus rv = CUBIT_SUCCESS;
 
@@ -1154,8 +592,6 @@
   // fall within a specified interval.  Triangles will be processed
   // from smallest angle to best angle
 
-  triSortArray = new DLIList<TRI *> [NUM_SORT_LISTS];
-
   // classify each trriangle and place into sort lists
 
   TRI *tri_ptr;
@@ -1164,89 +600,14 @@
   {
     tri_ptr = tri_list.get_and_step();
     //rv = 
-    classify_tri_by_angle( tri_ptr );
+    FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::classify_tri_by_angle(
+                                    tri_ptr, sorted_lists,  num_lists, interval, QUALITY_ANGLE);
   }
    
   return rv;
 }
 
-//-------------------------------------------------------------------------
-// Function:    classify_tri_by_angle
-// Description: compute the angles at the triangle vertices and classify
-//              by its worst triangle
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::classify_tri_by_angle( TRI *tri_ptr )
-{
-  //CubitStatus rv = CUBIT_SUCCESS;
 
-  // Determine the minimum angle
-
-  NODE *nodes[3];
-  tri_ptr->tri_nodes( nodes[0], nodes[1], nodes[2] );
-  double x0 = nodes[0]->coordinates().x();
-  double y0 = nodes[0]->coordinates().y();
-  double x1 = nodes[1]->coordinates().x();
-  double y1 = nodes[1]->coordinates().y();
-  double x2 = nodes[2]->coordinates().x();
-  double y2 = nodes[2]->coordinates().y();
-
-  double ax = x1 - x0;
-  double ay = y1 - y0;
-  double bx = x2 - x0;
-  double by = y2 - y0;
-  double dot = ax*bx + ay*by;
-  double a_mag = sqrt( ax*ax + ay*ay );
-  double b_mag = sqrt( bx*bx + by*by );
-  double angle0 = dot / ( a_mag * b_mag );
-  angle0 = acos( angle0 );
-
-  ax = -ax;
-  ay = -ay;
-  bx = x2 - x1;
-  by = y2 - y1;
-  dot = ax*bx + ay*by;
-  b_mag = sqrt( bx*bx + by*by );
-  double angle1 = dot / ( a_mag * b_mag );
-  angle1 = acos( angle1 );
-
-  double angle2 = CUBIT_PI - angle0 - angle1;
-
-  double min_angle = CUBIT_MIN( CUBIT_MIN(angle0,angle1), 
-                                CUBIT_MIN(angle1,angle2) );
-  if (min_angle < 0.0) {
-    assert(0);
-    return CUBIT_FAILURE;
-  }
-
-  // If it is greater than the QUALITY_ANGLE then place it in
-  // the triSortArray[0], otherwise place it in one of the other deques
-  // depending upon its minimum angle
-
-  // Determine which list
-
-  int index;
-  if (min_angle >= QUALITY_ANGLE) {
-    index = 0;
-  }
-  else {
-    index = 1 + (int)(min_angle/INTERVAL);
-    if (index < 1) index = 1;
-    if (index > NUM_SORT_LISTS-1) index = NUM_SORT_LISTS-1;
-  }
-
-  // Place it on a list
-
-  triSortArray[index].append( tri_ptr );
-  tri_sort_list( tri_ptr, index );
-
-  return CUBIT_SUCCESS;
-
-}
-
-
 //-------------------------------------------------------------------------
 // Function:    next_triangle
 // Description: get the next triangle to process
@@ -1254,231 +615,25 @@
 // Date:        6/3/2002
 //-------------------------------------------------------------------------
 template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-TRI *FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::next_triangle(void)
+TRI *FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::next_triangle(DLIList<TRI*>* sorted_lists,
+                                                                                      const int num_lists)
 {
   TRI *tri_ptr = NULL;
   int ii;
-  for(ii=1; ii<NUM_SORT_LISTS && tri_ptr == NULL; ii++)
+  for( ii = 1; ii < num_lists && tri_ptr == NULL; ii++)
   {
-    if (triSortArray[ii].size() > 0)
-      tri_ptr = triSortArray[ii].remove();
+    if (sorted_lists[ii].size() > 0)
+      tri_ptr = sorted_lists[ii].remove();
   }
   if (tri_ptr == NULL)
   {
-    if (triSortArray[0].size() > 0)
-      tri_ptr = triSortArray[0].remove();
+    if (sorted_lists[0].size() > 0)
+      tri_ptr = sorted_lists[0].remove();
   }
   return tri_ptr;
 }
-//-------------------------------------------------------------------------
-// Function:    get_size
-// Description: get the distortion factor for point inside tri, if one exists
-//				otherwise return 1;
-// Author:      chynes
-// Date:        7/24/02
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-double FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::get_size(CubitVector &cc, TRI *tri_ptr)
-{
-	//extract data
-	NODE *n0,*n1,*n2;
-	CubitVector area_coord;
-	tri_ptr->tri_nodes(n0,n1,n2);
-	
-	if    (n0->coordinates().z() - 1.0 < fabs(FT_INSIDE_TOL) 
-		&& n1->coordinates().z() - 1.0 < fabs(FT_INSIDE_TOL)
-		&& n2->coordinates().z() - 1.0 < fabs(FT_INSIDE_TOL)  )
-		return 1.0;
-	else 
-	{
-		//get vectors
-		CubitVector v0 = n0->coordinates();
-		CubitVector v1 = n1->coordinates();
-		CubitVector v2 = n2->coordinates();
 
-		//set z direction
-		v0.z(cc.z());
-		v1.z(cc.z());
-		v2.z(cc.z());
-
-		//create points
-		CubitPoint *p0 = (CubitPoint*) new CubitPointData(v0);
-		CubitPoint *p1 = (CubitPoint*) new CubitPointData(v1);
-		CubitPoint *p2 = (CubitPoint*) new CubitPointData(v2);
-
-		//create facet
-		CubitFacet *temp_facet = (CubitFacet*) new CubitFacetData(p0,p1,p2);
-
-		FacetEvalTool::facet_area_coordinate(temp_facet, cc, area_coord);
-		
-		delete p0;
-		delete p1;
-		delete p2;
-		delete temp_facet;
-
-		return	  (area_coord.x()*n0->coordinates().z()) 
-				+ (area_coord.y()*n1->coordinates().z()) 
-				+ (area_coord.z()*n2->coordinates().z());
-	}
-
-}
-
 //-------------------------------------------------------------------------
-// Function:    insert_at_circumcenter
-// Description: insert a node at the circumcenter of a tri
-// Author:      chynes
-// Date:        6/3/2002
-//-------------------------------------------------------------------------
-template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
-CubitStatus FacetorTool<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::insert_at_circumcenter(TRI *tri_ptr)
-{
-  CubitStatus rv = CUBIT_SUCCESS;
-
-  // find the cicumcenter of the triangle and the target size there
-    //if nodes are colinear do not try to find circumenter
-  if(!are_nodes_colinear(tri_ptr))
-  {
-    PRINT_ERROR("Can't evaluate center of circumcircle\n");
-    return CUBIT_FAILURE;
-  }
-  CubitVector cc = circumcenter( tri_ptr );
-  
-  //translate cc into 3D space
-  CubitVector cc_xyz;
-  pTool->transform_to_xyz(cc_xyz, cc);
-  // get target length in 3D space
-  double target_length = sizingFunction->size_at_point( cc_xyz );
-  // get new size
-  double size = get_size(cc, tri_ptr);
-  // update size
-  cc.z(size);
-  // update target_length
-  target_length = target_length*size;
-
-  // Determine if we should now insert the point.  Allow insertions
-  // in the general case down to circumcircle size of ALPHA times the
-  // interpolated target edge length size.  For tris with small
-  // angles, allow additional inserts to improve the quality down
-  // to 1/2 the target size
-  if(!are_nodes_colinear(tri_ptr))
-  {
-    PRINT_ERROR("Can't evaluate radius of circumcircle\n");
-    return CUBIT_FAILURE;
-  }
-     
-    
-  double r2 = radius( tri_ptr );
-  CubitBoolean insert = CUBIT_FALSE;
-  int tsindex = tri_sort_list( tri_ptr );
-  assert(tsindex > -1);
-  if (tsindex == 0) 
-  {
-    if (r2 > SQR(ALPHA*target_length)) 
-    {
-      insert = CUBIT_TRUE;
-    }
-  }
-  else 
-  {
-    if (r2 > SQR(0.5*ALPHA*target_length)) 
-    {
-      insert = CUBIT_TRUE;
-    }
-  }
-  if (insert) 
-  {
-
-    // Determine the tris that will be affected by the insertion
-
-    lastTriLocated = tri_ptr;
-    DLIList <TRI *> tri_list;
-    rv = natural_neighbor_tris( cc, tri_list );
-    // If it was outside, then we are done with it
-
-    if (tri_list.size() == 0) 
-    {
-      return CUBIT_SUCCESS;
-    }
-	if (rv != CUBIT_SUCCESS) {
-      return rv;
-    }
-
-    // See if we are too close to a boundary
-
-    double x0, y0, x1, y1, cx, cy, edge_radius, dist;
-    TRI *nntri_ptr;
-    EDGE *edge_ptr;
-    int ii, iedge;
-    for (ii=0; ii<tri_list.size(); ii++) 
-    {
-      nntri_ptr = tri_list.get_and_step();
-      for (iedge=0; iedge<3; iedge++) 
-      {
-		edge_ptr = tri_ptr->edge( iedge );
-
-        // An edge encroaches if the distance from the prospective
-        // new point to the midpoint of the edge is less than 
-        // half the length of the edge
-
-        if (edge_ptr->marked()) // on the boundary?
-        {
-          x0 = (edge_ptr->start_node())->coordinates().x();
-          y0 = (edge_ptr->start_node())->coordinates().y();
-          x1 = (edge_ptr->end_node())->coordinates().x();
-          y1 = (edge_ptr->end_node())->coordinates().y();
-          cx = (x0 + x1) * 0.5;
-          cy = (y0 + y1) * 0.5;
-          edge_radius = sqrt(SQR(x1-x0) + SQR(y1-y0)) * 0.5;       
-          dist = sqrt( SQR(cx-cc.x()) + SQR(cy-cc.y()) );
-
-          // Edge encroaches: don't insert, return now
-
-          if (dist - edge_radius < FT_INSIDE_TOL) 
-          {
-            return CUBIT_SUCCESS;
-          }
-        }
-      }
-    }
-
-    // Before inserting, remove all the tris on the neighbor
-    // tri_list from the lists 
-   
-    int index;
-    for (ii=0; ii<tri_list.size(); ii++) 
-    {
-      nntri_ptr = tri_list.get_and_step();
-      index = tri_sort_list( nntri_ptr );
-      assert(index >= 0);
-      triSortArray[index].remove( nntri_ptr );
-    }
-
-    // Create the new node
-
-    NODE *new_node_ptr = (NODE *)new NODECHILD( cc, refFacePtr );
-
-    // Insert the new node into the mesh
-
-    rv = bowyer_watson_insert( new_node_ptr, tri_list );
-    if (rv != CUBIT_SUCCESS)
-      return rv;
-
-    // get the new tris at the node and classify them
-
-    tri_list.clean_out();
-    new_node_ptr->tris( tri_list );
-    for (ii=0; ii<tri_list.size() && rv == CUBIT_SUCCESS; ii++) 
-    {
-      tri_ptr = tri_list.get_and_step();
-      rv = classify_tri_by_angle( tri_ptr );
-    }
-  }
-
-  return rv;
-
-}
-
-//-------------------------------------------------------------------------
 // Function:    clean_up_data
 // Description: clean up any data we've allocated
 // Author:      chynes
@@ -1546,7 +701,6 @@
     if (edge_ptr)
       edge_ptr->marked( CUBIT_FALSE );
   }
-  
 }
 
 // EOF

Modified: cgm/branches/cubit/geom/Cholla/FacetorTool.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetorTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/FacetorTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -68,16 +68,9 @@
    //- bounding edges on the surfaces represented by their start
    //- and end nodes
 
-  DLIList<TRI*> *triSortArray;
-   // array of lists of triangles sorted by their worst angle
-
   NODE *boxNodes[4];
    //- temporary nodes created enclosing the surface to facilitate
    //- Delaunay node insertion
-    
-  TRI *lastTriLocated;
-  //TRI *debugTri;
-   //- last triangle the locate point function found
 
   int curVisitFlag;
    //- current visited flag for triangles
@@ -88,57 +81,9 @@
   CubitStatus init_box();
    //- create two initial bounding triangles
 
-  CubitVector &circumcenter( TRI *tri_ptr );
-   //- get the circumcenter of the triangle
-
-  double radius( TRI *tri_ptr );
-   //- get the radius squared of the triangle circumcircle
-
-  CubitBoolean tri_visited( TRI *tri_ptr );
-  void tri_visited( TRI *tri_ptr, CubitBoolean visited );
-   //- get and set the visited flag
-
-  void tri_sort_list( TRI *tri_ptr, int sort_list_index );
-  int tri_sort_list( TRI *tri_ptr );
-   //- get and set the tri sort array index that this tri is in
-
   CubitStatus insert_nodes( DLIList<NODE *> *&bounding_nodes );
    //- insert a list of nodes into an existing triangulation
 
-  CubitStatus insert_node( NODE *node_ptr );
-    //- nsert one node into Delaunay mesh          
-
-  CubitBoolean are_nodes_colinear( TRI *tri_ptr );
-   //- are the nodes of this tri roughly colinear
-  
-  CubitStatus bowyer_watson_insert( NODE *node_ptr,
-                                    DLIList<TRI *> &tri_list);
-   //- Bowyer-Watson insertion into an existing Delaunay Mesh
-  CubitStatus valid_void( NODE *node_ptr,
-                          DLIList<TRI *> &tri_list);
-    //check the void created in Bowyer-Watson to ensure the boundary
-    //seems valid.
-
-  CubitStatus natural_neighbor_tris( CubitVector &the_point,
-                                     DLIList <TRI *> &tri_list);
-   //- get a list of all triangles whose circumcircle contain 
-   //- the point
-
-  CubitStatus locate_point( CubitVector &the_point,
-                            TRI *&tri_ptr );
-   //- return the triangle the point is located in
-
-  CubitStatus exhaustive_locate_point( CubitVector &the_point,
-                                       TRI *&tri_ptr );
-   //- return the triangle the point is located in by checking 
-   //- all triangles
-
-  CubitStatus point_in_circumcircle( CubitVector &the_point,
-                                     TRI *tri_ptr,
-                                     DLIList <TRI *> &tri_list );
-   //- determine if the point is inside the circumcircle of the
-   //- triangle and recurse to the adjacent triangles 
-
   CubitStatus constrain_boundary(void);
    //- recover the boundary edges from the mesh
 
@@ -157,20 +102,15 @@
    //- improve quality. This inserts nodes at the circumcenters of 
    //- triangles roughly based on the algorithm by Jonathon Shewchuk
 
-  CubitStatus classify_triangles(DLIList<TRI *> &tri_list);
+  CubitStatus classify_triangles(DLIList<TRI *> &tri_list,
+                                 DLIList<TRI*>* sorted_lists,
+                                 const int num_lists,
+                                 const double interval);
    //- order the triangles in the current mesh by their worst angle
 
-  CubitStatus classify_tri_by_angle( TRI *tri_ptr );
-   //- compute the angles at the triangle vertices and classify
-   //- by its worst triangle
-
-  TRI *next_triangle(void);
-   //- get the next triangle to process
-
-  double get_size(CubitVector &cc, TRI *tri_ptr);
-
-  CubitStatus insert_at_circumcenter(TRI *tri_ptr);
-   //- insert a node at the circumcenter of a tri
+  TRI *next_triangle(DLIList<TRI*>* sorted_lists,
+                     const int num_lists);
+   //- get the next triangle to process;
   
   void clean_up_data(void);
   //- clean up any data we've allocated

Added: cgm/branches/cubit/geom/Cholla/FacetorUtil.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetorUtil.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/Cholla/FacetorUtil.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,934 @@
+
+#ifdef INLINE_TEMPLATES
+#define MY_INLINE inline
+#else
+#define MY_INLINE
+#endif
+
+#include "FacetorUtil.hpp"
+#include "TDDelaunay.hpp"
+#include "FacetEvalTool.hpp"
+#include "CubitPoint.hpp"
+#include "CubitPointData.hpp"
+#include "CubitFacet.hpp"
+#include "CubitFacetData.hpp"
+#include "ParamTool.hpp"
+
+#define DETERM(p1,q1,p2,q2,p3,q3)\
+     ((q3)*((p2)-(p1)) + (q2)*((p1)-(p3)) + (q1)*((p3)-(p2)))
+#define FT_INSIDE_TOL 1.0e-6
+#define SQR(x) ((x) * (x))
+#define ALPHA 0.70228615
+
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::locate_point(
+                                      CubitVector& the_point,
+                                      DLIList<TRI*>& facet_list,
+                                      TRI* starting_tri,
+                                      SURF* owning_surface,
+                                      TRI*& tri_ptr)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+
+    // start with the last one found
+
+  if (starting_tri != NULL)
+      tri_ptr = starting_tri;
+
+    // otherwise use the first one on the list
+
+  else
+  {
+    tri_ptr = facet_list.get();
+  }
+
+
+    // loop until we find something
+
+  NODE *n0, *n1, *n2;
+  double aa, bb, cc;
+  CubitBoolean found = CUBIT_FALSE;
+
+    //avoiding infinite loop
+  int counter = 0;
+  int max_count = facet_list.size();
+  
+  while(!found && rv == CUBIT_SUCCESS)
+  {
+    tri_ptr->tri_nodes( n0, n1, n2 );
+    aa = DETERM(the_point.x(), the_point.y(),
+                n1->coordinates().x(), n1->coordinates().y(),
+                n2->coordinates().x(), n2->coordinates().y());
+    bb = DETERM(n0->coordinates().x(), n0->coordinates().y(),
+                the_point.x(), the_point.y(),
+                n2->coordinates().x(), n2->coordinates().y());
+    cc = DETERM(n0->coordinates().x(), n0->coordinates().y(),
+                n1->coordinates().x(), n1->coordinates().y(),
+                the_point.x(), the_point.y());
+    if (aa > -FT_INSIDE_TOL &&
+        bb > -FT_INSIDE_TOL &&
+        cc > -FT_INSIDE_TOL)
+    {
+      found = CUBIT_TRUE;  // this is the one
+    }
+    else
+    {
+        // set up to check the next logical neighbor
+      if (aa <= bb && aa <= cc) 
+      {
+        int edge_index = 1;
+        tri_ptr = tri_ptr->adjacent( edge_index, owning_surface );
+      }
+      else if (bb <= aa && bb <= cc) 
+      {
+        int edge_index = 2;
+        tri_ptr = tri_ptr->adjacent( edge_index, owning_surface );
+      }
+      else 
+      {
+        int edge_index = 0;
+        tri_ptr = tri_ptr->adjacent( edge_index, owning_surface );
+      }
+        // check to see if we've left the triangulation
+        // also make sure that we are not stuck in a cycle
+      if (tri_ptr == NULL || counter > max_count)
+      {
+        if(counter>max_count){
+          PRINT_WARNING("Encountered problem locating a triangle; going to exhaustive search.\n");
+        }
+
+        rv = exhaustive_locate_point( the_point, facet_list, tri_ptr );
+        found = CUBIT_TRUE;
+      }
+    }
+    ++counter;
+  }
+  
+  return rv;
+}
+
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::exhaustive_locate_point(
+                                                 CubitVector& the_point,
+                                                 DLIList<TRI*>& facet_list,
+                                                 TRI*& tri_ptr)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+  
+  // loop until we find something
+
+  int ii;
+  NODE *n0, *n1, *n2;
+  double aa, bb, cc;
+  CubitBoolean found = CUBIT_FALSE;
+  for (ii=0; ii<facet_list.size() && !found; ii++)
+  {
+    tri_ptr = facet_list.get_and_step();
+    tri_ptr->tri_nodes( n0, n1, n2 );
+    aa = DETERM(the_point.x(), the_point.y(),
+                n1->coordinates().x(), n1->coordinates().y(),
+                n2->coordinates().x(), n2->coordinates().y());
+    bb = DETERM(n0->coordinates().x(), n0->coordinates().y(),
+                the_point.x(), the_point.y(),
+                n2->coordinates().x(), n2->coordinates().y());
+    cc = DETERM(n0->coordinates().x(), n0->coordinates().y(),
+                n1->coordinates().x(), n1->coordinates().y(),
+                the_point.x(), the_point.y());
+    if (aa > -FT_INSIDE_TOL &&
+        bb > -FT_INSIDE_TOL &&
+        cc > -FT_INSIDE_TOL)
+    {
+      found = CUBIT_TRUE;  // this is the one
+    }
+  }
+  if (!found)
+  {
+    rv = CUBIT_FAILURE;
+    tri_ptr = NULL;
+  }
+
+  return rv;
+}
+
+//-------------------------------------------------------------------------
+// Function:    are_nodes_colinear
+// Description: determine if the TRI is valid
+// Author:      mbrewer
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitBoolean
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::are_nodes_colinear(TRI* tri_ptr)
+{
+  NODE *nodes[3];
+  tri_ptr->tri_nodes( nodes[0], nodes[1], nodes[2] );
+  double det = DETERM( nodes[0]->coordinates().x(),
+                       nodes[0]->coordinates().y(),
+                       nodes[1]->coordinates().x(),
+                       nodes[1]->coordinates().y(),
+                       nodes[2]->coordinates().x(),
+                       nodes[2]->coordinates().y());
+    //PRINT_INFO("Det = %f\n",det);
+  
+  if(fabs(det) > CUBIT_DBL_MIN){
+    return CUBIT_TRUE;
+  }
+  return CUBIT_FALSE;
+}
+
+//-------------------------------------------------------------------------
+// Function:    circumcenter
+// Description: get the circumcenter of the triangle
+// Author:      chynes
+// Date:        6/6/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitVector& 
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::circumcenter(TRI* tri_ptr)
+{
+	ToolData *td = tri_ptr->get_TD( TDDelaunay<TRI,NODE>::is_delaunay );
+	TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
+	if(td_del == NULL) {
+		td_del = new TDDelaunay<TRI, NODE>();
+		tri_ptr->add_TD( td_del );
+	}
+	return td_del->circumcenter2d( tri_ptr );
+}
+
+//-------------------------------------------------------------------------
+// Function:    tri_visited
+// Description: set the tri_visited flag
+// Author:      chynes
+// Date:        6/6/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitBoolean
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_visited(
+                                      TRI *tri_ptr,
+                                      int curr_visit_flag)
+{
+  ToolData *td = tri_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
+  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
+  if (td_del == NULL)
+  {
+    td_del = new TDDelaunay< TRI, NODE >();
+    tri_ptr->add_TD( td_del );
+  }
+  return (td_del->visit_flag() == curr_visit_flag);
+}
+
+//-------------------------------------------------------------------------
+// Function:    tri_visited
+// Description: set the tri_visited flag
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+void
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_visited(
+                               TRI *facet_ptr,
+                               CubitBoolean visited,
+                               int curr_visit_flag)
+{
+  ToolData *td = facet_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
+  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
+  if (td_del == NULL)
+  {
+    td_del = new TDDelaunay< TRI, NODE >();
+    facet_ptr->add_TD( td_del );
+  }
+  if (visited)
+    td_del->visit_flag(curr_visit_flag);
+  else
+    td_del->visit_flag(INT_MIN);
+}
+
+//-------------------------------------------------------------------------
+// Function:    radius
+// Description: get the radius squared of the triangle circumcircle
+// Author:      chynes
+// Date:        6/6/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+double
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::radius(TRI* tri_ptr)
+{
+  ToolData *td = tri_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
+  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
+  if (td_del == NULL)
+  {
+    td_del = new TDDelaunay< TRI, NODE >();
+    tri_ptr->add_TD( td_del );
+  }
+  return td_del->radius2d( tri_ptr );
+}
+
+//-------------------------------------------------------------------------
+// Function:    point_in_circumcircle
+// Description: determine if the point is inside the circumcircle of the
+//              triangle and recurse to the adjacent triangles
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::point_in_circumcircle(
+                                               CubitVector& the_point,
+                                               TRI* tri_ptr,
+                                               DLIList<TRI*>& tri_list,
+                                               SURF* surface_ptr,
+                                               int curr_visit_flag)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+
+  // check this triangle.  If the nodes are colinear do not try to calculate
+    //the circumcenter.
+  if(!are_nodes_colinear(tri_ptr))
+  {
+    PRINT_ERROR("Can't evaluate center of circumcircle\n");
+    return CUBIT_FAILURE;
+  }
+     
+  CubitVector cc = circumcenter( tri_ptr );
+  tri_visited( tri_ptr, CUBIT_TRUE, curr_visit_flag );
+  double dist2 = SQR(the_point.x() - cc.x()) + SQR(the_point.y() - cc.y());
+  double r2 = radius( tri_ptr );
+  double tol_factor = CUBIT_MAX(CUBIT_MAX(tri_ptr->edge(0)->length(),
+                                          tri_ptr->edge(1)->length()),
+                                tri_ptr->edge(2)->length());
+    //PRINT_INFO("Tolerance factor = %f\n", tol_factor);
+  
+  
+  
+  if (r2-dist2 > -(tol_factor*FT_INSIDE_TOL*FT_INSIDE_TOL))// inside or on circle
+  {
+    tri_list.append( tri_ptr );
+
+    // go to its neighbors
+
+    int iedge;
+    TRI *adjtri_ptr;
+    for (iedge=0; iedge<3 && rv == CUBIT_SUCCESS; iedge++){
+     
+      int ii = iedge;
+      adjtri_ptr = tri_ptr->adjacent( ii, surface_ptr );
+      if (adjtri_ptr != NULL && !tri_visited( adjtri_ptr, curr_visit_flag ))
+      {
+        rv = point_in_circumcircle( the_point, adjtri_ptr, tri_list,
+                                                   surface_ptr, curr_visit_flag );
+      }
+    }
+  }
+  return rv;
+}
+
+//-------------------------------------------------------------------------
+// Function:    natural_neighbor_tris
+// Description: get a list of all triangles whose circumcircle contain 
+//              the point
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::natural_neighbor_tris(
+                                               CubitVector& the_point,
+                                               DLIList<TRI*>& facet_list,
+                                               TRI*& start_tri,
+                                               SURF* surface_ptr,
+                                               int& curr_visit_flag,
+                                               DLIList<TRI*>& tri_list)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+
+  // find the triangle the point is contained in
+
+  //CubitVector areacoord;
+  TRI *tri_ptr;
+  rv = locate_point( the_point, facet_list, start_tri, surface_ptr, tri_ptr );
+  start_tri = tri_ptr;
+  
+  // keep track of visitation to triangles by incrementing curr_visit_flag
+  // and comparing with the visit flag stored with the triangle
+
+  curr_visit_flag++;
+
+  // Recursively search, (starting with the tri the point is in)
+  // search for all tris whose circumcircle contain the point and place 
+  // in the tri_list 
+
+  if (rv == CUBIT_SUCCESS)
+  {
+    tri_list.append( tri_ptr );
+    tri_visited( tri_ptr, CUBIT_TRUE, curr_visit_flag );
+    int iedge;
+    TRI *adjtri_ptr;
+    for (iedge=0; iedge<3 && rv == CUBIT_SUCCESS; iedge++)
+	{
+      int ii = iedge;
+      adjtri_ptr = tri_ptr->adjacent( ii, surface_ptr );
+      if (adjtri_ptr != NULL && !tri_visited( adjtri_ptr, curr_visit_flag )){
+        rv = point_in_circumcircle( the_point, adjtri_ptr,
+                                                   tri_list, surface_ptr,
+                                                   curr_visit_flag);
+      }
+    }
+  }
+  return rv;
+}
+
+/************************************************************/
+//author:  mbrewer
+//This function performs tests on the void created by a point's
+//insertion to make sure that invalid connectivities are not
+//being created.  
+/************************************************************/
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::valid_void(
+                                     NODE * /*point_ptr*/,
+                                     DLIList<TRI *> &tri_list,
+                                     SURF* surface_ptr,
+                                     int curr_visit_flag)
+{
+  int temp_i, temp_j;
+  DLIList<EDGE*> boundary_edge_list;
+  DLIList<NODE*> boundary_node_list;
+  TRI *adjtri_ptr;
+  TRI *tri_ptr;
+  EDGE *edge_ptr;
+  DLIList<EDGE *> edge_list;
+    //loop over the tri's in tri_list and find all of the curves
+    //on the boundary of the set (ie, on the boundary of the void). 
+  for (temp_i=0; temp_i<tri_list.size(); temp_i++)
+  {
+    tri_ptr = tri_list.get_and_step();
+      //check each edge to see whether it is a boundary edge or not
+    for (temp_j=0; temp_j<3; temp_j++){
+      
+      int kk = temp_j;
+        // - if TRI == CubitFacet
+        // - kk will be corrected in adjacent() to 
+        // - give the correct EDGE index
+      adjtri_ptr = tri_ptr->adjacent( kk, surface_ptr );
+      if (!adjtri_ptr || !tri_visited( adjtri_ptr, curr_visit_flag ))
+      {
+        edge_ptr = tri_ptr->edge(kk);
+        boundary_edge_list.append(edge_ptr);
+      }
+    }
+  }
+  int list_size = boundary_edge_list.size();
+    //uniquify the boundary edge list
+  boundary_edge_list.uniquify_unordered();
+    //the list shouldn't have changed size during the uniquify.
+    //if it did, there is a problem.
+  if(list_size != boundary_edge_list.size()){
+    PRINT_WARNING("Unexpected result.  Edge was duplicated on boundary.\n");
+    return CUBIT_FAILURE;
+  }
+    //loop over the boundary edges and get the nodes in the boundary loop
+  for(temp_i=0; temp_i<list_size; ++temp_i){
+    edge_ptr=boundary_edge_list.get_and_step();
+    boundary_node_list.append(edge_ptr->end_node());
+    boundary_node_list.append(edge_ptr->start_node());
+  }
+  list_size = boundary_node_list.size();
+    //each node should be in exactly two edges.  First make sure that there
+    //are the correct number of nodes.
+  if(list_size%2){
+    PRINT_WARNING("Unexpected result.  Node not listed twice.\n");
+    return CUBIT_FAILURE;
+  }
+    //now uniquify to make sure that the nodes were listed the correct number
+    //of times.  
+  boundary_node_list.uniquify_unordered();
+  if( (list_size/2) != boundary_node_list.size()){
+    PRINT_WARNING("Unexpected result.  Node was listed an incorrect number of times.\n");
+    return CUBIT_FAILURE;
+  }
+  return CUBIT_SUCCESS;
+  
+}
+
+//-------------------------------------------------------------------------
+// Function:    bowyer_watson_insert
+// Description: Bowyer-Watson insertion into an existing Delaunay Mesh
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::bowyer_watson_insert(
+                                              NODE* point_ptr,
+                                              DLIList<TRI*>& tri_list,
+                                              DLIList<TRI*>& facet_list,
+                                              int& curr_visit_flag,
+                                              SURF* surface_ptr,
+                                              TRI*& last_tri)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+
+    // mark the tris in the list so we can distinguish them from their 
+    // neighbors
+
+  curr_visit_flag++;
+  int ii, jj;
+  TRI *tri_ptr;
+  for (ii=0; ii<tri_list.size(); ii++)
+  {
+    tri_ptr = tri_list.get_and_step();
+    tri_visited( tri_ptr, CUBIT_TRUE, curr_visit_flag );
+  }
+    //MBREWER:  This is not an optimal test.  But, we need need to 
+    //do some tests to try to ensure that the void is valid for what
+    //we need.  This is attempting to avoid crashes by not allowing nodes
+    //to be inserted when the mesh starts diverging from the Delaunay
+    //criteria.
+  rv = valid_void( point_ptr, tri_list, surface_ptr, curr_visit_flag );
+  if(!rv)
+      return rv;
+  
+    // find all edges at the boundary of the visited triangles and create
+    // new triangles with them
+
+    // create a new triangle with this edge and the node
+  TRI *adjtri_ptr;
+  TRI *new_tri = NULL;
+  EDGE *edge_ptr;
+  DLIList<EDGE *> edge_list;
+  for (ii=0; ii<tri_list.size(); ii++)
+  {
+    tri_ptr = tri_list.get_and_step();
+    for (jj=0; jj<3; jj++){
+      
+      int kk = jj;
+        // - if TRI == CubitFacet
+        // - kk will be corrected in adjacent() to 
+        // - give the correct EDGE index
+      adjtri_ptr = tri_ptr->adjacent( kk, surface_ptr );
+      if (!adjtri_ptr || !tri_visited( adjtri_ptr, curr_visit_flag ))
+      {
+        edge_ptr = tri_ptr->edge(kk);
+        assert(edge_list.append_unique( edge_ptr ));
+        if(tri_ptr->sense(kk) == CUBIT_FORWARD)
+            new_tri = (TRI *) new TRICHILD( edge_ptr->start_node(), edge_ptr->end_node(), point_ptr, surface_ptr);
+        else
+            new_tri = (TRI *) new TRICHILD( edge_ptr->end_node(), edge_ptr->start_node(), point_ptr, surface_ptr);
+        facet_list.append(new_tri);
+      }
+    }
+  }
+  last_tri = new_tri;
+
+    // delete the triangles in the original triangle list
+
+  EDGE *del_edge_ptr;
+  DLIList<EDGE *> del_edge_list;
+  for (ii=0; ii<tri_list.size(); ii++)
+  {
+    tri_ptr = tri_list.get_and_step();
+    del_edge_list.clean_out();
+    facet_list.move_to(tri_ptr);
+    facet_list.extract();
+    tri_ptr->edges( del_edge_list );
+    delete tri_ptr;
+
+      // delete the unused edges
+    for (jj=0; jj<del_edge_list.size(); jj++)
+    {
+      del_edge_ptr = del_edge_list.get_and_step();
+      if (del_edge_ptr->number_tris() == 0 && del_edge_ptr->number_faces() == 0 )
+          delete del_edge_ptr;
+    }
+  }
+
+  return rv;
+}
+
+//-------------------------------------------------------------------------
+// Function:    insert_node
+// Description: insert one node into Delaunay mesh
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::insert_node(
+                                     NODE *node_ptr,
+                                     DLIList<TRI*>& facet_list,
+                                     SURF* surface_ptr,
+                                     int& curr_visit_flag,
+                                     TRI*& last_tri)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+
+  // get a list of all triangles whose circumcircle contain the point
+  
+  DLIList<TRI *> tri_list;
+  CubitVector the_point = node_ptr->coordinates();
+  rv = natural_neighbor_tris( the_point, facet_list,
+                              last_tri, surface_ptr,
+                              curr_visit_flag, tri_list );
+
+
+  // Use a Bowyer-Watson insertion 
+  
+  if (rv == CUBIT_SUCCESS)
+  {
+    rv = bowyer_watson_insert( node_ptr, tri_list,
+                               facet_list, curr_visit_flag,
+                               surface_ptr, last_tri);
+  }
+
+  return rv;
+}
+
+//-------------------------------------------------------------------------
+// Function:    get_size
+// Description: get the distortion factor for point inside tri, if one exists
+//              otherwise return 1;
+// Author:      chynes
+// Date:        7/24/02
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+double
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::get_size(CubitVector &cc, TRI *tri_ptr)
+{
+	//extract data
+	NODE *n0,*n1,*n2;
+	CubitVector area_coord;
+	tri_ptr->tri_nodes(n0,n1,n2);
+	
+	if    (n0->coordinates().z() - 1.0 < fabs(FT_INSIDE_TOL) 
+		&& n1->coordinates().z() - 1.0 < fabs(FT_INSIDE_TOL)
+		&& n2->coordinates().z() - 1.0 < fabs(FT_INSIDE_TOL)  )
+		return 1.0;
+	else 
+	{
+		//get vectors
+		CubitVector v0 = n0->coordinates();
+		CubitVector v1 = n1->coordinates();
+		CubitVector v2 = n2->coordinates();
+
+		//set z direction
+		v0.z(cc.z());
+		v1.z(cc.z());
+		v2.z(cc.z());
+
+		//create points
+		CubitPoint *p0 = (CubitPoint*) new CubitPointData(v0);
+		CubitPoint *p1 = (CubitPoint*) new CubitPointData(v1);
+		CubitPoint *p2 = (CubitPoint*) new CubitPointData(v2);
+
+		//create facet
+		CubitFacet *temp_facet = (CubitFacet*) new CubitFacetData(p0,p1,p2);
+
+		FacetEvalTool::facet_area_coordinate(temp_facet, cc, area_coord);
+		
+		delete p0;
+		delete p1;
+		delete p2;
+		delete temp_facet;
+
+		return	  (area_coord.x()*n0->coordinates().z()) 
+				+ (area_coord.y()*n1->coordinates().z()) 
+				+ (area_coord.z()*n2->coordinates().z());
+	}
+}
+
+//-------------------------------------------------------------------------
+// Function:    tri_sort_list
+// Description: set the tri sort list index
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+void
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_sort_list(
+                                TRI *facet_ptr,
+                                int sort_list_index )
+{
+  ToolData *td = facet_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
+  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
+  if (td_del == NULL)
+  {
+    td_del = new TDDelaunay<TRI, NODE>();
+    facet_ptr->add_TD( td_del );
+  }
+  td_del->tri_sort_list(sort_list_index);
+}
+
+
+//-------------------------------------------------------------------------
+// Function:    tri_sort_list
+// Description: get the tri sort list index
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+int
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::tri_sort_list( TRI *facet_ptr )
+{
+  ToolData *td = facet_ptr->get_TD( TDDelaunay< TRI, NODE >::is_delaunay );
+  TDDelaunay< TRI, NODE > *td_del = dynamic_cast<TDDelaunay< TRI, NODE >*> (td);
+  if (td_del == NULL)
+  {
+    td_del = new TDDelaunay<TRI, NODE>();
+    facet_ptr->add_TD( td_del );
+  }
+  return td_del->tri_sort_list();
+}
+
+//-------------------------------------------------------------------------
+// Function:    classify_tri_by_angle
+// Description: compute the angles at the triangle vertices and classify
+//              by its worst triangle
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::classify_tri_by_angle(
+                                               TRI* tri_ptr,
+                                               DLIList<TRI*>* sorted_lists,
+                                               const int num_lists,
+                                               const double interval,
+                                               const double quality_angle)
+{
+  //CubitStatus rv = CUBIT_SUCCESS;
+
+  // Determine the minimum angle
+
+  NODE *nodes[3];
+  tri_ptr->tri_nodes( nodes[0], nodes[1], nodes[2] );
+  double x0 = nodes[0]->coordinates().x();
+  double y0 = nodes[0]->coordinates().y();
+  double x1 = nodes[1]->coordinates().x();
+  double y1 = nodes[1]->coordinates().y();
+  double x2 = nodes[2]->coordinates().x();
+  double y2 = nodes[2]->coordinates().y();
+
+  double ax = x1 - x0;
+  double ay = y1 - y0;
+  double bx = x2 - x0;
+  double by = y2 - y0;
+  double dot = ax*bx + ay*by;
+  double a_mag = sqrt( ax*ax + ay*ay );
+  double b_mag = sqrt( bx*bx + by*by );
+  double angle0 = dot / ( a_mag * b_mag );
+  angle0 = acos( angle0 );
+
+  ax = -ax;
+  ay = -ay;
+  bx = x2 - x1;
+  by = y2 - y1;
+  dot = ax*bx + ay*by;
+  b_mag = sqrt( bx*bx + by*by );
+  double angle1 = dot / ( a_mag * b_mag );
+  angle1 = acos( angle1 );
+
+  double angle2 = CUBIT_PI - angle0 - angle1;
+
+  double min_angle = CUBIT_MIN( CUBIT_MIN(angle0,angle1), 
+                                CUBIT_MIN(angle1,angle2) );
+  if (min_angle < 0.0) {
+    assert(0);
+    return CUBIT_FAILURE;
+  }
+
+  // If it is greater than the QUALITY_ANGLE then place it in
+  // the triSortArray[0], otherwise place it in one of the other deques
+  // depending upon its minimum angle
+
+  // Determine which list
+
+  int index;
+  if (min_angle >= quality_angle) {
+    index = 0;
+  }
+  else {
+    index = 1 + (int)(min_angle/interval);
+    if (index < 1) index = 1;
+    if (index > num_lists-1) index = num_lists-1;
+  }
+
+  // Place it on a list
+
+  sorted_lists[index].append( tri_ptr );
+  tri_sort_list( tri_ptr, index );
+
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Function:    insert_at_circumcenter
+// Description: insert a node at the circumcenter of a tri
+// Author:      chynes
+// Date:        6/3/2002
+//-------------------------------------------------------------------------
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC> MY_INLINE
+CubitStatus
+FacetorUtil<SURF, TRI, EDGE, NODE, TRICHILD, NODECHILD, SIZEFUNC>::insert_at_circumcenter(
+                                                TRI* tri_ptr,
+                                                DLIList<TRI*>& facet_list,
+                                                TRI*& start_tri,
+                                                int& curr_visit_flag,
+                                                SURF* surface_ptr,
+                                                DLIList<TRI*>* sorted_lists,
+                                                const int num_lists,
+                                                const double interval,
+                                                const double quality_angle,
+                                                SIZEFUNC* sizing_function,
+                                                ParamTool* p_tool)
+{
+  CubitStatus rv = CUBIT_SUCCESS;
+
+  // find the cicumcenter of the triangle and the target size there
+    //if nodes are colinear do not try to find circumenter
+  if(!are_nodes_colinear(tri_ptr))
+  {
+    PRINT_ERROR("Can't evaluate center of circumcircle\n");
+    return CUBIT_FAILURE;
+  }
+  CubitVector cc = circumcenter( tri_ptr );
+  
+  //translate cc into 3D space
+  CubitVector cc_xyz;
+  p_tool->transform_to_xyz(cc_xyz, cc);
+  // get target length in 3D space
+  double target_length = sizing_function->size_at_point( cc_xyz );
+  // get new size
+  double size = get_size(cc, tri_ptr);
+  // update size
+  cc.z(size);
+  // update target_length
+  target_length = target_length*size;
+
+  // Determine if we should now insert the point.  Allow insertions
+  // in the general case down to circumcircle size of ALPHA times the
+  // interpolated target edge length size.  For tris with small
+  // angles, allow additional inserts to improve the quality down
+  // to 1/2 the target size
+  if(!are_nodes_colinear(tri_ptr))
+  {
+    PRINT_ERROR("Can't evaluate radius of circumcircle\n");
+    return CUBIT_FAILURE;
+  }
+     
+    
+  double r2 = radius( tri_ptr );
+  CubitBoolean insert = CUBIT_FALSE;
+  int tsindex = tri_sort_list( tri_ptr );
+  assert(tsindex > -1);
+  if (tsindex == 0) 
+  {
+    if (r2 > SQR(ALPHA*target_length)) 
+    {
+      insert = CUBIT_TRUE;
+    }
+  }
+  else 
+  {
+    if (r2 > SQR(0.5*ALPHA*target_length)) 
+    {
+      insert = CUBIT_TRUE;
+    }
+  }
+  if (insert) 
+  {
+
+      // Determine the tris that will be affected by the insertion
+
+    start_tri = tri_ptr;
+    DLIList <TRI *> tri_list;
+    rv = natural_neighbor_tris( cc, facet_list,
+                                               start_tri, surface_ptr,
+                                               curr_visit_flag, tri_list );
+      // If it was outside, then we are done with it
+
+    if (tri_list.size() == 0) 
+    {
+      return CUBIT_SUCCESS;
+    }
+    if (rv != CUBIT_SUCCESS) {
+      return rv;
+    }
+
+      // See if we are too close to a boundary
+
+    double x0, y0, x1, y1, cx, cy, edge_radius, dist;
+    TRI *nntri_ptr;
+    EDGE *edge_ptr;
+    int ii, iedge;
+    for (ii=0; ii<tri_list.size(); ii++) 
+    {
+      nntri_ptr = tri_list.get_and_step();
+      for (iedge=0; iedge<3; iedge++) 
+      {
+        edge_ptr = tri_ptr->edge( iedge );
+
+          // An edge encroaches if the distance from the prospective
+          // new point to the midpoint of the edge is less than 
+          // half the length of the edge
+
+        if (edge_ptr->marked()) // on the boundary?
+        {
+          x0 = (edge_ptr->start_node())->coordinates().x();
+          y0 = (edge_ptr->start_node())->coordinates().y();
+          x1 = (edge_ptr->end_node())->coordinates().x();
+          y1 = (edge_ptr->end_node())->coordinates().y();
+          cx = (x0 + x1) * 0.5;
+          cy = (y0 + y1) * 0.5;
+          edge_radius = sqrt(SQR(x1-x0) + SQR(y1-y0)) * 0.5;       
+          dist = sqrt( SQR(cx-cc.x()) + SQR(cy-cc.y()) );
+
+            // Edge encroaches: don't insert, return now
+
+          if (dist - edge_radius < FT_INSIDE_TOL) 
+          {
+            return CUBIT_SUCCESS;
+          }
+        }
+      }
+    }
+
+      // Before inserting, remove all the tris on the neighbor
+      // tri_list from the lists 
+   
+    int index;
+    for (ii=0; ii<tri_list.size(); ii++) 
+    {
+      nntri_ptr = tri_list.get_and_step();
+      index = tri_sort_list( nntri_ptr );
+      assert(index >= 0);
+      sorted_lists[index].remove( nntri_ptr );
+    }
+
+      // Create the new node
+
+    NODE *new_node_ptr = (NODE *)new NODECHILD( cc, surface_ptr );
+
+      // Insert the new node into the mesh
+
+    rv = bowyer_watson_insert( new_node_ptr, tri_list,
+                               facet_list, curr_visit_flag,
+                               surface_ptr, start_tri);
+    if (rv != CUBIT_SUCCESS)
+        return rv;
+
+      // get the new tris at the node and classify them
+
+    tri_list.clean_out();
+    new_node_ptr->tris( tri_list );
+    for (ii=0; ii<tri_list.size() && rv == CUBIT_SUCCESS; ii++) 
+    {
+      tri_ptr = tri_list.get_and_step();
+      rv = classify_tri_by_angle( tri_ptr, sorted_lists, num_lists, interval, quality_angle );
+    }
+  }
+
+  return rv;
+}

Added: cgm/branches/cubit/geom/Cholla/FacetorUtil.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/FacetorUtil.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/Cholla/FacetorUtil.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,134 @@
+//- Class: FacetorUtil
+//- Description: Utility functions used by FactorTool and available to other classes.
+//               FacetorUtil uses template functions that accepts both CubitNode, CubitTri, CubitEdge classes 
+//-              and CubitPoint, CubitFacet, CubitFacetEdge classes.  CubitPoint, CubitFacet, and 
+//-              CubitFacetEdge classes have been modified to account for the difference between the mdb
+//=              entities and geometric entities.
+//-------------------------------------------------------------------------
+// Filename      : FacetorTool.hpp
+//
+// Purpose       : 2D Delaunay Mesher
+//
+// Creator       : Christopher Hynes
+//
+// Creation Date : 5/31/2002
+//
+// Owner         : Steve Owen
+//-------------------------------------------------------------------------
+
+#ifndef FACETOR_UTIL_HPP
+#define FACETOR_UTIL_HPP
+
+
+#include "CubitDefines.h"
+class ParamTool;
+
+template<class SURF, class TRI, class EDGE, class NODE, class TRICHILD, class NODECHILD, class SIZEFUNC>
+class FacetorUtil
+{
+public:
+  FacetorUtil(){}
+  ~FacetorUtil(){}
+
+    //- Insert one node into a Delaunay mesh
+  static CubitStatus insert_node(NODE *node_ptr,
+                                 DLIList<TRI*>& facet_list,
+                                 SURF* surface_ptr,
+                                 int& curr_visit_flag,
+                                 TRI*& last_tri);
+
+    // Insert a node at the circumcenter of a tri
+  static CubitStatus insert_at_circumcenter(TRI *tri_ptr,
+                                            DLIList<TRI*>& facet_list,
+                                            TRI*& start_tri,
+                                            int& curr_visit_flag,
+                                            SURF* surface_ptr,
+                                            DLIList<TRI*>* sorted_lists,
+                                            const int num_lists,
+                                            const double interval,
+                                            const double quality_angle,
+                                            SIZEFUNC* sizing_function,
+                                            ParamTool* p_tool);
+
+    // Compute the angles at the triangle vertices and classify
+    // by its worst triangle
+  static CubitStatus classify_tri_by_angle(TRI* tri_ptr,
+                                           DLIList<TRI*>* sorted_lists,
+                                           const int num_lists,
+                                           const double interval,
+                                           const double quality_angle);
+
+private:
+
+    //Get the tri_visited flag.
+  static CubitBoolean tri_visited(TRI *tri_ptr,
+                                  int curr_visit_flag);
+
+    //Set the tri_visited flag.
+  static void tri_visited(TRI *tri_ptr,
+                          CubitBoolean visited,
+                          int curr_visit_flag);
+  
+    //Search every TRI until the one that the_point is in
+    //is found.
+  static CubitStatus exhaustive_locate_point(CubitVector& the_point,
+                                             DLIList<TRI*>& facet_list,
+                                             TRI*& tri_ptr);
+
+  static CubitStatus point_in_circumcircle(CubitVector& the_point,
+                                           TRI* tri_ptr,
+                                           DLIList<TRI*>& tri_list,
+                                           SURF* surface_ptr,
+                                           int curr_visit_flag);
+
+    //Find the TRI in facet_list that the_point is in.
+    //If starting_tri is not NULL the search will begin
+    //with it.
+  static CubitStatus locate_point(CubitVector& the_point,
+                                  DLIList<TRI*>& facet_list,
+                                  TRI* starting_tri,
+                                  SURF* owning_surface,
+                                  TRI*& tri_ptr);
+
+    //check the void created in Bowyer-Watson to ensure the boundary
+    //seems valid.  
+  static CubitStatus valid_void( NODE * /*point_ptr*/,
+                                 DLIList<TRI *> &tri_list,
+                                 SURF* surface_ptr,
+                                 int curr_visit_flag);
+
+  static CubitStatus natural_neighbor_tris(CubitVector& the_point,
+                                           DLIList<TRI*>& facet_list,
+                                           TRI*& start_tri,
+                                           SURF* surface_ptr,
+                                           int& curr_visit_flag,
+                                           DLIList<TRI*>& tri_list);
+
+   //- Bowyer-Watson insertion into an existing Delaunay Mesh
+  static CubitStatus bowyer_watson_insert(NODE* point_ptr,
+                                          DLIList<TRI*>& tri_list,
+                                          DLIList<TRI*>& facet_list,
+                                          int& curr_visit_flag,
+                                          SURF* surf_ptr,
+                                          TRI*& last_tri);
+
+    //Return true if all three points in tri_ptr are colinear.
+    //Return false otherwise.
+  static CubitBoolean are_nodes_colinear(TRI* tri_ptr);
+
+  static CubitVector& circumcenter(TRI* tri_ptr);
+
+  static double get_size(CubitVector &cc, TRI *tri_ptr);
+
+    // get and set the tri sort array index that this tri is in
+  static void tri_sort_list( TRI *tri_ptr, int sort_list_index );
+  static int tri_sort_list( TRI *tri_ptr );
+
+  static double radius(TRI* tri_ptr);  
+};
+
+// Added by CAT for NT port
+#if defined(TEMPLATE_DEFS_INCLUDED)
+  #include "FacetorUtil.cpp"
+#endif
+#endif

Modified: cgm/branches/cubit/geom/Cholla/LoopParamTool.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/LoopParamTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/LoopParamTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -59,7 +59,8 @@
 // Author: Shiraj Khan
 // Date: 1/21/2003
 //===================================================================================
-CubitStatus LoopParamTool::new_space_LoopParam( DLIList<DLIList<CubitPoint *>*> &loops_cubit_points)
+CubitStatus LoopParamTool::new_space_LoopParam( DLIList<DLIList<CubitPoint *>*> &loops_cubit_points,
+                                                CubitVector* normal)
 {
 	
   int ii;
@@ -131,7 +132,13 @@
     //(vec1) crossproduct (vec2)
     // where vec1 and vec2 are the vectors originating from a common point( center of mass of a plane) and  
     // lying on the plane.
-  if ( determinant_aa == 0.0 )
+  if(normal){
+    a = normal->x();
+    b = normal->y();
+    c = normal->z();
+    d = -(a*Xc + b*Yc + c*Zc );
+  }
+  else if ( determinant_aa == 0.0 )
   {
     sub_loops_cubit_points = loops_cubit_points.get_and_step();
     point1 = sub_loops_cubit_points->get_and_step();
@@ -350,7 +357,12 @@
     for ( jj = 0; jj < sub_loop_cubit_points->size(); jj++ )
     {
       point_ptr = sub_loop_cubit_points->get_and_step();
-      TDVector *td_pos = new TDVector(point_ptr->coordinates());
+      ToolData* td = point_ptr->get_TD( &TDVector::is_td_vector );
+      TDVector* td_pos = NULL;
+      if( NULL == td )
+          td_pos = new TDVector(point_ptr->coordinates());
+      else
+          td_pos = static_cast<TDVector*>( td );
       point_ptr->add_TD(td_pos);
       point_coordinates = point_ptr->coordinates();
 			
@@ -376,7 +388,7 @@
 // Author: Shiraj Khan
 // Date: 1/21/2003
 //===================================================================================
-CubitStatus LoopParamTool::transform_to_uv(CubitVector &, CubitVector &) 
+CubitStatus LoopParamTool::transform_to_uv(const CubitVector &, CubitVector &) 
 {
   PRINT_ERROR("This function is not appropriate for the the LoopParamTool.\n");
   assert(0);
@@ -410,7 +422,7 @@
 // Author: Shiraj Khan
 // Date: 1/21/2003
 //===================================================================================
-CubitStatus LoopParamTool::transform_to_xyz(CubitVector &, CubitVector &) 
+CubitStatus LoopParamTool::transform_to_xyz(CubitVector &, const CubitVector &) 
 {
   PRINT_ERROR("This function is not appropriate for the the LoopParamTool.\n");
   assert(0);
@@ -536,154 +548,140 @@
 CubitStatus LoopParamTool::check_selfintersecting_coincident_edges(DLIList<DLIList<CubitPoint *>*> 
                                                                    &loops_bounding_points)
 {
+    //This function checks each line segment against every other line segment
+    //to see if they intersect or overlap.  Each line will be described
+    //by the following equations:
+    //
+    // Pa = P1 + ua( P2 - P1 )
+    // Pb = P3 + ub( P4 - P3 )
+    //
+    //Setting the Pa equal to Pb and solving for ua and ub you will get two
+    //equation.  Both will have the common denominator:
+    //
+    // denom = ( (uv4.y() - uv3.y()) * (uv2.x() - uv1.x() ) -
+    //         (uv4.x() - uv3.x()) * (uv2.y() - uv1.y() ) )
+    //
+    //And the numerators will be:
+    //
+    // numer_a = ( (uv4.x() - uv3.x()) * (uv1.y() - uv3.y() ) -
+    //          (uv4.y() - uv3.y()) * (uv1.x() - uv3.x() ) )
+    //      
+    // numer_b = ( (uv2.x() - uv1.x()) * (uv1.y() - uv3.y() ) -
+    //           (uv2.y() - uv1.y()) * (uv1.x() - uv3.x() ) )
+    //
+    //ua and ub then become:
+    //
+    // ua = numer_a / denom
+    // ub = numer_b / denom
+    //
+    //If the lines are parallel then denom will be zero.  If they are
+    //also coincedent then the numerators will also be zero.  For the
+    //segments to intersect ua and ub need to both be between 0
+    //and 1.
+  
   int ii, jj, kk, ll;
-  DLIList<CubitPoint *> *sub_loops_bounding_points1, *sub_loops_bounding_points2;
-  CubitPoint *start_point1, *end_point1, *start_point2, *end_point2;
-  CubitVector uv1, uv2, uv3, uv4;
-  CubitVector u, v, w;
-  double s,t;
-  int flag = 1;
   
-  
   for ( ii = 0; ii < loops_bounding_points.size(); ii++ )
   {
-    sub_loops_bounding_points1 = loops_bounding_points.next(ii);
+    DLIList<CubitPoint*>* sub_loops_bounding_points1 = loops_bounding_points.next(ii);
     for( jj = 0; jj < sub_loops_bounding_points1->size(); jj++ )
     {
-		  
-      start_point1 = sub_loops_bounding_points1->next(jj);//
+      CubitPoint* start_point1 = sub_loops_bounding_points1->next(jj);
+      CubitPoint* end_point1 = NULL;
       if ( jj == sub_loops_bounding_points1->size()-1 )
          end_point1 = sub_loops_bounding_points1->next(0);
       else
          end_point1 = sub_loops_bounding_points1->next(jj+1);
-      uv1 = start_point1->coordinates();
-      uv2 = end_point1->coordinates();
-		  
-      if ( (uv1.x() > EPSILON_LOWER) && (uv1.x() < EPSILON_UPPER) )
-         uv1.x(0.0);
-      if ( (uv1.y() > EPSILON_LOWER) && (uv1.y() < EPSILON_UPPER) )
-         uv1.y(0.0);
-      if ( (uv1.z() > EPSILON_LOWER) && (uv1.z() < EPSILON_UPPER) )
-        uv1.z(0.0);
-      if ( (uv2.x() > EPSILON_LOWER) && (uv2.x() < EPSILON_UPPER) )
-        uv2.x(0.0);
-      if ( (uv2.y() > EPSILON_LOWER) && (uv2.y() < EPSILON_UPPER) )
-        uv2.y(0.0);
-      if ( (uv2.z() > EPSILON_LOWER) && (uv2.z() < EPSILON_UPPER) )
-        uv2.z(0.0);
+      CubitVector uv1 = start_point1->coordinates();
+      CubitVector uv2 = end_point1->coordinates();
 
-      for ( kk = 0; kk < loops_bounding_points.size(); kk++ )
+        //Start with the current loop in the list.  The previous
+        //lists have already been checked against this list.
+      for ( kk = ii; kk < loops_bounding_points.size(); kk++ )
       {
-        sub_loops_bounding_points2 = loops_bounding_points.next(kk);
+        DLIList<CubitPoint*>* sub_loops_bounding_points2 = loops_bounding_points.next(kk);
         for ( ll = 0; ll < sub_loops_bounding_points2->size(); ll++ )
         {
-          start_point2 = sub_loops_bounding_points2->next(ll);//
+          CubitPoint* start_point2 = sub_loops_bounding_points2->next(ll);
+          CubitPoint* end_point2 = NULL;
           if ( ll == sub_loops_bounding_points2->size()-1 )
             end_point2 = sub_loops_bounding_points2->next(0);
           else
             end_point2 = sub_loops_bounding_points2->next(ll+1);
-          uv3 = start_point2->coordinates();
-          uv4 = end_point2->coordinates();
+          CubitVector uv3 = start_point2->coordinates();
+          CubitVector uv4 = end_point2->coordinates();
 
           if ( start_point1 == end_point2 || start_point1== start_point2 ||
                end_point1 == start_point2 || end_point1 == end_point2 )
             continue;
           
-          if ( (uv3.x() > EPSILON_LOWER) && (uv3.x() < EPSILON_UPPER) )
-            uv3.x(0.0);
-          if ( (uv3.y() > EPSILON_LOWER) && (uv3.y() < EPSILON_UPPER) )
-            uv3.y(0.0);
-          if ( (uv3.z() > EPSILON_LOWER) && (uv3.z() < EPSILON_UPPER) )
-            uv3.z(0.0);
-          if ( (uv4.x() > EPSILON_LOWER) && (uv4.x() < EPSILON_UPPER) )
-            uv4.x(0.0);
-          if ( (uv4.y() > EPSILON_LOWER) && (uv4.y() < EPSILON_UPPER) )
-            uv4.y(0.0);
-          if ( (uv4.z() > EPSILON_LOWER) && (uv4.z() < EPSILON_UPPER) )
-            uv4.z(0.0);
-          
           if ( (uv1 == uv3) && (uv2 == uv4) )
             continue;
           
-				  
-            // If condition to check that both points (uv3 and uv4 )lie on
-            //the straight line through uv1 and uv2
-          if ( (uv3.y()*(uv2.x()-uv1.x()) ==
-                ((uv2.y()-uv1.y()) * uv3.x()+ uv1.y()*uv2.x()-uv1.x()*uv2.y()) ) &&
-               (uv4.y()*(uv2.x()-uv1.x()) ==
-                ((uv2.y()-uv1.y()) * uv4.x()+ uv1.y()*uv2.x()-uv1.x()*uv2.y())) )
+          double denom = ( (uv4.y() - uv3.y()) * (uv2.x() - uv1.x() ) -
+                           (uv4.x() - uv3.x()) * (uv2.y() - uv1.y() ) );
+          
+          double numer_a = ( (uv4.x() - uv3.x()) * (uv1.y() - uv3.y() ) -
+                             (uv4.y() - uv3.y()) * (uv1.x() - uv3.x() ) );
+          
+          double numer_b = ( (uv2.x() - uv1.x()) * (uv1.y() - uv3.y() ) -
+                             (uv2.y() - uv1.y()) * (uv1.x() - uv3.x() ) );
+          
+          if( denom < CUBIT_RESABS && denom > -CUBIT_RESABS )
           {
-            
-              // This condition to check that one of the 2 points (uv3 and uv4)
-              //lie between uv1 and uv2 or two edges exactly overlapping
-            if ( ( (( uv3.x() > uv1.x()) && (uv3.x() < uv2.x())) ||
-                   (( uv3.x() > uv2.x()) && (uv3.x() < uv1.x())) ) ||
-                 ( (( uv4.x() > uv1.x()) && (uv4.x() < uv2.x())) ||
-                   (( uv4.x() > uv2.x()) && (uv4.x() < uv1.x())) ) ||
-                 ( (( uv3.y() > uv1.y()) && (uv3.y() < uv2.y())) ||
-                   (( uv3.y() > uv2.y()) && (uv3.y() < uv1.y())) ) ||
-                 ( (( uv4.y() > uv1.y()) && (uv4.y() < uv2.y())) ||
-                   (( uv4.y() > uv2.y()) && (uv4.y() < uv1.y())) ) ||
-                 (( uv1 == uv3 ) && ( uv2 == uv4 )) ||
-                 (( uv1 == uv4 ) && ( uv2 == uv3 )) )
+              //The lines are parallel.  Check the numerators to
+              //see if they are coincident.
+            if( numer_a < CUBIT_RESABS && numer_a > -CUBIT_RESABS &&
+                numer_b < CUBIT_RESABS && numer_b > -CUBIT_RESABS )
             {
-              PRINT_ERROR("Can't mesh due to coincident edges \n\n\n");
-              flag = 0;
-              break;
+                //The lines are coincident.  Now see if the segments
+                //over lap.
+              double ua;
+              double ub;
+              if( (uv2.x() - uv1.x()) < CUBIT_RESABS &&
+                  (uv2.x() - uv1.x()) > -CUBIT_RESABS )
+              {
+		if( (uv2.y() - uv1.y() < CUBIT_RESABS &&
+		     uv2.y() - uv1.y() > -CUBIT_RESABS)){
+			PRINT_ERROR("Can't mesh due to zero-length edge.\n");
+			return CUBIT_FAILURE;
+		}
+                ua = (uv3.y() - uv1.y() ) / ( uv2.y() - uv1.y() );
+                ub = (uv4.y() - uv1.y() ) / ( uv2.y() - uv1.y() );
+              }
+              else
+              {
+                ua = (uv3.x() - uv1.x() ) / ( uv2.x() - uv1.x() );
+                ub = (uv4.x() - uv1.x() ) / ( uv2.x() - uv1.x() );
+              }
+                  
+              if( ua > CUBIT_RESABS && ua < (1.0 - CUBIT_RESABS ) ||
+                  ub > CUBIT_RESABS && ub < (1.0 - CUBIT_RESABS ))
+              {
+                  //The segments overlap.
+                PRINT_ERROR("Can't mesh due to coincident edges \n\n\n");
+                return CUBIT_FAILURE;
+              }
             }
           }
-          
-          u = uv2 - uv1;
-          v = uv4 - uv3;
-          w = uv1 - uv3;
-          s = v.x()*u.y()-v.y()*u.x();
-          t = u.x()*v.y()-u.y()*v.x();
-          if ( s < CUBIT_RESABS && s > -CUBIT_RESABS)
-            s = CUBIT_DBL_MAX;
           else
-            s = ( v.y()*w.x()-v.x()*w.y() )/( s );
-          if ( t < CUBIT_RESABS && t > -CUBIT_RESABS)
-            t = CUBIT_DBL_MAX;
-          else
-            t = ( u.x()*w.y()-u.y()*w.x() )/( t );
-
-            //this condition to check whether two segments intersect
-          if ( (s > (0.0+CUBIT_RESABS) && s < (1.0-CUBIT_RESABS)) &&
-               (t > (0.0+CUBIT_RESABS) && t < (1.0-CUBIT_RESABS)))
           {
-            PRINT_ERROR("1. Can't mesh due to self intersecting edges \n\n\n");
-            flag = 0;
-            break;
+            double ua = numer_a / denom;
+            double ub = numer_b / denom;
+
+            if( ( (ua > CUBIT_RESABS && ua < (1.0-CUBIT_RESABS)) &&
+                  (ub > CUBIT_RESABS && ub < (1.0-CUBIT_RESABS))) )
+            {
+              PRINT_ERROR("Can't mesh due to self intersecting edges \n\n\n");
+              return CUBIT_FAILURE;
+            }
           }
-          else if( (double_equal(s, 0.0) || double_equal( s,1.0) ) && 
-                   ((t > (0.0+CUBIT_RESABS)) && (t < (1.0-CUBIT_RESABS))))
-          {
-            PRINT_ERROR("2. Can't mesh due to self intersecting edges \n\n\n");
-              flag = 0;
-              break;
-          }
-          else if ( (double_equal(t,0.0) || double_equal(t,1.0) ) && 
-                    ((s > (0.0+CUBIT_RESABS)) && (s < (1.0-CUBIT_RESABS))))
-          {
-            PRINT_ERROR("3. Can't mesh due to self intersecting edges, t = %f, s = %f \n\n\n", t,s);
-            flag = 0;
-            break;
-          }
         }//end of for ( ll )
-        if ( flag == 0 ) break;
       }// end of for ( kk )
-      if ( flag == 0 ) break;
     }//end of for ( jj )
-    if ( flag == 0 ) break;
   }// end of for ( ii )
 
-    //if the self-intersecting and coincident edges are there then return CUBIT_FAILURE
-    // else return CUBIT_SUCCESS
-  if ( flag == 0 )
-    return CUBIT_FAILURE;
-  else 
-    return CUBIT_SUCCESS;
-  
+  return CUBIT_SUCCESS;
 }
 
 bool LoopParamTool::double_equal(double val, double equal_to)

Modified: cgm/branches/cubit/geom/Cholla/LoopParamTool.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/LoopParamTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/LoopParamTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -30,8 +30,8 @@
   ~LoopParamTool();
 	
   virtual CubitStatus set_up_space();
-  virtual CubitStatus transform_to_uv(CubitVector &, CubitVector &);
-  virtual CubitStatus transform_to_xyz(CubitVector &, CubitVector &);
+  virtual CubitStatus transform_to_uv(const CubitVector &, CubitVector &);
+  virtual CubitStatus transform_to_xyz(CubitVector &, const CubitVector &);
     //These functions are required because this is a child of ParamTool.
     //They do nothing.
 
@@ -45,7 +45,8 @@
     ///The calling code is reponsible for removing and deleting the memory of the TDVectors.
     ///
 		                                        
-  CubitStatus new_space_LoopParam( DLIList<DLIList<CubitPoint *>*> &loop_cubit_points);
+  CubitStatus new_space_LoopParam( DLIList<DLIList<CubitPoint *>*> &loop_cubit_points,
+                                   CubitVector* normal = NULL);
     ///
     ///This function must be called first for this tool.  This sets up the plane and
     ///the transformation to the XY plane.

Modified: cgm/branches/cubit/geom/Cholla/Makefile.am
===================================================================
--- cgm/branches/cubit/geom/Cholla/Makefile.am	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/Makefile.am	2010-01-06 19:22:14 UTC (rev 3423)
@@ -21,6 +21,7 @@
     ChollaPoint.cpp \
     ChollaSkinTool.cpp \
     ChollaSurface.cpp \
+    ChollaVolume.cpp \
     ChordalAxis.cpp \
     CubitFacet.cpp \
     CubitFacetData.cpp \
@@ -57,6 +58,7 @@
     ChollaPoint.hpp \
     ChollaSkinTool.hpp \
     ChollaSurface.hpp \
+    ChollaVolume.hpp \
     ChordalAxis.hpp \
     CubitFacet.hpp \
     CubitFacetData.hpp \
@@ -71,6 +73,7 @@
     FacetEntity.hpp \
     FacetEvalTool.hpp \
     FacetorTool.hpp \
+    FacetorUtil.hpp \
     GeoNode.hpp \
     GeoTet.hpp \
     LoopParamTool.hpp \
@@ -93,12 +96,14 @@
   libcholla_la_include_HEADERS += \
     BoundaryConstrainTool.cpp \
     FacetorTool.cpp \
+    FacetorUtil.cpp \
     TetFacetorTool.cpp \
     TDDelaunay.cpp 
 else
   libcholla_la_SOURCES += \
     BoundaryConstrainTool.cpp \
     FacetorTool.cpp \
+    FacetorUtil.cpp \
     TetFacetorTool.cpp \
     TDDelaunay.cpp 
 endif

Modified: cgm/branches/cubit/geom/Cholla/TDGeomFacet.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/TDGeomFacet.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/TDGeomFacet.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -7,7 +7,10 @@
 #include "CubitFacetEdge.hpp"
 #include "CubitFacet.hpp"
 #include "CastTo.hpp"
+#include "ChollaVolume.hpp"
 #include "ChollaSurface.hpp"
+#include "ChollaCurve.hpp"
+#include "ChollaPoint.hpp"
 #include "CubitPoint.hpp"
 
 TDGeomFacet::TDGeomFacet()
@@ -16,6 +19,7 @@
   hitFlag = 0;
   partnerEdgeList = NULL;
   partnerPointList = NULL;
+  onBoundaryFlag = 0;
 }
 
 TDGeomFacet::~TDGeomFacet()
@@ -145,6 +149,27 @@
   }
   return -1;
 }
+void TDGeomFacet::add_cholla_owner( ChollaEntity *cholla_entity )
+{
+  ChollaSurface *cholla_surface = dynamic_cast<ChollaSurface *> (cholla_entity);
+  if (cholla_surface != NULL)
+    add_cholla_surf(cholla_surface);
+  else
+  {
+    ChollaCurve *cholla_curve = dynamic_cast<ChollaCurve *> (cholla_entity);
+    if (cholla_curve != NULL)
+      add_cholla_curve( cholla_curve );
+    else
+    {
+      ChollaPoint *cholla_point = dynamic_cast<ChollaPoint *> (cholla_entity);
+      if (cholla_point != NULL)
+        add_cholla_point( cholla_point );
+      else
+        assert(0); // not a recognized cholla entity
+    }
+  }  
+  return;
+}
 void TDGeomFacet::add_cholla_surf( ChollaSurface *f_s_m )
 {
   int ii;
@@ -201,5 +226,50 @@
   return CUBIT_FALSE;
 }
 
+void TDGeomFacet::reset_TD_as_new()
+{
+  blockId = -1;
+  hitFlag = 0;
+  partnerEdgeList = NULL;
+  partnerPointList = NULL;
+  onBoundaryFlag = 0;
+  ChollaSurfaceList.clean_out();
+  ChollaCurveList.clean_out();
+  myPoints.clean_out();
+    //normal??????;
+    //need to delete these?
+  partnerEdgeList=NULL;
+  partnerPointList=NULL;
 
+}
 
+int TDGeomFacet::geo_type()
+{
+  if (ChollaSurfaceList.size() > 0)
+    return 2;
+  else if (ChollaCurveList.size() > 0)
+    return 1;
+  else if (myPoints.size() > 0)
+    return 0;
+  return -1;
+}
+
+CubitBoolean TDGeomFacet::is_in_volume( ChollaVolume *chvol_ptr )
+{
+  for (int ii=0; ii<ChollaSurfaceList.size(); ii++)
+  {
+    ChollaSurface *chsurf_ptr = ChollaSurfaceList.get_and_step();
+    if (chsurf_ptr->is_in_volume( chvol_ptr ))
+      return CUBIT_TRUE;
+  }
+  for (int jj=0; jj<ChollaCurveList.size(); jj++)
+  {
+    ChollaCurve *chcurv_ptr = ChollaCurveList.get_and_step();
+    if (chcurv_ptr->is_in_volume( chvol_ptr ))
+      return CUBIT_TRUE;
+  }
+  return CUBIT_FALSE;
+}
+
+
+

Modified: cgm/branches/cubit/geom/Cholla/TDGeomFacet.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/TDGeomFacet.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/TDGeomFacet.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -15,8 +15,11 @@
 #include "ToolData.hpp"
 #include "CubitPoint.hpp"
 class FacetEntity;
+class ChollaEntity;
+class ChollaVolume;
 class ChollaSurface;
 class ChollaCurve;
+class ChollaPoint;
 class CubitFacet;
 class CubitFacetEdge;
 
@@ -42,6 +45,9 @@
   DLIList<ChollaCurve*> ChollaCurveList;
     //- list of curves this element (edge) is on
   
+  DLIList<ChollaPoint*> ChollaPointList;
+    //- list chollapoints this element (point) is on 
+  
   DLIList<CubitPoint*> myPoints;
     //- list of associated points for this entity (could be one).
 
@@ -74,6 +80,11 @@
 
   void set_hit_flag(int flag)
     {hitFlag = flag;}
+  
+  int on_boundary(){return onBoundaryFlag;}
+  void on_boundary( int status ){ onBoundaryFlag = status; }
+  
+  void add_cholla_owner(ChollaEntity *cholla_entity);
 
   void add_cholla_surf(ChollaSurface *f_s_m);
 
@@ -97,7 +108,19 @@
 
   void remove_cholla_curve( ChollaCurve *chcurv_ptr )
     {ChollaCurveList.remove( chcurv_ptr );}
+  
+  void add_cholla_point(ChollaPoint *chpt_ptr)
+    {ChollaPointList.append_unique( chpt_ptr );}
 
+  void get_cholla_points(DLIList<ChollaPoint*> &point_list)
+    {point_list =  ChollaPointList;}
+  
+  void remove_cholla_points()
+    {ChollaPointList.clean_out();}
+  
+  void remove_cholla_point( ChollaPoint *point_ptr )
+    { ChollaPointList.remove( point_ptr ); }
+  
   void add_point(CubitPoint *point)
     {myPoints.append(point);}
 
@@ -143,6 +166,8 @@
         return 0;
       else
         return partnerPointList->size(); }
+  
+  CubitBoolean is_in_volume( ChollaVolume *chvol_ptr );
 
   SetDynamicMemoryAllocation(memoryManager)
     //- class specific new and delete operators
@@ -177,6 +202,11 @@
 
   CubitBoolean is_partner( CubitFacetEdge *edge_ptr );
   CubitBoolean is_partner( CubitPoint *point_ptr );
+
+  void reset_TD_as_new();
+  
+  int geo_type();
+  
 };
     
 

Modified: cgm/branches/cubit/geom/Cholla/debug.cpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/debug.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/debug.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -5,6 +5,7 @@
 #include "CubitFacetEdge.hpp"
 #include "GfxDebug.hpp"
 #include "CubitBox.hpp"
+#include "ChollaSurface.hpp"
 
 #include "debug.hpp"
 static int fg_color = CUBIT_MAGENTA;
@@ -62,6 +63,15 @@
   GfxDebug::zoom(box);
 }
 
+
+void dsurfdraw( ChollaSurface *surf)
+{
+  DLIList<FacetEntity*> surface_facets;
+  surf->get_facets(surface_facets);
+  dldraw(surface_facets);
+}
+
+
 void dldraw( DLIList<FacetEntity *> &facet_list )
 {
   FacetEntity *facet_ptr;

Modified: cgm/branches/cubit/geom/Cholla/debug.hpp
===================================================================
--- cgm/branches/cubit/geom/Cholla/debug.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Cholla/debug.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -9,6 +9,8 @@
 class CubitPoint;
 class CubitVector;
 class CubitBox;
+class ChollaSurface;
+
 template <class X> class DLIList;
 
 void dcolor(int icol);
@@ -21,6 +23,8 @@
 
 void dpdraw( CubitPoint *facet_ptr );
 
+void dsurfdraw( ChollaSurface *surf);
+
 void dview();
 
 void dzoom(CubitBox &box);

Modified: cgm/branches/cubit/geom/CubitAttrib.cpp
===================================================================
--- cgm/branches/cubit/geom/CubitAttrib.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CubitAttrib.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -21,8 +21,8 @@
 #include "GeometryQueryTool.hpp"
 
 
-    
 
+
 CubitAttrib::CubitAttrib(RefEntity *attrib_owner)
 {
   attribOwnerEntity = attrib_owner;
@@ -31,12 +31,12 @@
   hasWritten = CUBIT_FALSE;
   deleteAttrib = CUBIT_FALSE;
   nextAttrib = NULL;
-  
+
     // add this to the owner
   if (attrib_owner) attrib_owner->add_cubit_attrib(this);
 }
 
-CubitAttrib::~CubitAttrib() 
+CubitAttrib::~CubitAttrib()
 {
   if( !hasActuated )
     CADeferredAttrib::remove_unactuated_ca( this );
@@ -50,7 +50,7 @@
     ref_ent = entity_list.get_and_step();
     ref_ent->actuate_cubit_attrib(CA_ENTITY_NAME);
     ref_ent->actuate_cubit_attrib ( CA_UNIQUE_ID );
-    ref_ent->actuate_cubit_attrib(CA_SIZING_FUNCTION_SKELETON);    
+    ref_ent->actuate_cubit_attrib(CA_SIZING_FUNCTION_SKELETON);
     ref_ent->actuate_cubit_attrib(CA_MESH_INTERVAL);
     ref_ent->actuate_cubit_attrib(CA_GROUP);
     ref_ent->actuate_cubit_attrib(CA_GENESIS_ENTITY);
@@ -90,10 +90,10 @@
     ref_ent->actuate_cubit_attrib(CA_MATERIAL_BLOCK);
 //#endif
     ref_ent->actuate_cubit_attrib(CA_MERGE_STATUS);
-  } 
+  }
   return CUBIT_SUCCESS;
 }
-  
+
 void CubitAttrib::has_written(CubitBoolean set_has_written)
 {
   hasWritten = set_has_written;
@@ -121,7 +121,7 @@
 {
     //- return true if the csa and this are equivalent
    CubitSimpleAttrib* this_csa_ptr = cubit_simple_attrib();
-       
+
    CubitBoolean equivalent =
        CubitSimpleAttrib::equivalent(csa_ptr, this_csa_ptr);
    delete this_csa_ptr;

Modified: cgm/branches/cubit/geom/CubitAttribUser.cpp
===================================================================
--- cgm/branches/cubit/geom/CubitAttribUser.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CubitAttribUser.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -127,6 +127,9 @@
     GeometryEntity* GE_ptr =
       BTE_ptr->get_geometry_entity_ptr();
     
+    if( NULL == GE_ptr )
+      return CUBIT_FAILURE;
+
       // check for duplicates
     if (DEBUG_FLAG(94))
     {
@@ -171,6 +174,41 @@
   return CUBIT_SUCCESS;
 }
 
+CubitStatus CubitAttribUser::clear_simple_attribs_set_to_actuate()
+{
+  CubitAttrib *cubit_attrib_ptr = NULL;
+  CubitAttrib *next_attrib_ptr = NULL;
+  for(cubit_attrib_ptr = headAttrib;
+      cubit_attrib_ptr != NULL;)
+  {
+    //ignore Assembly and Name attributes
+    next_attrib_ptr = cubit_attrib_ptr->next_attrib();
+    if( cubit_attrib_ptr->int_attrib_type() != CA_ENTITY_NAME && 
+        cubit_attrib_ptr->int_attrib_type() != CA_ASSEMBLY_DATA &&
+        CGMApp::instance()->attrib_manager()->auto_actuate_flag(
+          cubit_attrib_ptr->int_attrib_type()))
+    {
+      remove_cubit_attrib( cubit_attrib_ptr );
+      delete cubit_attrib_ptr;
+    }
+    cubit_attrib_ptr = next_attrib_ptr;
+  }
+ 
+  if (DEBUG_FLAG(94))
+  {
+    PRINT_DEBUG_94("CubitAttribUser::clear_simple_attribs()\n");
+  }
+  TopologyEntity* te_ptr = dynamic_cast<TopologyEntity*>(this);
+  if( !te_ptr )
+    return CUBIT_FAILURE;
+  
+  remove_all_simple_attribute(te_ptr->bridge_manager()->topology_bridge());
+  write_cubit_attrib_by_type(CA_ASSEMBLY_DATA);
+  write_cubit_attrib_by_type( CA_ENTITY_NAME );
+  set_written_flag(CUBIT_FALSE);
+  return CUBIT_SUCCESS; 
+}
+
 CubitStatus CubitAttribUser::clear_simple_attribs()
 {
 
@@ -182,7 +220,7 @@
     //ignore Assembly and Name attributes
     next_attrib_ptr = cubit_attrib_ptr->next_attrib();
     if( cubit_attrib_ptr->int_attrib_type() != CA_ENTITY_NAME && 
-        cubit_attrib_ptr->int_attrib_type() != CA_ASSEMBLY_DATA )
+        cubit_attrib_ptr->int_attrib_type() != CA_ASSEMBLY_DATA)
     {
       remove_cubit_attrib( cubit_attrib_ptr );
       delete cubit_attrib_ptr;
@@ -538,14 +576,14 @@
                      attrib->att_internal_name(), attrib->attrib_owner()->class_name(),
                      attrib->attrib_owner()->id());
       
-      if (attrib->actuate() == CUBIT_FAILURE)
+      if(attrib->actuate() == CUBIT_FAILURE)
       {
         actuate_status = CUBIT_FAILURE;
       }
 
         // need to check again for delete flag, since it might have been set
         // in actuate function
-      if (attrib->delete_attrib() == CUBIT_TRUE)
+      if( attrib->delete_attrib() == CUBIT_TRUE)
       {
         remove_cubit_attrib(attrib);
         delete attrib;
@@ -605,6 +643,7 @@
 
 CubitStatus CubitAttribUser::auto_update_cubit_attrib ()
 {
+
     // for this cau, automatically create and update ca's
 
     // first, create ca's for any attribute type which has its auto
@@ -731,6 +770,14 @@
   return result;
 }
 
+CubitStatus CubitAttribUser::clear_all_simple_attrib_set_to_actuate( DLIList<RefEntity*>& entity_list )
+{
+  CubitStatus result = CUBIT_SUCCESS;
+  for( int i = entity_list.size(); i--; )
+    if( entity_list.get_and_step()->clear_simple_attribs_set_to_actuate() != CUBIT_SUCCESS )
+      result = CUBIT_FAILURE;
+  return result;
+}
 
 void CubitAttribUser::find_cubit_attrib_type (int type,
                                               DLIList<CubitAttrib*>& attrib_list) const

Modified: cgm/branches/cubit/geom/CubitAttribUser.hpp
===================================================================
--- cgm/branches/cubit/geom/CubitAttribUser.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CubitAttribUser.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -69,6 +69,9 @@
 
   CubitStatus clear_simple_attribs();
     // Remove all CubitSimpleAttrib from TopologyBridges.
+
+  CubitStatus clear_simple_attribs_set_to_actuate();
+    // Remove all CubitSimpleAttrib from TopologyBridges if attrib type's actuate was set to true
   
 public:
   CubitStatus auto_read_cubit_attrib ();
@@ -158,6 +161,9 @@
   static CubitStatus clear_all_simple_attrib( DLIList<RefEntity*>& entity_list );
     //- remove all CubitSimpleAttrib from TopologyBridges.
 
+  static CubitStatus clear_all_simple_attrib_set_to_actuate( DLIList<RefEntity*>& entity_list );
+    //- remove all CubitSimpleAttrib from TopologyBridges that have actuate flag set to true.
+
 private:
   static void auto_reset_cubit_attrib(DLIList<RefEntity*> ref_ents);
     //- set the update flag on all attribs on these entities and their children to false

Modified: cgm/branches/cubit/geom/CubitGeomConfigure.h.in
===================================================================
--- cgm/branches/cubit/geom/CubitGeomConfigure.h.in	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CubitGeomConfigure.h.in	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,13 +4,21 @@
 
 #cmakedefine CUBIT_GEOM_BUILD_SHARED_LIBS
 
-#if defined(WIN32) && defined(CUBIT_GEOM_BUILD_SHARED_LIBS)
+#if defined(CUBIT_GEOM_BUILD_SHARED_LIBS)
 #if defined(cubit_geom_EXPORTS)
-#define CUBIT_GEOM_EXPORT __declspec(dllexport)
+# if defined(WIN32)
+#  define CUBIT_GEOM_EXPORT __declspec(dllexport)
+# elif defined(__GNUC__) && __GNUC__ >= 4
+#  define CUBIT_GEOM_EXPORT __attribute__ ((visibility("default")))
+# endif
 #else
-#define CUBIT_GEOM_EXPORT __declspec(dllimport)
+# if defined(WIN32)
+#  define CUBIT_GEOM_EXPORT __declspec(dllimport)
+# endif
 #endif
-#else
+#endif
+
+#ifndef CUBIT_GEOM_EXPORT
 #define CUBIT_GEOM_EXPORT
 #endif
 

Modified: cgm/branches/cubit/geom/Curve.cpp
===================================================================
--- cgm/branches/cubit/geom/Curve.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Curve.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -245,15 +245,25 @@
   {
       // If not within parameter range, return
       // the the closest endpoint
+    CubitVector start, end;
+    position_from_u( start_param, start );
+    position_from_u( end_param, end );
+
     if( (param < start_param) || (param > end_param) )
     {
-      CubitVector start, end;
-      position_from_u( start_param, start );
-      position_from_u( end_param, end );
       result = ( (start - result).length_squared() < 
                  (end - result).length_squared() ) ? start : end ;
     }
+    else
+    {
+      double tmp_dist_sq = (from_pt - result).length_squared();
+      if( (start-from_pt).length_squared() < tmp_dist_sq )
+        result = start;
+      else if( (end-from_pt).length_squared() < tmp_dist_sq )
+        result = end;
+    }
   }
+
   
   return CUBIT_SUCCESS;
 }

Modified: cgm/branches/cubit/geom/CurveOverlapFacet.cpp
===================================================================
--- cgm/branches/cubit/geom/CurveOverlapFacet.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CurveOverlapFacet.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -6,6 +6,7 @@
 
 #include "CurveOverlapFacet.hpp"
 #include "IntersectionTool.hpp"
+#include "GfxPreview.hpp"
 
 //AnalyticGeometryTool* CurveOverlapFacet::agt = AnalyticGeometryTool::instance();
 
@@ -270,3 +271,20 @@
 
   return dP.length();   // return the closest distance
 }
+
+void CurveOverlapFacet::draw( int color ) 
+{
+  GfxPreview::draw_line( p0, p1, color );
+  return;
+}
+
+CubitVector CurveOverlapFacet::start_point()
+{
+  return p0; 
+}
+
+CubitVector CurveOverlapFacet::end_point()
+{
+  return p1; 
+}
+

Modified: cgm/branches/cubit/geom/CurveOverlapFacet.hpp
===================================================================
--- cgm/branches/cubit/geom/CurveOverlapFacet.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/CurveOverlapFacet.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -32,6 +32,11 @@
 
   double facet_to_facet_distance( CurveOverlapFacet *other_facet );
 
+  void draw( int color ); 
+
+  CubitVector start_point();
+  CubitVector end_point();
+
 protected:
    
 private:

Modified: cgm/branches/cubit/geom/DAG.hpp
===================================================================
--- cgm/branches/cubit/geom/DAG.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/DAG.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -71,6 +71,8 @@
 
   ~DAG() ;
     //- Destructor
+    
+  static void delete_instance() { if(instance_) delete instance_; };
 
   void add_deactivated_DAG_node(ModelEntity* deactivatedDAGNodePtr) ;
     //R void

Modified: cgm/branches/cubit/geom/DagDrawingTool.hpp
===================================================================
--- cgm/branches/cubit/geom/DagDrawingTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/DagDrawingTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -58,10 +58,10 @@
 
 class CUBIT_GEOM_EXPORT DagDrawingTool
 {
-	public:
+  public:
 	
-		static DagDrawingTool* instance();
-		~DagDrawingTool();
+  static DagDrawingTool* instance();
+  ~DagDrawingTool();
 /*		
 		void draw_DAG( DLIList<Body*>&      body_list,           int down );
 		void draw_DAG( DLIList<RefVolume*>& volume_list, int up, int down );
@@ -135,11 +135,18 @@
 		
 		int window_id() const;
 		//The last window drawn in my DagDrawingTool
-*/		
+*/	
+  
+  //! Print the DAG of the specified surfaces.
   void printDag(DLIList<RefFace*> &face_list, int depth);
+
+  //! Print the DAG of the specified body.
   void printDag(DLIList<Body*> &body_list, int depth);
+
+  //! Print the DAG of the entities. 
   void printDag(DLIList<ModelEntity*> &entity_list, int depth);
   
+  //! Print the DAG of the entity. 
   void printDag( ModelEntity* ME_ptr, int depth );
 
 	protected:

Modified: cgm/branches/cubit/geom/GSaveOpen.cpp
===================================================================
--- cgm/branches/cubit/geom/GSaveOpen.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GSaveOpen.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -8,6 +8,7 @@
 #include "RefEntityFactory.hpp"
 
 // Initialize Globals
+int GSaveOpen::performingUndo = 0;
 int GSaveOpen::gsoSetsIds = 0;
 int GSaveOpen::gsoIncBodyId = 0;
 int GSaveOpen::gsoIncRefVolumeId = 0;
@@ -20,13 +21,25 @@
 GSaveOpen::GSaveOpen()
 {
   RefEntityFactory *ref = RefEntityFactory::instance();
-
-  gsoSetsIds = 1;
-  gsoIncBodyId = ref->current_body_id();
-  gsoIncRefVolumeId = ref->current_volume_id();
-  gsoIncRefFaceId = ref->current_face_id();
-  gsoIncRefEdgeId = ref->current_edge_id();
-  gsoIncRefVertexId = ref->current_vertex_id();
+  
+  if( performingUndo == 1 )
+  {
+    gsoSetsIds = 0;
+    gsoIncBodyId = 0;
+    gsoIncRefVolumeId = 0; 
+    gsoIncRefFaceId = 0; 
+    gsoIncRefEdgeId = 0; 
+    gsoIncRefVertexId = 0;
+  }  
+  else
+  {
+    gsoSetsIds = 1;
+    gsoIncBodyId = ref->current_body_id();
+    gsoIncRefVolumeId = ref->current_volume_id();
+    gsoIncRefFaceId = ref->current_face_id();
+    gsoIncRefEdgeId = ref->current_edge_id();
+    gsoIncRefVertexId = ref->current_vertex_id();
+  }
   gsoErrorCount = 0;
 }
 

Modified: cgm/branches/cubit/geom/GSaveOpen.hpp
===================================================================
--- cgm/branches/cubit/geom/GSaveOpen.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GSaveOpen.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -25,10 +25,10 @@
     static int get_id_inc( RefEntity *entity );
     static void set_error();
     static void add_error_id( int id );
+    static int performingUndo;
 
 protected:
    static int gsoSetsIds;
-
    static int gsoIncBodyId;
    static int gsoIncRefVolumeId;
    static int gsoIncRefFaceId;

Modified: cgm/branches/cubit/geom/GeomMeasureTool.cpp
===================================================================
--- cgm/branches/cubit/geom/GeomMeasureTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeomMeasureTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -40,6 +40,10 @@
 #include "ProgressTool.hpp"
 #include "AppUtil.hpp"
 
+#include <set>
+#include <map>
+#include <stack>
+#include <algorithm>
 
 void GeomMeasureTool::get_edges_from_list(DLIList <RefEntity*> &entity_list,
                                           DLIList <RefEdge*> &ref_edges )
@@ -1175,31 +1179,98 @@
     ratio = (double) ((double)merged_surfaces / (double)unmerged_surfaces);
 }
 
-void GeomMeasureTool::report_intersected_bodies(DLIList <RefVolume*> &volume_list,
-                                                DLIList <Body*> &intersection_list)
+void GeomMeasureTool::report_intersected_volumes(DLIList <RefVolume*> &ref_vols,
+                                                 DLIList <RefVolume*> &intersection_list)
 {
-  DLIList <Body*> bodies;
-  get_bodies_from_list( volume_list, bodies);
-  report_intersected_bodies( bodies, intersection_list);
+  DLIList <RefVolume*> results;
+  RefVolume *curr_vol;
+  int i, j;
+  ProgressTool *progress_ptr = NULL;
+  int total_volumes = ref_vols.size();
+  if (total_volumes > 5)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Overlapping Volumes Progress", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+  double curr_percent = 0.0;
+
+  for( i = 0; i < ref_vols.size(); i++ )
+  {
+    curr_vol = ref_vols.next(i);
+
+    //is this body a multi-volume-body?
+    Body *single_volume_body = curr_vol->body();
+    DLIList<RefVolume*> body_vols;
+    single_volume_body->ref_volumes( body_vols );
+    if( body_vols.size() > 1 )
+      single_volume_body = NULL;
+      
+    for( j = (i + 1); j < ref_vols.size(); j++ )
+    {
+      RefVolume *curr_vol2 = ref_vols.next(j);
+      if ( CubitMessage::instance()->Interrupt() )
+      {
+          //interrpt.  We need to exit.
+        if ( progress_ptr != NULL )
+        {
+          progress_ptr->end();
+        }
+          //just leave what has been calculated...
+        return;
+      }
+
+      Body *single_volume_body2 = curr_vol2->body();
+      DLIList<RefVolume*> body_vols2;
+      single_volume_body2->ref_volumes( body_vols2 );
+      if( body_vols2.size() > 1 )
+        single_volume_body2 = NULL;
+
+      //update the progress..
+      if ( progress_ptr != NULL )
+      {
+        curr_percent = ((double)(i+1))/((double)(total_volumes));
+        progress_ptr->percent(curr_percent);
+      }
+    
+      //if both are single-volume-bodies
+      if( single_volume_body && single_volume_body2 )
+      {
+        if( GeometryQueryTool::instance()->bodies_overlap( single_volume_body,
+                                                       single_volume_body2 ) )
+        {
+          intersection_list.append( curr_vol );
+          intersection_list.append( curr_vol2 );
+        }
+      }
+      else if( GeometryQueryTool::instance()->volumes_overlap( curr_vol, curr_vol2 ) )
+      {
+       intersection_list.append( curr_vol );
+       intersection_list.append( curr_vol2 );
+      }
+    }
+  }
   
+  if ( progress_ptr != NULL )
+  {
+    progress_ptr->end();
+  }
 }
 
 void GeomMeasureTool::report_intersected_bodies(DLIList <Body*> &ref_bodies,
                                                 DLIList <Body*> &intersection_list)
 {
-  
-  DLIList <Body*> results;
   Body *curr_body, *curr_body_2;
   int ii, jj;
   ProgressTool *progress_ptr = NULL;
-  char title[29];
   int total_bodies = ref_bodies.size();
   if (total_bodies > 5)
   {
-    strcpy(title, "Overlapping Volumes Progress");
     progress_ptr = AppUtil::instance()->progress_tool();
     assert(progress_ptr != NULL);
-    progress_ptr->start(0, 100, title, NULL, CUBIT_TRUE, CUBIT_TRUE);
+    progress_ptr->start(0, 100, "Overlapping Volumes Progress", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
   }
   double curr_percent = 0.0;
  
@@ -1211,7 +1282,6 @@
     for( jj = (ii + 1); jj < ref_bodies.size(); jj++ )
     {
       curr_body_2 = ref_bodies.next(jj);
-      results.clean_out();
       if ( CubitMessage::instance()->Interrupt() )
       {
           //interrpt.  We need to exit.
@@ -1224,11 +1294,10 @@
       }
 
       if (GeometryQueryTool::instance()->bodies_overlap(curr_body,
-                                                         curr_body_2) )
+                                                        curr_body_2) )
       {
         intersection_list.append(curr_body);
         intersection_list.append(curr_body_2);
-        GeometryQueryTool::instance()->delete_Body(results);
       }
     }
        //update the progress..
@@ -1375,20 +1444,6 @@
   } 
 }
 
-void GeomMeasureTool::ratio_of_shells_to_volumes(int number_of_shells,
-                                                 DLIList <RefVolume*> &ref_volumes,
-                                                 int &number_of_volumes,
-                                                 double &ratio)
-{
-  int ii, number = 0;
-
-  for( ii = ref_volumes.size(); ii > 0; ii-- )
-    number++;
-  number_of_volumes = number;
-
-  ratio = (double) ((double)number_of_shells / (double)number_of_volumes);
-  
-}
 void GeomMeasureTool::print_surface_measure_summary( DLIList <RefFace*> &ref_faces )
                                                   
 {
@@ -1837,6 +1892,725 @@
   return;
 
 }
+
+// Find all of the surfaces in the given volumes that have narrow regions.
+void GeomMeasureTool::find_surfs_with_narrow_regions(DLIList <RefVolume*> &ref_vols,
+                                          double tol,
+                                          DLIList <RefFace*> &surfs_with_narrow_regions)
+{
+  int j;
+  double tol_sq = tol*tol;
+
+  int ii, jj;
+  DLIList <RefFace*> ref_faces, temp_faces;
+  RefVolume *ref_vol;
+  RefFace *curr_face;
+  for ( ii = 0; ii < ref_vols.size(); ii++ )
+  {
+    DLIList<RefFace*> faces;
+    ref_vol = ref_vols.get_and_step();
+    ref_vol->ref_faces(faces);
+    for ( jj = faces.size(); jj > 0; jj-- )
+    {
+      curr_face = faces.get_and_step();
+      curr_face->marked(0);
+      temp_faces.append(curr_face);
+    }
+  }
+
+  //uniquely add the faces.
+  for ( jj = temp_faces.size(); jj > 0; jj-- )
+  {
+    curr_face = temp_faces.get_and_step();
+    if ( curr_face->marked()== 0 )
+    {
+      curr_face->marked(1);
+      ref_faces.append(curr_face);
+    }
+  }
+
+  int num_faces = ref_faces.size();
+
+  ProgressTool *progress_ptr = NULL;
+  if (num_faces > 20)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Finding Surfaces with Narrow Regions", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+
+  int total_faces = 0;
+  double curr_percent = 0.0;
+
+  for(j=0; j<num_faces; j++)
+  {
+    DLIList<CubitVector> split_pos1_list;
+    DLIList<CubitVector> split_pos2_list;
+    RefFace *cur_face = ref_faces.get_and_step();
+    total_faces++;
+    if ( progress_ptr != NULL )
+    {
+      curr_percent = ((double)(total_faces))/((double)(num_faces));
+      progress_ptr->percent(curr_percent);
+    }
+
+    if ( CubitMessage::instance()->Interrupt() )
+    {
+        //interrpt.  We need to exit.
+      if ( progress_ptr != NULL )
+        progress_ptr->end();
+        //just leave what has been calculated...
+      return;
+    }
+    find_split_points_for_narrow_regions(cur_face,
+      tol, split_pos1_list, split_pos2_list); 
+    if(split_pos1_list.size() > 0)
+      surfs_with_narrow_regions.append_unique(cur_face);
+  }
+
+  if ( progress_ptr != NULL )
+    progress_ptr->end();
+}
+
+bool GeomMeasureTool::is_surface_narrow(RefFace *face, double small_curve_size)
+{
+  bool ret = true;
+  DLIList<RefEdge*> edges;
+  face->ref_edges(edges);
+  RefVolume *vol = face->ref_volume();
+  int i, j;
+  double dist_sq = small_curve_size*small_curve_size;
+  double proj_dist = 1.2 * small_curve_size;
+  for(i=edges.size(); i>0 && ret == true; i--)
+  {
+    RefEdge *cur_edge = edges.get_and_step();
+    double edge_length = cur_edge->measure();
+    if(edge_length > small_curve_size)
+    {
+      int num_incs = (int)(edge_length/small_curve_size) + 1;
+      double start, end;
+      cur_edge->get_param_range(start, end);
+      double dt = small_curve_size*((end-start)/edge_length);
+      double t = start;
+      bool one_bad = false;
+      for(j=0; j<num_incs && ret == true; j++)
+      {
+        CubitVector pos1, tangent;
+        cur_edge->position_from_u(t, pos1);
+        cur_edge->tangent(pos1, tangent, face);
+        CubitVector norm = face->normal_at(pos1, vol);
+        CubitVector indir = norm * tangent;
+        indir.normalize();
+        CubitVector new_pos = pos1 + proj_dist * indir;
+        CubitVector pt_on_surf;
+        face->get_surface_ptr()->closest_point_trimmed(new_pos, pt_on_surf);
+        if((pt_on_surf-pos1).length_squared() < dist_sq)
+        {
+          one_bad = false;
+        }
+        else // we found one out of small_curve range
+        {
+          if(one_bad)  // if we had already found one out of range this makes two in a row
+            ret = false;
+          else  // this is the first one out of range
+            one_bad = true;
+        }
+      }
+    }
+  }
+
+  return ret;
+}
+
+void GeomMeasureTool::find_split_points_for_narrow_regions(RefFace *face,
+                                                          double size, 
+                                                          DLIList<CubitVector> &split_pos1_list,
+                                                          DLIList<CubitVector> &split_pos2_list)
+{
+  int k, i, j;
+  double size_sq = size*size;
+  DLIList<RefEdge*> edges;
+  face->ref_edges(edges);
+  while(edges.size() > 1)
+  {
+    RefEdge *cur_edge = edges.extract();
+    for(k=edges.size(); k--;)
+    {
+      RefEdge *other_edge = edges.get_and_step();
+      DLIList<CubitVector*> e1_pos_list, e2_pos_list;
+      DLIList<RefVertex*> e1_vert_list, e2_vert_list;
+      if(narrow_region_exists(cur_edge, other_edge, face, size,
+        e1_pos_list, e2_pos_list, e1_vert_list, e2_vert_list))
+      {
+        e1_pos_list.reset();
+        e2_pos_list.reset();
+        e1_vert_list.reset();
+        e2_vert_list.reset();
+
+        // Loop through each pair of positions defining a split.
+        for(i=e1_pos_list.size(); i--;)
+        {
+          int do_the_split = 1;
+          RefVertex *e1_vert = e1_vert_list.get_and_step();
+          RefVertex *e2_vert = e2_vert_list.get_and_step();
+          CubitVector *e1_pos = e1_pos_list.get_and_step();
+          CubitVector *e2_pos = e2_pos_list.get_and_step();
+
+          // Snap to existing vertices if we are not already at at vertex.
+          if(!e1_vert)
+          {
+            if((cur_edge->start_vertex()->coordinates() - *e1_pos).length_squared() < size_sq)
+              e1_vert = cur_edge->start_vertex();
+            else if((cur_edge->end_vertex()->coordinates() - *e1_pos).length_squared() < size_sq)
+              e1_vert = cur_edge->end_vertex();
+          }
+          if(!e2_vert)
+          {
+            if((other_edge->start_vertex()->coordinates() - *e2_pos).length_squared() < size_sq)
+              e2_vert = other_edge->start_vertex();
+            else if((other_edge->end_vertex()->coordinates() - *e2_pos).length_squared() < size_sq)
+              e2_vert = other_edge->end_vertex();
+          }
+
+          // We may have multiple edges separating these two vertices but the accumulated
+          // length of them may still be within our narrow size so check this.  If this
+          // is the case we will not want to consider this as a place to split and 
+          // will as a result discard these positions.
+          if(e1_vert && e2_vert)
+          {
+            double dist = size*sqrt(2.0);
+            RefVertex *cur_vert = e1_vert;
+            RefEdge *edge = cur_edge;
+            double length = 0.0;
+            while(edge && cur_vert != e2_vert && length <= dist)
+            {
+              edge = edge->get_other_curve(cur_vert, face);
+              if(edge)
+              {
+                length += edge->get_arc_length();
+                cur_vert = edge->other_vertex(cur_vert);
+              }
+            }
+            if(length <= dist)
+              do_the_split = 0;
+            else
+            {
+              // We want to keep this split.
+              split_pos1_list.append(e1_vert->coordinates());
+              split_pos2_list.append(e2_vert->coordinates());
+            }
+          }
+          else
+          {
+            // We want to keep this split.
+            split_pos1_list.append(*e1_pos);
+            split_pos2_list.append(*e2_pos);
+          }
+        }
+      }
+      while(e1_pos_list.size())
+        delete e1_pos_list.pop();
+      while(e2_pos_list.size())
+        delete e2_pos_list.pop();
+    }
+  }
+
+  // Make splits unique
+  DLIList<CubitVector> unique_list1, unique_list2;
+  split_pos1_list.reset();
+  split_pos2_list.reset();
+  for(i=split_pos1_list.size(); i--;)
+  {
+    CubitVector p1 = split_pos1_list.get_and_step();
+    CubitVector p2 = split_pos2_list.get_and_step();
+    int unique = 1;
+    for(j=unique_list1.size(); j>0 && unique; j--)
+    {
+      CubitVector u1 = unique_list1.get_and_step();
+      CubitVector u2 = unique_list2.get_and_step();
+      if((p1.about_equal(u1) && p2.about_equal(u2)) ||
+        (p1.about_equal(u2) && p2.about_equal(u1)))
+      {
+          unique = 0;
+      }
+    }
+    if(unique)
+    {
+      unique_list1.append(p1);
+      unique_list2.append(p2);
+    }
+  }
+  split_pos1_list = unique_list1;
+  split_pos2_list = unique_list2;
+}
+
+// Checks to see if at the given position the two edges are close together and 
+// have the same tangent.
+int GeomMeasureTool::is_narrow_region_at_point(RefEdge *e1,
+                                               RefFace *face,
+                                               const CubitVector &pt_on_e1,
+                                               RefEdge *e2,
+                                               const double &tol_sq,
+                                               CubitVector &closest)
+{
+  int ret = 0;
+
+  CubitVector tan_1, tan_2;
+  e2->closest_point_trimmed(pt_on_e1, closest);
+  double dist = (pt_on_e1-closest).length_squared();
+  if(dist < tol_sq)
+  {
+    DLIList<CoEdge*> coes;
+    e1->tangent(pt_on_e1, tan_1);
+    e2->tangent(closest, tan_2);
+    e1->get_co_edges(coes, face);
+    if(coes.size() == 1)
+    {
+      if(coes.get()->get_sense() == CUBIT_REVERSED)
+        tan_1 *= -1.0;
+      coes.clean_out();
+      e2->get_co_edges(coes, face);
+      if(coes.size() == 1)
+      {
+        if(coes.get()->get_sense() == CUBIT_REVERSED)
+          tan_2 *= -1.0;
+        tan_1.normalize();
+        tan_2.normalize();
+        if(tan_1 % tan_2 < -0.9)
+          ret = 1;
+      }
+    }
+  }
+  return ret;
+}
+
+int GeomMeasureTool::narrow_region_exists(RefFace *face,
+                                          const double &tol)
+{
+  int k, ret = 0;
+  DLIList<RefEdge*> edges;
+  face->ref_edges(edges);
+  int num_curves = edges.size();
+  int num_small_curves = 0;
+  while(edges.size() > 1 && !ret)
+  {
+    // Remove the current edge each time so that we aren't
+    // doing redundant comparisons.
+    RefEdge *cur_edge = edges.extract();
+    if(cur_edge->get_arc_length() < tol)
+      num_small_curves++;
+
+    // Compare this edge with the remaining edges on the face.
+    for(k=edges.size(); k && !ret; k--)
+    {
+      RefEdge *other_edge = edges.get_and_step();
+
+      DLIList<CubitVector*> e1_pos_list, e2_pos_list;
+      DLIList<RefVertex*> 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();
+    }
+  }
+  if(!ret)
+  {
+    if(edges.size() == 1 && edges.get()->get_arc_length() < tol)
+      num_small_curves++;
+  }
+
+  ret = ret || (num_small_curves == num_curves);
+
+  return ret;
+}
+
+int GeomMeasureTool::narrow_region_exists(RefFace *face,
+                                          RefEdge *edge,
+                                          const double &tol)
+{
+  int k, ret = 0;
+  DLIList<RefEdge*> edges;
+  face->ref_edges(edges);
+  if(edges.move_to(edge))
+  {
+    edges.extract();
+
+    // Compare this edge with the remaining edges on the face.
+    for(k=edges.size(); k && !ret; k--)
+    {
+      RefEdge *other_edge = edges.get_and_step();
+
+      DLIList<CubitVector*> e1_pos_list, e2_pos_list;
+      DLIList<RefVertex*> e1_vert_list, e2_vert_list;
+      ret = narrow_region_exists(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 GeomMeasureTool::narrow_region_exists(
+                                            RefEdge *e1,
+                                            RefEdge *e2,
+                                            RefFace *face,
+                                            const double &tol,
+                                            DLIList<CubitVector*> &e1_pos_list,
+                                            DLIList<CubitVector*> &e2_pos_list,
+                                            DLIList<RefVertex*> &e1_vert_list,
+                                            DLIList<RefVertex*> &e2_vert_list)
+{
+  int ret = 0;
+  double tol_sq = tol*tol;
+  double small_step = 5.0*tol;
+  double small_step_sq = small_step*small_step;
+  double max_dist_sq = 0.0;
+  RefVertex *e1_start_vert = e1->start_vertex();
+  RefVertex *e1_end_vert = e1->end_vertex();
+
+  CubitVector closest;
+  DLIList<RefVertex*> e1_verts, e2_verts;
+
+  e1->ref_vertices(e1_verts);
+  e2->ref_vertices(e2_verts);
+  e1_verts.intersect_unordered(e2_verts);
+  int num_shared_verts = e1_verts.size();
+  RefVertex *shared_vert = NULL;
+  RefEdge *edge1 = NULL;
+  RefEdge *edge2 = NULL;
+  if(num_shared_verts == 1)
+  {
+    shared_vert = e1_verts.get();
+    DLIList<CoEdge*> coes;
+    e1->get_co_edges(coes, face);
+    if(coes.size() == 1)
+    {
+      RefVolume *vol = face->ref_volume();
+      CubitSense facevol_sense = face->sense(vol);
+      if((coes.get()->start_vertex() == shared_vert) ==
+        (facevol_sense == CUBIT_FORWARD))
+      {
+        edge1 = e1;
+        edge2 = e2;
+      }
+      else
+      {
+        edge1 = e2;
+        edge2 = e1;
+      }
+    }
+  }
+
+  // Project cur endpoints onto other.
+  int do_narrow_region_check = 1;
+  if(num_shared_verts == 1 && shared_vert == e1_start_vert)
+  {
+    // Edges are next to each other.  Check the angle between them
+    // before doing anything else.
+    double interior_angle = edge1->angle_between(edge2, face);
+    if(interior_angle > CUBIT_PI/4.0)
+      do_narrow_region_check = 0;
+  }
+  if(do_narrow_region_check &&
+     is_narrow_region_at_point(e1, face, e1_start_vert->coordinates(), e2, tol_sq, closest))
+  {
+    max_dist_sq = (closest - e1_start_vert->coordinates()).length_squared();
+    e1_pos_list.append(new CubitVector(e1_start_vert->coordinates()));
+    e2_pos_list.append(new CubitVector(closest));
+    e1_vert_list.append(e1_start_vert);
+    e2_vert_list.append(NULL);
+  }
+  do_narrow_region_check = 1;
+  if(num_shared_verts == 1 && shared_vert == e1_end_vert)
+  {
+    // Edges are next to each other.  Check the angle between them
+    // before doing anything else.
+    double interior_angle = edge1->angle_between(edge2, face);
+    if(interior_angle > CUBIT_PI/4.0)
+      do_narrow_region_check = 0;
+  }
+  if(do_narrow_region_check &&
+     is_narrow_region_at_point(e1, face, e1_end_vert->coordinates(), e2, tol_sq, closest))
+  {
+    double cur_dist_sq = (closest - e1_end_vert->coordinates()).length_squared();
+    max_dist_sq = max_dist_sq > cur_dist_sq ? max_dist_sq : cur_dist_sq;
+    e1_pos_list.append(new CubitVector(e1_end_vert->coordinates()));
+    e2_pos_list.append(new CubitVector(closest));
+    e1_vert_list.append(e1_end_vert);
+    e2_vert_list.append(NULL);
+  }
+
+  if(e1_pos_list.size() < 2)
+  {
+    RefVertex *e2_start_vert = e2->start_vertex();
+    RefVertex *e2_end_vert = e2->end_vertex();
+    do_narrow_region_check = 1;
+    if(num_shared_verts == 1 && shared_vert == e2_start_vert)
+    {
+      // Edges are next to each other.  Check the angle between them
+      // before doing anything else.
+      double interior_angle = edge1->angle_between(edge2, face);
+      if(interior_angle > CUBIT_PI/4.0)
+        do_narrow_region_check = 0;
+    }
+    if(do_narrow_region_check &&
+       is_narrow_region_at_point(e2, face, e2_start_vert->coordinates(), e1, tol_sq, closest))
+    {
+      if(e1_pos_list.size() == 0 || !closest.about_equal(*e1_pos_list.get()))
+      {
+        double cur_dist_sq = (closest - e2_start_vert->coordinates()).length_squared();
+        max_dist_sq = max_dist_sq > cur_dist_sq ? max_dist_sq : cur_dist_sq;
+        e2_pos_list.append(new CubitVector(e2_start_vert->coordinates()));
+        e1_pos_list.append(new CubitVector(closest));
+        e2_vert_list.append(e2_start_vert);
+        e1_vert_list.append(NULL);
+      }
+    }
+    if(e1_pos_list.size() < 2)
+    {
+      do_narrow_region_check = 1;
+      if(num_shared_verts == 1 && shared_vert == e2_end_vert)
+      {
+        // Edges are next to each other.  Check the angle between them
+        // before doing anything else.
+        double interior_angle = edge1->angle_between(edge2, face);
+        if(interior_angle > CUBIT_PI/4.0)
+          do_narrow_region_check = 0;
+      }
+      if(do_narrow_region_check &&
+         is_narrow_region_at_point(e2, face, e2_end_vert->coordinates(), e1, tol_sq, closest))
+      {
+        if(e1_pos_list.size() == 0 || !closest.about_equal(*e1_pos_list.get()))
+        {
+          double cur_dist_sq = (closest - e2_end_vert->coordinates()).length_squared();
+          max_dist_sq = max_dist_sq > cur_dist_sq ? max_dist_sq : cur_dist_sq;
+          e2_pos_list.append(new CubitVector(e2_end_vert->coordinates()));
+          e1_pos_list.append(new CubitVector(closest));
+          e2_vert_list.append(e2_end_vert);
+          e1_vert_list.append(NULL);
+        }
+      }
+    }
+  }
+
+  if(e1_pos_list.size() == 2)
+  {
+    int w;
+    int all_good = 1;
+ //   double dist_tol = sqrt(max_dist_sq)*5.0;
+    e1_pos_list.reset();
+    e2_pos_list.reset();
+    CubitVector *cur1 = e1_pos_list.get_and_step();
+    CubitVector *cur2 = e1_pos_list.get();
+    CubitVector *other1 = e2_pos_list.get_and_step();
+    CubitVector *other2 = e2_pos_list.get();
+
+    double len1 = e1->get_arc_length(*cur1, *cur2);
+    if(len1 > tol)
+    {
+      double len2 = e2->get_arc_length(*other1, *other2);
+      if(len2 > tol)
+      {
+        double cur_param1 = e1->u_from_position(*cur1);
+        double cur_param2 = e1->u_from_position(*cur2);
+        int num_divisions = 2;
+        CubitVector cur_pos;
+        double param_step = (cur_param2-cur_param1)/num_divisions;
+        double cur_param = cur_param1 + param_step;
+        for(w=1; w<num_divisions && all_good; w++)
+        {
+          e1->position_from_u(cur_param, cur_pos);
+          cur_param += param_step;
+          if(is_narrow_region_at_point(e1, face, cur_pos, e2, tol_sq, closest))
+          {
+            // Sanity check to make sure we aren't splitting off negative space.
+            CubitVector mid = (cur_pos + closest)/2.0;
+            CubitVector tmp_pt;
+            face->get_surface_ptr()->closest_point_trimmed(mid, tmp_pt);
+            if(!mid.about_equal(tmp_pt))
+            {
+              CubitVector norm = face->normal_at(tmp_pt);
+              CubitVector dir(tmp_pt - mid);
+              dir.normalize();
+              if(fabs(norm % dir) < .9)
+                all_good = 0;
+            }
+          }
+        }
+      }
+      else
+        all_good = 0;
+    }
+    else 
+      all_good = 0;
+
+    if(all_good)
+      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;
+    }
+  }
+
+  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--;)
+    {
+      CubitVector *e1_pos = e1_pos_list.get_and_step();
+      CubitVector *e2_pos = e2_pos_list.get_and_step();
+      RefVertex *e1_vert = e1_vert_list.get_and_step();
+      RefVertex *e2_vert = e2_vert_list.get_and_step();
+
+      RefVertex *cur_vert = NULL;
+      RefEdge *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)
+      {
+        CubitVector next_pos;
+        CubitVector prev_pos = cur_vert->coordinates();
+        int num_incs = 20;
+        double step = cur_edge->get_arc_length()/(double)num_incs;
+        int still_good = 1;
+        int cntr = 0;
+        double direction = (cur_vert == cur_edge->start_vertex() ? 1.0 : -1.0);
+        // Do coarse traversal along curve to see where we start deviating from
+        // narrow.
+        while(still_good)
+        {
+          cur_edge->point_from_arc_length(prev_pos, step*direction, next_pos);
+          if(is_narrow_region_at_point(cur_edge, face, next_pos, other_edge, tol_sq, closest) &&
+                      cntr < num_incs)
+          {
+            prev_pos = next_pos;
+            cntr++;
+          }
+          else
+            still_good = 0;
+        }
+        if(cntr < num_incs)
+        {
+          cntr = 0;
+          double cur_arc_length = cur_edge->get_arc_length(prev_pos, next_pos);
+          // Do bisection on remaining interval to zero in on point where
+          // we go from narrow to non-narrow.
+          CubitVector mid_pos;
+          double close_enough = tol/20.0;
+          while(cur_arc_length > close_enough && cntr < 100)
+          {
+            cntr++;  // prevent infinite looping
+            cur_edge->point_from_arc_length(prev_pos, cur_arc_length*direction/2.0, mid_pos);
+            if(is_narrow_region_at_point(cur_edge, face, mid_pos, other_edge, tol_sq, closest))
+              prev_pos = mid_pos;
+            else
+              next_pos = mid_pos;
+            cur_arc_length = cur_edge->get_arc_length(prev_pos, next_pos);
+          }
+          if(cur_edge->get_arc_length(cur_vert->coordinates(), prev_pos) > tol)
+          {
+            // end up with the position that guarantees a new split curve that
+            // is smaller than the small curve size.
+            other_edge->closest_point_trimmed(prev_pos, closest);
+            if(cur_edge == e1)
+            {
+              e1_pos_list.append(new CubitVector(prev_pos));
+              e2_pos_list.append(new CubitVector(closest));
+            }
+            else
+            {
+              e2_pos_list.append(new CubitVector(prev_pos));
+              e1_pos_list.append(new CubitVector(closest));
+            }
+            e1_vert_list.append(NULL);
+            e2_vert_list.append(NULL);
+            ret = 1;
+          }
+        }
+      }
+    }
+  }
+
+  if(ret)
+  {
+    int i, j;
+    e1_pos_list.reset();
+    e2_pos_list.reset();
+    e1_vert_list.reset();
+    e2_vert_list.reset();
+    for(i=e1_pos_list.size(); i--;)
+    {
+      CubitVector *e1_pos = e1_pos_list.get();
+      CubitVector *e2_pos = e2_pos_list.get();
+      int num_divisions = 6;
+      CubitVector step = (*e2_pos - *e1_pos)/num_divisions;
+      CubitVector cur_pos = *e1_pos + step;
+      int removed = 0;
+      for(j=1; j<num_divisions; j++)
+      {
+        CubitVector tmp_pt;
+        face->get_surface_ptr()->closest_point_trimmed(cur_pos, tmp_pt);
+        if(!cur_pos.about_equal(tmp_pt))
+        {
+          CubitVector norm = face->normal_at(tmp_pt);
+          CubitVector dir(tmp_pt - cur_pos);
+          dir.normalize();
+          if(fabs(norm % dir) < .9)
+          {
+            removed = 1;
+            j=num_divisions;
+            e1_pos_list.remove();
+            e2_pos_list.remove();
+            e1_vert_list.remove();
+            e2_vert_list.remove();
+          }
+        }
+        else
+          cur_pos += step;
+      }
+      if(!removed)
+      {
+        e1_pos_list.step();
+        e2_pos_list.step();
+        e1_vert_list.step();
+        e2_vert_list.step();
+      }
+    }
+
+    if(e1_pos_list.size() == 0)
+      ret = 0;
+  }
+
+  return ret;
+}
+
 void GeomMeasureTool::find_small_curves( DLIList <RefVolume*> &ref_vols,
                                          double tol,
                                          DLIList <RefEdge*> &small_curves,
@@ -1861,10 +2635,38 @@
       }
     }
   }
+
+  int num_curves = ref_edges.size();
+  ProgressTool *progress_ptr = NULL;
+  if (num_curves> 20)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Finding Small Curves", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+
+  int total_curves = 0;
+  double curr_percent = 0.0;
   double length;
     //find the small curves and reset the marked flag.
   for ( ii = ref_edges.size(); ii > 0; ii-- )
   {
+    total_curves++;
+    if ( progress_ptr != NULL )
+    {
+      curr_percent = ((double)(total_curves))/((double)(num_curves));
+      progress_ptr->percent(curr_percent);
+    }
+    if ( CubitMessage::instance()->Interrupt() )
+    {
+        //interrpt.  We need to exit.
+      if ( progress_ptr != NULL )
+        progress_ptr->end();
+        //just leave what has been calculated...
+      return;
+    }
+
     curr_edge = ref_edges.get_and_step();
 
     //skip point curves
@@ -1879,8 +2681,115 @@
       small_lengths.append(length);
     }
   }
+
+  if ( progress_ptr != NULL )
+    progress_ptr->end();
+
   return;
 }
+
+RefEdge* GeomMeasureTool::find_first_small_curve(RefVolume* vol,
+                                         double tol)
+{
+  RefEdge *ret = NULL;
+  int j;
+  DLIList <RefEdge*> ref_edges;
+  vol->ref_edges(ref_edges);
+  for(j=ref_edges.size(); j > 0 && !ret; j--)
+  {
+    RefEdge *curr_edge = ref_edges.get_and_step();
+    if(curr_edge->measure() <= tol)
+      ret = curr_edge;
+  }
+  return ret;
+}
+
+void GeomMeasureTool::find_narrow_faces(DLIList<RefVolume*> &ref_vols,
+                                        double small_curve_size,
+                                        DLIList<RefFace*> &narrow_faces,
+                                        DLIList<RefFace*> &surfs_to_ignore)
+{
+  int ii, jj;
+  DLIList <RefFace*> ref_faces, temp_faces;
+  RefVolume *ref_vol;
+  RefFace *curr_face;
+
+  for ( ii = 0; ii < ref_vols.size(); ii++ )
+  {
+    DLIList<RefFace*> faces;
+    ref_vol = ref_vols.get_and_step();
+    ref_vol->ref_faces(faces);
+    for ( jj = faces.size(); jj > 0; jj-- )
+    {
+      curr_face = faces.get_and_step();
+      curr_face->marked(0);
+      temp_faces.append(curr_face);
+    }
+  }
+
+  //uniquely add the faces.
+  for ( jj = temp_faces.size(); jj > 0; jj-- )
+  {
+    curr_face = temp_faces.get_and_step();
+    if ( curr_face->marked()== 0 )
+    {
+      curr_face->marked(1);
+      ref_faces.append(curr_face);
+    }
+  }
+
+  int num_faces = ref_faces.size();
+  ProgressTool *progress_ptr = NULL;
+  if (num_faces > 20)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Finding Narrow Surfaces", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+
+  int total_faces = 0;
+  double curr_percent = 0.0;
+
+  for ( ii = ref_faces.size(); ii > 0; ii-- )
+  {
+    total_faces++;
+    if ( progress_ptr != NULL )
+    {
+      curr_percent = ((double)(total_faces))/((double)(num_faces));
+      progress_ptr->percent(curr_percent);
+    }
+
+    if ( CubitMessage::instance()->Interrupt() )
+    {
+        //interrpt.  We need to exit.
+      if ( progress_ptr != NULL )
+        progress_ptr->end();
+        //just leave what has been calculated...
+      return;
+    }
+
+    curr_face = ref_faces.get_and_step();
+    if(!surfs_to_ignore.is_in_list(curr_face))
+    {
+      if(narrow_region_exists(curr_face, small_curve_size))
+      {
+        DLIList<CubitVector> split_pos1_list;
+        DLIList<CubitVector> split_pos2_list;
+        find_split_points_for_narrow_regions(curr_face,
+          small_curve_size, split_pos1_list, split_pos2_list); 
+        if(split_pos1_list.size() == 0)
+          narrow_faces.append_unique(curr_face);
+      }
+    }
+  }
+
+  if ( progress_ptr != NULL )
+    progress_ptr->end();
+
+  return;
+}
+
 void GeomMeasureTool::find_small_faces( DLIList <RefVolume*> &ref_vols,
                                         double tol,
                                         DLIList <RefFace*> &small_faces)
@@ -1891,32 +2800,72 @@
   RefFace *curr_face;
   for ( ii = 0; ii < ref_vols.size(); ii++ )
   {
+    DLIList<RefFace*> faces;
     ref_vol = ref_vols.get_and_step();
-    ref_vol->ref_faces(temp_faces);
-      //uniquely add the faces.
-    for ( jj = temp_faces.size(); jj > 0; jj-- )
+    ref_vol->ref_faces(faces);
+    for ( jj = faces.size(); jj > 0; jj-- )
     {
-      curr_face = temp_faces.pop();
-      if ( curr_face->marked()== 0 )
-      {
-        curr_face->marked(1);
-        ref_faces.append(curr_face);
-      }
+      curr_face = faces.get_and_step();
+      curr_face->marked(0);
+      temp_faces.append(curr_face);
     }
   }
+
+  //uniquely add the faces.
+  for ( jj = temp_faces.size(); jj > 0; jj-- )
+  {
+    curr_face = temp_faces.get_and_step();
+    if ( curr_face->marked()== 0 )
+    {
+      curr_face->marked(1);
+      ref_faces.append(curr_face);
+    }
+  }
+
+  int num_faces = ref_faces.size();
+  ProgressTool *progress_ptr = NULL;
+  if (num_faces > 20)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Finding Small Surfaces", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+
+  int total_faces = 0;
+  double curr_percent = 0.0;
   double area;
     //find the small curves and reset the marked flag.
   for ( ii = ref_faces.size(); ii > 0; ii-- )
   {
+    total_faces++;
+    if ( progress_ptr != NULL )
+    {
+      curr_percent = ((double)(total_faces))/((double)(num_faces));
+      progress_ptr->percent(curr_percent);
+    }
+
+    if ( CubitMessage::instance()->Interrupt() )
+    {
+        //interrpt.  We need to exit.
+      if ( progress_ptr != NULL )
+        progress_ptr->end();
+        //just leave what has been calculated...
+      return;
+    }
+
     curr_face = ref_faces.get_and_step();
-      //reset the mark.
-    curr_face->marked(0);
     area = measure_area(curr_face);
     if ( area <= tol )
       small_faces.append(curr_face);
   }
+
+  if ( progress_ptr != NULL )
+    progress_ptr->end();
+
   return;
 }
+
 void GeomMeasureTool::find_small_faces_hydraulic_radius( DLIList <RefVolume*> &ref_vols,
                                                          double tol,
                                                          DLIList <RefFace*> &small_faces,
@@ -1954,13 +2903,12 @@
   DLIList <CoEdge*> co_edges;
   int num_faces = ref_faces.size();
   ProgressTool *progress_ptr = NULL;
-  char title[32];
   if (num_faces > 20)
   {
-    strcpy(title, "Small Surface Progress");
     progress_ptr = AppUtil::instance()->progress_tool();
     assert(progress_ptr != NULL);
-    progress_ptr->start(0, 100, title, NULL, CUBIT_TRUE, CUBIT_TRUE);
+    progress_ptr->start(0, 100, "Small Surface Progress", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
   }
   double curr_percent = 0.0;
   for ( ii = ref_faces.size(); ii > 0; ii-- )
@@ -2003,7 +2951,7 @@
       //compute the hydraulic radius 4*(A/P).
     if ( length <= CUBIT_RESABS )
     {
-      PRINT_INFO("Total Perimiter Length of Surface %d is less than tolerance.\n",
+      PRINT_INFO("Total Perimeter Length of Surface %d is less than tolerance.\n",
                  curr_face->id());
       
       continue;
@@ -2629,14 +3577,14 @@
   RefEdge *closest_edge_1, *closest_edge_2;
   CubitVector curr_loc;
   double closest_dist;
-  double min_for_loop;
+  double min_for_loop_squared;
   atree_list.reset();
   for ( ii = 0; ii < atree_list.size(); ii++ )
   {
     curr_points = boundary_point_loops.get_and_step();
     for ( jj = ii+1; jj < atree_list.size(); jj++ )
     {
-      min_for_loop = CUBIT_DBL_MAX;
+      min_for_loop_squared = CUBIT_DBL_MAX;
       closest_edge_1 = NULL;
       closest_edge_2 = NULL;
       curr_tree = atree_list.next(jj);
@@ -2655,7 +3603,7 @@
             //hmm, not sure what is wrong here.
           PRINT_ERROR("Can't find closest point between loops.\n");
         }
-        if (closest_dist <= tol*tol && closest_dist < min_for_loop*min_for_loop )
+        if (closest_dist <= tol*tol && closest_dist < min_for_loop_squared )
         {
             //just store the smaller ones.  Don't store
           RefEntity *ref_ent = curr_point->owner();
@@ -2698,7 +3646,7 @@
             continue;
           }
           
-          min_for_loop = sqrt(closest_dist);
+          min_for_loop_squared = closest_dist;
           closest_edge_1 = ref_edge_1;
           closest_edge_2 = ref_edge_2;
         }
@@ -2707,7 +3655,7 @@
       {
         close_edges.append(closest_edge_1);
         close_edges.append(closest_edge_2);
-        small_lengths.append(min_for_loop);
+        small_lengths.append(sqrt(min_for_loop_squared));
       }
     }
   }
@@ -2875,35 +3823,60 @@
 ///
 ///  Find fillets and rounds.
 ///
+#define FACE_BLEND      1
+#define VERTEX_BLEND    2
+#define BLEND_PROCESSED 3
+
 void GeomMeasureTool::find_blends( RefVolume *ref_volume,
                                    DLIList <RefFace*> &blend_faces,
                                    DLIList <DLIList<RefFace*>*> &blend_groups )
 {
     //Assume for now that blends have cartesian angles between
     //all the attached faces and itself.
-    //Also a blend cannot be plannar.  And directly accross from
+    //Also a blend cannot be planar.  And directly accross from
     //one blend edge, there is usually another blended edge but
     //the angle between the two normals must be orthogonal. In other
     //words their must be some sort of transition.
   
+    //mark all the faces as 0.  The mark is used here to find the
+    // blend groups.  The function is_vertex_blend() marks faces
+    // as being a vertex blend.  The group of faces is then traversed
+    // until the adjacent surface (across the cross curve) is either
+    // a vertex blend or not a blend.
+  DLIList <RefFace*> ref_faces;
+  DLIList <RefFace*> vertex_blends, face_blends;
+  ref_volume->ref_faces(ref_faces);
+  int ii, jj;
+  for ( ii =0; ii < ref_faces.size(); ii++ )
+    ref_faces.get_and_step()->marked(0);
+
     //First go through each face and each edge on each face.
-  int ii, jj;
-  DLIList <RefFace*> ref_faces;
   DLIList <RefEdge*> ref_edges;
   RefFace *ref_face;
   RefEdge *ref_edge, *other_edge;
-  ref_volume->ref_faces(ref_faces);
+  int num_vertex_blends = 0;
+  int num_face_blends = 0;
   for ( ii = ref_faces.size(); ii > 0; ii-- )
   {
     ref_face = ref_faces.get_and_step();
-      //Test the face to see if it is a blend.
+      //Test the face to see if it is a face or vertex blend.
     other_edge = NULL;
     ref_edge = NULL;
     if ( is_face_blend(ref_face, ref_volume,
                        ref_edge, other_edge ) )
-      blend_faces.append(ref_face);
+    {
+      face_blends.append(ref_face);
+      ref_face->marked(1);
+      num_face_blends++;
+    }
+    else if ( is_vertex_blend(ref_face, ref_volume) )
+    {
+      vertex_blends.append(ref_face);
+      ref_face->marked(2);
+      num_vertex_blends++;  // keep track of the number of vertex blends
+    }
   }
-  if ( blend_faces.size() == 0 )
+  if ( face_blends.size() + vertex_blends.size() == 0 )
   {
     return;
   }
@@ -2911,42 +3884,79 @@
     //are that share curves.
   DLIList <RefFace*> *blend_group;
   DLIList <RefFace*> stack;
-  RefFace *other_face;
-    //mark all the faces as 0.
-  for ( ii =0; ii < ref_faces.size(); ii++ )
-    ref_faces.get_and_step()->marked(0);
-    //mark just the blends as 1.
-  for ( ii =0; ii < blend_faces.size(); ii++ )
-    blend_faces.get_and_step()->marked(1);
+  RefFace *start_face = NULL, *other_face;
   
-  for ( ii =0; ii < blend_faces.size(); ii++ )
+  // continue while there are blends to process
+  while ( vertex_blends.size() + face_blends.size() > 0 || 
+          start_face != NULL)
   {
-    ref_face = blend_faces.get_and_step();
-    if ( ref_face->marked() == 2 )
-      continue;
-    blend_group = new DLIList <RefFace*>;
-    blend_groups.append(blend_group);
-    stack.clean_out();
-    stack.append(ref_face);
-    while ( stack.size() > 0 )
+    // if we don't have a start_face, get a new one.
+    if (!start_face) 
     {
-      ref_face = stack.pop();
-      ref_face->marked(2);
-      blend_group->append(ref_face);
-      ref_edges.clean_out();
-      ref_face->ref_edges(ref_edges);
-      for ( jj = 0; jj < ref_edges.size(); jj++ )
+      // this is the start of a new group
+      blend_group = new DLIList <RefFace*>;
+      blend_groups.append(blend_group);
+
+      // always prefer to start at a vertex blend if one exists
+      if (vertex_blends.size() > 0 )
       {
-        ref_edge = ref_edges.get_and_step();
-        other_face = ref_edge->other_face(ref_face, ref_volume);
-        if ( other_face == NULL )
-            //shouldn't happend.
-          continue;
-        if ( other_face->marked() == 1 )
-          stack.append(other_face);
+        start_face = vertex_blends.pop();
       }
+      else 
+      {
+        start_face = face_blends.pop();
+      }
     }
+
+    blend_group->append(start_face);  // add ref_face to group
+    blend_faces.append(start_face);   // add the ref_face to the returned list
+    start_face->marked(BLEND_PROCESSED);
+
+    ref_edges.clean_out();
+    start_face->ref_edges(ref_edges);
+    for ( jj = 0; jj < ref_edges.size(); jj++ )
+    {
+      ref_edge = ref_edges.get_and_step();
+      other_face = ref_edge->other_face(start_face, ref_volume);
+      if (other_face == NULL)
+      {
+        start_face = NULL;
+        break;
+      }
+
+      // if this blend has been processed and isn't in the current group
+      if (other_face->marked() == BLEND_PROCESSED && 
+          !blend_group->is_in_list(other_face) )
+      {
+        start_face = NULL;
+        break;  // reached an end of this loop
+      }
+      else if (other_face->marked() == VERTEX_BLEND)
+      {
+        blend_group->append(other_face);  // add the ref_face to the group
+        blend_faces.append(other_face);   // add the ref_face to the returned list
+        vertex_blends.remove(other_face);
+        other_face->marked(BLEND_PROCESSED);
+        start_face = NULL;
+        break;  // a vertex blend is also end of the line
+      }
+      else if (other_face->marked() == FACE_BLEND)
+      {
+        start_face = other_face;
+        face_blends.remove(other_face);
+        break;  // continue using this face as the new start face
+      }
+    }
+    // if we traversed through all the edges of this blend without
+    // finding another blend attached, this is the end of the chain 
+    // and we need to find another starting place.
+    if ( jj >= ref_edges.size() ) 
+    {
+      start_face = NULL;
+    }
+    
   }
+
     //cleanup marks.
   for ( ii =0; ii < ref_faces.size(); ii++ )
     ref_faces.get_and_step()->marked(0);
@@ -2957,6 +3967,198 @@
     //REMEMBER TO DELETE the dllists in blend_faces.
   return;
 }
+
+// struct type object private to the next function
+class NextBlend
+{
+  public:
+  RefEdge* ref_edge;
+  RefFace* ref_face;
+};
+
+void GeomMeasureTool::find_blends_from_edge( RefVolume* ref_volume, 
+                                                    RefFace *start_face, 
+                                                    RefEdge* start_edge,
+                                                    std::vector <RefFace*> &blend_faces)
+{
+  // initialize the mark on all surfaces in the volume
+  DLIList <RefFace*> ref_faces;
+  RefEdge *next_edge, *other_edge;
+  ref_volume->ref_faces(ref_faces);
+  int ii;
+  for ( ii =0; ii < ref_faces.size(); ii++ )
+    ref_faces.get_and_step()->marked(0);
+
+  std::stack<NextBlend> blend_stack;
+
+  NextBlend blend;
+  blend.ref_edge = start_edge;
+  blend.ref_face = start_face;
+  blend_faces.push_back(start_face);
+
+  blend_stack.push(blend);
+
+  while (blend_stack.size() > 0)
+  {
+    // this is an oddity with std::stack.  Get the top of the stack
+    // and then you have to remove it from the stack with pop
+    NextBlend next_blend = blend_stack.top();
+    blend_stack.pop();
+    RefEdge* ref_edge = next_blend.ref_edge;
+    RefFace* ref_face = next_blend.ref_face;
+
+    RefFace* next_face;
+    next_face = ref_edge->other_face(ref_face, ref_volume);
+
+    // the the next face exists and it's a face blend, save the current blend,
+    // create a new blend object and add it to the stack
+    if ( next_face && is_face_blend(next_face, ref_volume, next_edge, other_edge ) )
+    {
+      // if the next face is already processed, the chain loops back on itself.
+      if (next_face->marked() == BLEND_PROCESSED)
+      {
+        for ( ii =0; ii < ref_faces.size(); ii++ )
+          ref_faces.get_and_step()->marked(0);
+        return;
+      }
+
+      blend_faces.push_back(next_face);
+      next_face->marked(BLEND_PROCESSED);
+
+      // the is_face_blend function assumes (poorly) rectangular surfaces
+      // without any holes.  It returns the spring curves and we want
+      // the cross curves. So get all four edges and remove the two
+      // spring curves returned by is_face_blend
+      DLIList <RefEdge*> ref_edges;
+      next_face->ref_edges(ref_edges);
+      ref_edges.remove(next_edge);
+      ref_edges.remove(other_edge);
+
+      if (ref_edges.get() != ref_edge)
+      {
+        next_blend.ref_edge = ref_edges.get();
+      }
+      else
+      {
+        next_blend.ref_edge = ref_edges.next(1);
+      }
+      next_blend.ref_face = next_face;
+      blend_stack.push(next_blend);
+    }
+    else if ( next_face && is_vertex_blend(next_face, ref_volume) )
+    {
+      // we will stop the chain at a vertex blend
+      blend_faces.push_back(next_face);
+      next_face->marked(BLEND_PROCESSED);
+    }
+  }
+
+  // clean up the marks
+  std::vector<RefFace*>::iterator iter;
+  for ( iter = blend_faces.begin(); iter != blend_faces.end(); iter++)
+    (*iter)->marked(0);
+}
+
+// given a starting blend surface find a chain of blends from
+// that surface.  
+//
+// Note that this function intentionally does _not_
+// clear the blend_face list so that additional chains can be added.
+CubitStatus GeomMeasureTool::find_blend_chains( RefFace *start_face,
+                                std::vector<std::vector< RefFace*> > &blend_chains)
+{
+
+  if (start_face == NULL)
+  {
+    return CUBIT_FAILURE;
+  }
+
+  std::vector <RefFace*> blend_faces;
+
+  // get the owning volume of this blend
+  DLIList<RefEntity*> entity_list;
+  RefVolume* ref_volume;
+  int ii;
+
+  start_face->get_parent_ref_entities(entity_list);
+
+  // this indicates merged enitites and potential problems
+  if (entity_list.size() > 1)
+  {
+    return CUBIT_FAILURE;
+  }
+
+  // make sure we're at the beginning of the list and get the first
+  // and only item on the list and cast it to a RefVolume
+  entity_list.reset();
+  ref_volume = CAST_TO(entity_list.get(), RefVolume);
+ 
+  if (!ref_volume)
+  {
+    return CUBIT_FAILURE;
+  }
+
+  // initialize the mark on all surfaces in the volume
+  DLIList <RefFace*> ref_faces;
+  ref_volume->ref_faces(ref_faces);
+
+  RefEdge *spring_curve1, *spring_curve2;
+  if ( is_face_blend(start_face, ref_volume, spring_curve1, spring_curve2 ) )
+  {
+    // the is_face_blend function assumes (poorly) rectangular surfaces
+    // without any holes.  It returns the spring curves and we want
+    // the cross curves. So get all four edges and remove the two
+    // spring curves returned by is_face_blend
+    DLIList <RefEdge*> ref_edges;
+    start_face->ref_edges(ref_edges);
+    ref_edges.remove(spring_curve1);
+    ref_edges.remove(spring_curve2);
+
+    // there is a special case where the blend is a periodic surface
+    // meaning that there _are_ no cross curves
+    if ( ref_edges.size() == 0 )
+    {
+      blend_faces.push_back(start_face);
+    }
+    else
+    {
+      // now find additional blends extending from either side of the blend
+      blend_faces.clear();
+      find_blends_from_edge( ref_volume, start_face, ref_edges.get(), blend_faces);
+      find_blends_from_edge( ref_volume, start_face, ref_edges.next(1), blend_faces);
+
+      // make sure that we have a unique list (the start surface is probably here twice)
+      std::vector<RefFace*>::iterator new_end;
+      std::sort( blend_faces.begin(), blend_faces.end() );
+      new_end = std::unique( blend_faces.begin(), blend_faces.end() );
+      blend_faces.erase(new_end, blend_faces.end());
+    }
+
+    blend_chains.push_back(blend_faces);
+  }
+  else if ( is_vertex_blend(start_face, ref_volume) )
+  {
+    DLIList<RefEdge*> ref_edges;
+    start_face->ref_edges(ref_edges);
+
+    for (ii = 0; ii < ref_edges.size(); ii++)
+    {
+      RefEdge* start_edge = ref_edges.get_and_step();
+      blend_faces.clear();
+      find_blends_from_edge( ref_volume, start_face, start_edge, blend_faces);
+
+      blend_chains.push_back(blend_faces);
+    }
+  }
+  else
+  {
+    // the given face is not a blend
+    return CUBIT_FAILURE;
+  }
+
+  return CUBIT_SUCCESS;
+}
+
 //--------------------------------------------------------------------
 //Function: Public, is_face_blend
 //Description: Determines if a face is a blend surface, returns the
@@ -3085,6 +4287,93 @@
   return CUBIT_FALSE;
 }
 
+//--------------------------------------------------------------------
+//Function: Public, is_vertex_blend
+//Description: Determines if a face is a vertex blend surface.
+//   For this type of blend, all ref_edges must be meet tangentially
+//   with another surface.  This assumes blend surface with no holes. 
+//---------------------------------------------------------------------
+CubitBoolean GeomMeasureTool::is_vertex_blend(RefFace *ref_face,
+                                              RefVolume* ref_volume)
+{
+    //first we know that blend surfaces are not planar.
+    //so remove these first.
+    //Also, don't look at faces with more than 2 loops.
+  if ( ref_face->geometry_type() == PLANE_SURFACE_TYPE ||
+       ref_face->num_loops() > 2 )
+    return CUBIT_FALSE;
+  
+  CubitBoolean is_cartesian;
+  DLIList<RefEdge*> ref_edges;
+  RefFace *other_face;
+  RefEdge *ref_edge = NULL;
+  int jj;
+  double angle;
+  ref_face->ref_edges(ref_edges);
+  for ( jj = ref_edges.size(); jj > 0; jj-- )
+  {
+    ref_edge = ref_edges.get_and_step();
+
+    //Weed-out case where one edge is shared between more 
+    //than 2 surfaces of the same volume
+    DLIList<RefFace*> tmp_faces;
+    ref_edge->ref_faces( tmp_faces );
+
+    if( tmp_faces.size() > 2 )
+    {
+      int kk;
+      for(kk=tmp_faces.size(); kk--;)
+      {
+        if( !tmp_faces.get()->is_child( ref_volume ) )
+          tmp_faces.change_to(NULL);
+        tmp_faces.step();
+      }
+      tmp_faces.remove_all_with_value( NULL );
+      if( tmp_faces.size() > 2 )
+        //this isn't the type of surface we are looking for...
+        continue;
+    }
+
+    other_face = ref_edge->other_face(ref_face, ref_volume);
+    if ( other_face == NULL )
+    {
+        //this isn't the type of surface we are looking for...
+      break;
+    }
+    angle = GeometryQueryTool::instance()->surface_angle(ref_face,
+                                                         other_face,
+                                                         ref_edge,
+                                                         ref_volume);
+    angle *= 180.0/CUBIT_PI;
+    is_cartesian = CUBIT_TRUE;
+    if ( angle <= GEOM_SIDE_LOWER ||
+         angle >= GEOM_SIDE_UPPER )
+      is_cartesian = CUBIT_FALSE;
+      //Okay, we have one major criteria achieved, this edge is a cartesian meet.
+
+    if ( !is_cartesian )
+      return CUBIT_FALSE;
+      //Now we need to check the radius of curvatures between these
+      //two surfaces. I'm not totally sure about this but I think we
+      // want the same radius of curvature.
+    double k1_s1, k2_s1, k1_s2, k2_s2;
+    CubitVector mid_point;
+    ref_edge->mid_point(mid_point);
+    ref_face->get_principal_curvatures( mid_point, k1_s1, k2_s1, ref_volume);
+    other_face->get_principal_curvatures( mid_point, k1_s2, k2_s2, ref_volume);
+    if (( is_equal(k1_s1, k1_s2) || is_equal(k1_s1, k2_s2) ) &&
+        ( is_equal(k2_s1, k1_s2) || is_equal(k2_s1, k2_s2) ) )
+        //try a different edge.
+        continue;
+    else
+      return CUBIT_FALSE;
+  }
+
+  // if all edges are tangent and share curvatures then it must be a 
+  // vertex blend.
+  return CUBIT_TRUE;
+}
+
 CubitBoolean GeomMeasureTool::find_opposite_edge( RefEdge* ref_edge,
                                                   RefFace* ref_face,
                                                   RefEdge *&other_edge,
@@ -3250,26 +4539,22 @@
 }
 CubitStatus GeomMeasureTool::get_centroid( RefFace *ref_face, CubitVector &centroid, double &tot_area )
 {
-  int i;
-  int num_tris, num_pnts, num_facets;
   GMem g_mem;
   unsigned short norm_tol = 5;
   double dist_tol = -1.0;
 
   ref_face->get_geometry_query_engine()->
-      get_graphics(ref_face->get_surface_ptr(),num_tris, num_pnts, num_facets,
-      &g_mem, norm_tol, dist_tol );
+      get_graphics(ref_face->get_surface_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;
       ref_face->get_geometry_query_engine()->
-          get_graphics(ref_face->get_surface_ptr(),num_tris, num_pnts, num_facets,
-          &g_mem, norm_tol, dist_tol );
+          get_graphics(ref_face->get_surface_ptr(), &g_mem, norm_tol, dist_tol );
   }
 
-  if(num_tris < 1)
+  if(g_mem.fListCount < 1)
   {
       // Lets give up 
       PRINT_ERROR( "Unable to find the center of a surface\n" );
@@ -3286,7 +4571,7 @@
   GPoint* plist = g_mem.point_list();
   int* facet_list = g_mem.facet_list();
   int c = 0;
-  for( i=0; i<num_tris; i++ )
+  for( ; c < g_mem.fListCount; )
   {
       p[0] = plist[facet_list[++c]];
       p[2] = plist[facet_list[++c]];
@@ -3314,6 +4599,9 @@
 	  tot_area += tri_area;
         
     }
+  if( tot_area == 0 )
+    return CUBIT_FAILURE;
+
   centroid /= tot_area;
   return CUBIT_SUCCESS;
 }    
@@ -3348,3 +4636,626 @@
                   id, centroid.x(), centroid.y(), centroid.z());
   return CUBIT_SUCCESS;
 }
+
+CubitStatus GeomMeasureTool::find_near_coincident_vertices( 
+                            DLIList<RefVolume*> &ref_volumes,
+                            DLIList<RefVertex*> &ref_vertices_out,
+                            DLIList<double> &distances,
+                            double low_tol,
+                            double high_tol,
+                            bool filter_same_volume_cases)
+{
+  DLIList<RefVertex*> tmp_vert_list;
+  DLIList<RefVertex*> ref_verts; 
+  int i,j;
+  for( i=ref_volumes.size(); i--; )
+  {
+    RefVolume *tmp_vol = ref_volumes.get_and_step();
+    tmp_vert_list.clean_out();
+    tmp_vol->ref_vertices( tmp_vert_list );
+    ref_verts += tmp_vert_list;
+  }
+
+  //put all the vertices in a tree 
+  AbstractTree <RefVertex*> *a_tree = new RTree<RefVertex*>( high_tol ); 
+  for (i=ref_verts.size(); i--;)
+    a_tree->add(ref_verts.get_and_step());
+
+  std::multimap<double, dist_vert_struct> distance_vertex_map; 
+
+  //for each vertex
+  for (i=ref_verts.size(); i--;)
+  {
+    RefVertex *tmp_vert = ref_verts.get_and_step();
+    RefVolume *v1 = tmp_vert->ref_volume();
+    CubitVector vert_xyz = tmp_vert->coordinates();
+
+    //get all close vertices
+    DLIList<RefVertex*> close_verts;
+    a_tree->find(tmp_vert->bounding_box(), close_verts);
+
+    //if any vertex is between low_tol and high_tol
+    //add it to the list
+    DLIList<RefVertex*> near_coincident_verts;
+    for( j=close_verts.size(); j--; )
+    {
+      RefVertex *close_vert = close_verts.get_and_step();
+      if( close_vert == tmp_vert ) 
+        continue;
+
+      RefVolume *v2 = close_vert->ref_volume();
+      bool check_distance = true;
+      if(filter_same_volume_cases && v1 && v2 && v1 == v2)
+        check_distance = false;
+      if(check_distance)
+      {
+        double distance = vert_xyz.distance_between( close_vert->coordinates() );
+        if( distance >= low_tol && distance <= high_tol )
+        {
+          dist_vert_struct tmp_struct;
+          tmp_struct.dist = distance;
+          tmp_struct.v1 = tmp_vert;
+          tmp_struct.v2 = close_vert;
+          distance_vertex_map.insert( std::multimap<double, dist_vert_struct>::
+                                      value_type( distance, tmp_struct ));
+        }
+      }
+    }
+
+    a_tree->remove( tmp_vert );
+  }
+
+  std::multimap<double, dist_vert_struct>::reverse_iterator iter;
+  
+  iter = distance_vertex_map.rbegin();
+  for(; iter!=distance_vertex_map.rend(); iter++ )
+  {
+    distances.append( (*iter).second.dist );
+    ref_vertices_out.append( (*iter).second.v1 );
+    ref_vertices_out.append( (*iter).second.v2 );
+  }
+
+  delete a_tree;
+
+  return CUBIT_SUCCESS;
+}
+
+// This function is similar to find_near_coincident_vertices except for the
+// fact that it will only find the closest vertex in a given volume for
+// a vertex in another volume to be close to.  This tries to exclude the case where
+// you would attempt to merge one vertex from one volume to two different
+// vertices in another volume.
+CubitStatus GeomMeasureTool::find_near_coincident_vertices_unique( 
+                            DLIList<RefVolume*> &ref_volumes,
+                            double high_tol,
+                            std::map <RefVertex*, DLIList<dist_vert_struct*>*> &vert_dist_map)
+{
+  DLIList<RefVertex*> tmp_vert_list;
+  DLIList<RefVertex*> ref_verts; 
+  int i,j;
+  for( i=ref_volumes.size(); i--; )
+  {
+    RefVolume *tmp_vol = ref_volumes.get_and_step();
+    tmp_vert_list.clean_out();
+    tmp_vol->ref_vertices( tmp_vert_list );
+    ref_verts += tmp_vert_list;
+  }
+
+  //put all the vertices in a tree 
+  AbstractTree <RefVertex*> *a_tree = new RTree<RefVertex*>( high_tol ); 
+  for (i=ref_verts.size(); i--;)
+    a_tree->add(ref_verts.get_and_step());
+
+  //for each vertex
+  for (i=ref_verts.size(); i--;)
+  {
+    RefVertex *tmp_vert = ref_verts.get_and_step();
+    RefVolume *vol1 = tmp_vert->ref_volume();
+    CubitVector vert_xyz = tmp_vert->coordinates();
+
+    //get all close vertices
+    DLIList<RefVertex*> close_verts;
+    a_tree->find(tmp_vert->bounding_box(), close_verts);
+
+    //if any vertex is between low_tol and high_tol
+    //add it to the list
+    DLIList<dist_vert_struct*> *near_coincident_verts = NULL;
+    for( j=close_verts.size(); j--; )
+    {
+      RefVertex *close_vert = close_verts.get_and_step();
+      if( close_vert == tmp_vert ) 
+        continue;
+
+      RefVolume *vol2 = close_vert->ref_volume();
+      if(vol1 && vol2 && vol1 != vol2)
+      {
+        if(!near_coincident_verts)
+        {
+          near_coincident_verts = new DLIList<dist_vert_struct*>;
+          vert_dist_map[tmp_vert] = near_coincident_verts;
+        }
+        double distance = vert_xyz.distance_between( close_vert->coordinates() );
+        int h;
+        bool found_entry_with_same_vol = false;
+        for(h=near_coincident_verts->size(); h>0 && !found_entry_with_same_vol; h--)
+        {
+          dist_vert_struct* vds = near_coincident_verts->get_and_step();
+          if(vds->vol2 == vol2)
+          {
+            found_entry_with_same_vol = true;
+            if(distance < vds->dist)
+            {
+              vds->dist = distance;
+              vds->vol2 = vol2;
+              vds->v2 = close_vert;
+            }
+          }
+        }
+        if(!found_entry_with_same_vol)
+        {
+          dist_vert_struct *new_vds = new dist_vert_struct;
+          new_vds->dist = distance;
+          new_vds->v2 = close_vert;
+          new_vds->vol2 = vol2;
+          near_coincident_verts->append(new_vds);
+        }
+      }
+    }
+    a_tree->remove( tmp_vert );
+  }
+
+  delete a_tree;
+
+  return CUBIT_SUCCESS;
+}
+
+struct dist_vert_vert_struct
+{
+  double dist;
+  RefVertex *vert1;
+  RefVertex *vert2;
+};
+
+struct dist_vert_curve_struct
+{
+  double dist;
+  RefVertex *vert;
+  RefEdge *edge;
+//  bool operator<( const dist_vert_curve_struct& b ) const
+//  {
+//    return this->dist < b.dist;
+ // }
+};
+
+struct vert_curve_dist_sort
+{
+  bool operator()( const dist_vert_curve_struct& a, const dist_vert_curve_struct& b ) const
+  {
+    return a.dist < b.dist;
+  }
+};
+
+struct vert_curve_dist_sort_ptr
+{
+  bool operator()( dist_vert_curve_struct *a, dist_vert_curve_struct *b ) const
+  {
+    if( a->dist < b->dist )
+      return true;
+    else if( a->dist > b->dist )
+      return false;
+    else 
+      return true;
+  }
+};
+
+struct vert_vert_dist_sort_ptr
+{
+  bool operator()( dist_vert_vert_struct *a, dist_vert_vert_struct *b ) const
+  {
+    if( a->dist < b->dist )
+      return true;
+    else if( a->dist > b->dist )
+      return false;
+    else 
+      return true;
+  }
+};
+
+CubitStatus GeomMeasureTool::find_closest_vertex_curve_pairs(
+                                  DLIList<RefVolume*> &vol_list,
+                                  int &num_to_return,
+                                  DLIList<RefVertex*> &vert_list,
+                                  DLIList<RefEdge*> &curve_list,
+                                  DLIList<double> &distances)
+{
+  DLIList<RefFace*> surfs;
+
+  int i, total_num_entries = 0;
+  for( i=vol_list.size(); i--; )
+  {
+    RefVolume *tmp_vol = vol_list.get_and_step();
+    tmp_vol->ref_faces( surfs );
+  }
+
+  std::set<dist_vert_curve_struct*,vert_curve_dist_sort_ptr> distance_vertex_curve_set; 
+
+  for(i=surfs.size(); i>0; i--)
+  {
+    RefFace *surf = surfs.get_and_step();
+    DLIList<RefVertex*> surf_verts;
+    surf->ref_vertices(surf_verts);
+    DLIList<RefEdge*> surf_curves;
+    surf->ref_edges(surf_curves);
+
+    int j;
+    for(j=surf_verts.size(); j>0; j--)
+    {
+      RefVertex *tmp_vert = surf_verts.get_and_step();
+      CubitVector vert_xyz = tmp_vert->coordinates();
+      CubitVector closest_pt;
+      int k;
+      for(k=surf_curves.size(); k>0; k--)
+      {
+        RefEdge *cur_edge = surf_curves.get_and_step();
+        if(cur_edge->start_vertex() != tmp_vert &&
+          cur_edge->end_vertex() != tmp_vert)
+        {
+          cur_edge->closest_point_trimmed(vert_xyz, closest_pt);
+          if(!closest_pt.about_equal(cur_edge->start_coordinates()) &&
+             !closest_pt.about_equal(cur_edge->end_coordinates()))
+          {
+            double dist_sq = vert_xyz.distance_between_squared(closest_pt);
+            dist_vert_curve_struct *tmp_struct = new dist_vert_curve_struct;
+            tmp_struct->dist = dist_sq;
+            tmp_struct->vert = tmp_vert;
+            tmp_struct->edge = cur_edge; 
+            distance_vertex_curve_set.insert( tmp_struct );
+            total_num_entries++;
+          }
+        }
+      }
+    }
+  }
+
+  std::set<dist_vert_curve_struct*, vert_curve_dist_sort_ptr>::iterator iter, upper_iter; 
+  
+  int local_num_to_return = num_to_return;
+  if(num_to_return == -1)
+  {
+    local_num_to_return = total_num_entries;
+  }
+  int cntr = 0;
+  iter = distance_vertex_curve_set.begin();
+  for(; iter!=distance_vertex_curve_set.end() && cntr < local_num_to_return; iter++ )
+  {
+    distances.append( sqrt((*iter)->dist) );
+    vert_list.append( (*iter)->vert );
+    curve_list.append( (*iter)->edge );
+    cntr++;
+  }
+
+  iter = distance_vertex_curve_set.begin();
+  for(; iter!=distance_vertex_curve_set.end(); iter++ )
+  {
+    delete *iter;
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus GeomMeasureTool::find_closest_vertex_vertex_pairs(
+                                  DLIList<RefVolume*> &vol_list,
+                                  int &num_to_return,
+                                  DLIList<RefVertex*> &vert_list1,
+                                  DLIList<RefVertex*> &vert_list2,
+                                  DLIList<double> &distances)
+{
+  std::set<dist_vert_vert_struct*,vert_vert_dist_sort_ptr> distance_vertex_vertex_set; 
+
+  int i, total_num_entries = 0;
+  for( i=vol_list.size(); i--; )
+  {
+    RefVolume *tmp_vol = vol_list.get_and_step();
+    DLIList<RefVertex*> vol_verts;
+    tmp_vol->ref_vertices(vol_verts);
+    while(vol_verts.size() > 1)
+    {
+      RefVertex *vert1 = vol_verts.pop();
+      CubitVector vert1_xyz = vert1->coordinates();
+      int j;
+      for(j=vol_verts.size(); j>0; j--)
+      {
+        RefVertex *vert2 = vol_verts.get_and_step();
+        double dist_sq = vert2->coordinates().distance_between_squared(vert1_xyz);
+        dist_vert_vert_struct *tmp_struct = new dist_vert_vert_struct;
+        tmp_struct->dist = dist_sq;
+        tmp_struct->vert1 = vert1;
+        tmp_struct->vert2 = vert2; 
+        distance_vertex_vertex_set.insert( tmp_struct );
+        total_num_entries++;
+      }
+    }
+  }
+
+  std::set<dist_vert_vert_struct*, vert_vert_dist_sort_ptr>::iterator iter, upper_iter; 
+  
+  int local_num_to_return = num_to_return;
+  if(num_to_return == -1)
+    local_num_to_return = total_num_entries;
+  int cntr = 0;
+  iter = distance_vertex_vertex_set.begin();
+  for(; iter!=distance_vertex_vertex_set.end() && cntr < local_num_to_return; iter++ )
+  {
+    distances.append( sqrt((*iter)->dist) );
+    vert_list1.append( (*iter)->vert1 );
+    vert_list2.append( (*iter)->vert2 );
+    cntr++;
+  }
+
+  iter = distance_vertex_vertex_set.begin();
+  for(; iter!=distance_vertex_vertex_set.end(); iter++ )
+  {
+    delete *iter;
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus GeomMeasureTool::find_near_coincident_vertex_curve_pairs( 
+                                DLIList<RefVolume*> &ref_vols,
+                                DLIList<RefEdge*> &ref_edges,
+                                DLIList<RefVertex*> &ref_verts,
+                                DLIList<double> &distances,
+                                double low_tol,
+                                double high_tol,
+                                bool filter_same_volume_cases)
+{
+  //get all the curves and vertices of volumes in list
+  DLIList<RefVertex*> verts;
+  DLIList<RefEdge*> curves;
+
+  RTree<RefEdge*> a_tree(high_tol);
+
+  int i,j;
+  for( i=ref_vols.size(); i--; )
+  {
+    RefVolume *tmp_vol = ref_vols.get_and_step();
+    tmp_vol->ref_vertices( verts );
+    
+    curves.clean_out();
+    tmp_vol->ref_edges( curves );
+    for( j=curves.size(); j--; )
+    {
+      RefEdge *tmp_edge = curves.get_and_step();
+      a_tree.add( tmp_edge );
+    }
+  }
+
+  ProgressTool *progress_ptr = NULL;
+  int total_verts = verts.size();
+  if (total_verts > 5)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Finding Near Coincident Vertex-Curve Pairs", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+    
+  double curr_percent = 0.0;
+  int processed_verts = 0;
+  int times = 0;
+  std::multimap<double, dist_vert_curve_struct> distance_vertex_curve_map; 
+
+  //for each vertex
+  for( i=verts.size(); i--; )
+  {
+    processed_verts++;
+    if ( progress_ptr != NULL )
+    {
+      curr_percent = ((double)(processed_verts))/((double)(total_verts));
+      progress_ptr->percent(curr_percent);
+    }
+
+    RefVertex *tmp_vert = verts.get_and_step();
+    RefVolume *v1 = tmp_vert->ref_volume();
+    CubitBox vertex_box ( tmp_vert->coordinates(), tmp_vert->coordinates() );
+    DLIList<RefEdge*> close_curves;
+    a_tree.find( vertex_box, close_curves );
+
+    CubitVector vertex_xyz = tmp_vert->coordinates(); 
+
+    for( j=close_curves.size(); j--; )
+    {
+      RefEdge *tmp_edge = close_curves.get_and_step();
+      RefVolume *v2 = tmp_edge->ref_volume();
+
+      bool check_distance = true;
+      if(filter_same_volume_cases && v1 && v2 && v1 == v2)
+        check_distance = false;
+      if(check_distance)
+      {
+        CubitVector closest_location;
+        tmp_edge->closest_point_trimmed( vertex_xyz, closest_location );
+        double distance = closest_location.distance_between( vertex_xyz );
+
+        if( distance >= low_tol && distance <= high_tol )
+        {
+          dist_vert_curve_struct tmp_struct;
+          tmp_struct.dist = distance;
+          tmp_struct.vert = tmp_vert;
+          tmp_struct.edge = tmp_edge; 
+
+          distance_vertex_curve_map.insert( std::multimap<double, dist_vert_curve_struct>::
+                                            value_type( distance, tmp_struct ));
+        }
+      }
+    }
+  }
+
+  if ( progress_ptr != NULL )
+    progress_ptr->end();
+
+  //std::set<dist_vert_curve_struct, vert_curve_dist_sort>::iterator iter, upper_iter; 
+  std::multimap<double, dist_vert_curve_struct>::reverse_iterator iter;
+  
+  iter = distance_vertex_curve_map.rbegin();
+  for(; iter!=distance_vertex_curve_map.rend(); iter++ )
+  {
+    distances.append( (*iter).second.dist );
+    ref_verts.append( (*iter).second.vert );
+    ref_edges.append( (*iter).second.edge );
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+
+struct dist_vert_surf_struct
+{
+  double dist;
+  RefVertex *vert;
+  RefFace *face;
+};
+
+struct vert_surf_dist_sort
+{
+  bool operator()( dist_vert_surf_struct a, dist_vert_surf_struct b ) const
+  {
+    if( a.dist < b.dist )
+      return true;
+    else if( a.dist > b.dist )
+      return false;
+    else 
+    {
+      if( a.vert < b.vert )
+        return true;
+      else if( a.vert > b.vert )
+        return false;
+      else if( a.face < b.face )
+        return true;
+      else if( a.face > b.face )
+        return false;
+    }
+    return false;
+  }
+};
+
+
+CubitStatus GeomMeasureTool::find_near_coincident_vertex_surface_pairs( 
+                                DLIList<RefVolume*> &ref_vols,
+                                DLIList<RefFace*> &ref_faces,
+                                DLIList<RefVertex*> &ref_verts,
+                                DLIList<double> &distances,
+                                double low_tol,
+                                double high_tol,
+                                bool filter_same_volume_cases)
+{
+  //get all the curves and vertices of volumes in list
+  DLIList<RefVertex*> verts;
+  DLIList<RefFace*> faces;
+
+  AbstractTree<RefFace*> *a_tree = new RTree<RefFace*>( high_tol );
+
+  int i,j;
+  for( i=ref_vols.size(); i--; )
+  {
+    RefVolume *tmp_vol = ref_vols.get_and_step();
+    tmp_vol->ref_vertices( verts );
+    
+    faces.clean_out();
+    tmp_vol->ref_faces( faces );
+    // Populate the Surface AbstractTree
+    for( j=faces.size(); j--; )
+    {
+      RefFace *tmp_face = faces.get_and_step();
+      a_tree->add( tmp_face );
+    }
+  }
+
+  ProgressTool *progress_ptr = NULL;
+  int total_verts = verts.size();
+  if (total_verts > 50)
+  {
+    progress_ptr = AppUtil::instance()->progress_tool();
+    assert(progress_ptr != NULL);
+    progress_ptr->start(0, 100, "Finding Near Coincident Vertex-Surface Pairs", 
+      NULL, CUBIT_TRUE, CUBIT_TRUE);
+  }
+  double curr_percent = 0.0;
+  int processed_verts = 0;
+
+  std::multimap<double, dist_vert_surf_struct> distance_vertex_surface_map; 
+
+  //for each vertex
+  for( i=verts.size(); i--; )
+  {
+    processed_verts++;
+    if ( progress_ptr != NULL )
+    {
+      curr_percent = ((double)(processed_verts))/((double)(total_verts));
+      progress_ptr->percent(curr_percent);
+    }
+
+    RefVertex *tmp_vert = verts.get_and_step();
+    RefVolume *v1 = tmp_vert->ref_volume();
+    CubitBox vertex_box ( tmp_vert->coordinates(), tmp_vert->coordinates() );
+    DLIList<RefFace*> close_faces;
+    a_tree->find( vertex_box, close_faces);
+
+    CubitVector vertex_xyz = tmp_vert->coordinates(); 
+
+    for( j=close_faces.size(); j--; )
+    {
+      RefFace *tmp_face = close_faces.get_and_step();
+      RefVolume *v2 = tmp_face->ref_volume();
+
+      bool check = true;
+      if(filter_same_volume_cases && v1 && v2 && v1 == v2)
+        check = false;
+
+      if(check)
+      {
+        DLIList<RefVertex*> tmp_verts;
+        tmp_face->ref_vertices( tmp_verts );
+        if( tmp_verts.is_in_list( tmp_vert ) ) 
+          continue;
+
+        CubitVector closest_location;
+        tmp_face->find_closest_point_trimmed( vertex_xyz, closest_location );
+        double distance = closest_location.distance_between( vertex_xyz );
+
+        if( distance > low_tol && distance < high_tol )
+        {
+          dist_vert_surf_struct tmp_struct;
+          tmp_struct.dist = distance;
+          tmp_struct.vert = tmp_vert;
+          tmp_struct.face = tmp_face; 
+          distance_vertex_surface_map.insert( std::multimap<double, dist_vert_surf_struct>::
+                                      value_type( distance, tmp_struct ));
+        }
+      }
+    }
+  }
+
+  if ( progress_ptr != NULL )
+    progress_ptr->end();
+
+  std::multimap<double, dist_vert_surf_struct>::reverse_iterator iter;
+
+  iter = distance_vertex_surface_map.rbegin();
+  for(; iter!=distance_vertex_surface_map.rend(); iter++ )
+  {
+    distances.append( (*iter).second.dist );
+    ref_verts.append( (*iter).second.vert );
+    ref_faces.append( (*iter).second.face);
+  }
+
+  delete a_tree;
+
+  return CUBIT_SUCCESS;
+}
+
+
+
+
+

Modified: cgm/branches/cubit/geom/GeomMeasureTool.hpp
===================================================================
--- cgm/branches/cubit/geom/GeomMeasureTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeomMeasureTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -20,6 +20,8 @@
 class GeomPoint;
 class GeomSeg;
 #include "CubitGeomConfigure.h"
+#include <vector>
+#include <map>
 
 typedef DLIList <GeomPoint*> PointList;
 typedef DLIList <PointList*> PointLoopList;
@@ -34,6 +36,14 @@
 const double GEOM_CORNER_UPPER = 273.0;
 const double GEOM_REVERSAL_LOWER = 355.0;
 
+struct dist_vert_struct
+{
+  double dist;
+  RefVertex *v1;
+  RefVertex *v2;
+  RefVolume *vol2;
+};
+
 class AreaHashTuple 
 {
 public:
@@ -45,6 +55,7 @@
   double myArea;
 };
 
+//! Calculates measurements and statistics for a given entity.
 class CUBIT_GEOM_EXPORT GeomMeasureTool
 {
 private:
@@ -56,10 +67,10 @@
                                     DLIList <RefVolume*> &ref_volumes );
   static void get_bodies_from_list(DLIList <RefVolume*> &entity_list,
                                    DLIList <Body*> &ref_bodies );
-    ///
-    ///converts the entity list, and expands the list to get the edges,
-    ///faces or volumes of the entities.
-    ///
+  ///
+  ///converts the entity list, and expands the list to get the edges,
+  ///faces or volumes of the entities.
+  ///
 
   static double dist_sq_point_data( CubitVector &curr_point,
                                     GeomSeg *&curr_seg );
@@ -112,6 +123,11 @@
     /// Returns TRUE if they are, false if they aren't.
     ///
 
+  static RefFace* valid_start( DLIList <RefFace*> &all_faces );
+
+  static void face_list_from_volume_list( DLIList <RefVolume*> &input_vols,
+                                          DLIList <RefFace*> &all_faces );
+
  public:
   GeomMeasureTool()
     {}
@@ -119,6 +135,17 @@
   ~GeomMeasureTool()
     {}
 
+  //! Determines if a surface is narrow.
+  static bool is_surface_narrow(RefFace *face, double small_curve_size);
+
+  //! Determines points along which to make a curve for splitting a narrow surface.
+  static void find_split_points_for_narrow_regions(RefFace *face,
+                                        double size, 
+                                        DLIList<CubitVector> &split_pos1_list,
+                                        DLIList<CubitVector> &split_pos2_list);
+  
+  //! Find the smallest, longest and average size of the curves.  Also
+  //! compute the sum of all the curve.  Do that for a list of RefEntity pointers.
   static void measure_curve_length(DLIList <RefEntity*> &entity_list,
                                    double &smallest,
                                    RefEdge *&smallest_edge,
@@ -126,11 +153,9 @@
                                    RefEdge *&largest_edge,
                                    double &average,
                                    double &sum);
-    ///
-    ///Find the smallest, longest and average size of the curves.  Also
-    ///compute the sum of all the curve.  Do that for a list of RefEntity pointers.
-    ///
 
+  //! Find the smallest, longest and average size of the curves.  Also
+  //! compute the sum of all the curve.  Do that for a list of RefEdge pointers.
   static void measure_curve_length(DLIList <RefEdge*> &ref_edges,
                                    double &smallest,
                                    RefEdge *&smallest_edge,
@@ -138,35 +163,74 @@
                                    RefEdge *&largest_edge,
                                    double &average,
                                    double &sum);
-    ///
-    ///Find the smallest, longest and average size of the curves.  Also
-    ///compute the sum of all the curve.  Do that for a list of RefEdge pointers.
-    ///
-    
 
+  //! Finds the curve with the smallest length on the surface.
+  //! Also find the biggest change in curve lengths where
+  //! the ratio is the largest curve divided by the smallest curve.
   static void measure_face_curves( RefFace *ref_face,
                                    double &min_curve_length,
                                    double &max_curve_ratio,
                                    RefEdge *&min_ref_edge);
-    ///
-    /// Finds the curve with the smallest length on the surface.
-    /// Also find the biggest change in curve lengths where
-    /// the ratio is the largest curve divided by the smallest curve.
-    ///
 
+  //! Determines if a narrow region exists between the
+  //! passed-in edge and any other edge in the passed-in
+  //! face.  'tol' defines what is 'narrow'.  A non-zero
+  //! int is returned if a narrow region exists.
+  static int narrow_region_exists(RefFace *face,
+                                  RefEdge *edge,
+                                  const double &tol);
+  //! Determines whether a narrow region exists between the two
+  //! passed-in edges on the passed-in face.  'tol' specifies what
+  //! 'narrow' is.  The four lists that are returned contain points
+  //! at which the face can be split in order to separate off the
+  //! narrow region.  The 'pos' lists contain split points on the
+  //! edges that are not on pre-existing vertices.  If a split point
+  //! falls on a pre-existing vertex it will show up in the 'vert' list.
+  //! The points/vertices in the lists are ordered so that a point/vertex
+  //! in an 'e1' list will correspond with a point/vertex in an 'e2' list.
+  //! If a narrow region exists between the edges a non-zero value will
+  //! be returned.
+  static int narrow_region_exists(
+                          RefEdge *e1,
+                          RefEdge *e2,
+                          RefFace *face,
+                          const double &tol,
+                          DLIList<CubitVector*> &e1_pos_list,
+                          DLIList<CubitVector*> &e2_pos_list,
+                          DLIList<RefVertex*> &e1_vert_list,
+                          DLIList<RefVertex*> &e2_vert_list);
+  //! Determine if a narrow region exists on the given face.  The passed-in
+  //! tolerance defines the narrow size.  Returns a non-zero value
+  //! if a narrow region exists.
+  static int narrow_region_exists(RefFace *face,
+                           const double &tol);
+  //! Checks to see if at the given position the two edges are close together and
+  //! have the same tangent.  'e1' is one of the edges.  'face' is the face that
+  //! the edges are on.  'pt_on_e1' is a position on 'e1'.  'pt_on_e1' will be
+  //! projected onto the other edge, 'e2', to look for closeness.  'tol_sq' is
+  //! the squared distance defining what is 'close'.  The closest pt on 'e2' to
+  //! 'pt_on_e1' is returned.  Returns a non-zero int if the two edges form a narrow region
+  //! at the given point.
+  static int is_narrow_region_at_point(RefEdge *e1,
+                                      RefFace *face,
+                                      const CubitVector &pt_on_e1,
+                                      RefEdge *e2,
+                                      const double &tol_sq,
+                                      CubitVector &closest);
+
+  //! Find the smallest distance between multiple loops on the surface.
+  //! Find the smallest distance between two curves.  This could be the length
+  //! of the smallest curve...
+  //! Also calculate the angles between curves on the faces.
+  //! The tolerance is used to specify the faceting to approximate the boundaries.
   static CubitStatus measure_face_loops(RefFace *face,
                                         double &min_distance_between_loops,
                                         double &min_distance_in_one_loop,
                                         double &min_angle, double &max_angle,
                                         double tolerance);
-    ///
-    ///Find the smallest distance between multiple loops on the surface.
-    ///Find the smallest distance between two curves.  This could be the length
-    ///of the smallest curve...
-    ///Also calculate the angles between curves on the faces.
-    ///The tolerance is used to specify the faceting to approximate the boundaries.
-    ///
 
+  //! Find the smallest, largest and average area of the faces contained
+  //! in the entity list..  Also compute the sum of all the face area.
   static void  measure_face_area (DLIList <RefEntity*> &entity_list,
                                   double &smallest,
                                   RefFace *&smallest_face,
@@ -174,11 +238,9 @@
                                   RefFace *&largest_face,
                                   double &average,
                                   double &sum);
-    ///
-    ///Find the smallest, largest and average area of the faces contained
-    ///in the entity list..  Also compute the sum of all the face area.
-    ///
 
+  //! Find the smallest, largest and average area of the faces 
+  //! in the face list..  Also compute the sum of all the face area.
   static void  measure_face_area (DLIList <RefFace*> &ref_faces,
                                   double &smallest,
                                   RefFace *&smallest_face,
@@ -186,11 +248,9 @@
                                   RefFace *&largest_face,
                                   double &average,
                                   double &sum);
-    ///
-    ///Find the smallest, largest and average area of the faces 
-    ///in the face list..  Also compute the sum of all the face area.
-    ///
   
+  //! Find the smallest, largest, and average volume.  Compute the sum of all
+  //! the volumes for the volumes contained by the entities in the entity list.
   static void  measure_volume_volume (DLIList <RefEntity*> &entity_list,
                                       double &smallest,
                                       RefVolume *&smallest_volume,
@@ -198,11 +258,9 @@
                                       RefVolume *&largest_volume,
                                       double &average,
                                       double &sum);
-    ///
-    ///Find the smallest, largest, and average volume.  Compute the sum of all
-    ///the volumes for the volumes contained by the entities in the entity list.
-    ///
 
+  //! Find the smallest, largest, and average volume.  Compute the sum of all
+  //! the volumes in the list.
   static void  measure_volume_volume (DLIList <RefVolume*> &ref_volumes,
                                       double &smallest,
                                       RefVolume *&smallest_volume,
@@ -210,10 +268,6 @@
                                       RefVolume *&largest_volume,
                                       double &average,
                                       double &sum);
-    ///
-    ///Find the smallest, largest, and average volume.  Compute the sum of all
-    ///the volumes in the list.
-    ///
 
 #ifdef BOYD14
   static void  measure_face_hydraulic_radius( DLIList <RefEntity*> &entity_list,
@@ -274,69 +328,53 @@
                                       double &average_curvature_change);
 #endif
 
+  //! Given a list of volumes, return number of surface merged, unmerged, 
+  //! and ratio between the two.
   static void merged_unmerged_surface_ratio(DLIList <RefVolume*> &ref_volumes,
                                             int &merged, int &unmerged,
                                             double &ratio);
 
-  static void report_intersected_bodies(DLIList <RefVolume*> &volume_list,
-                                        DLIList <Body*> &intersection_list);
+  //! From a list of volumes, find ones that intersect. 
+  static void report_intersected_volumes(DLIList <RefVolume*> &volume_list,
+                                        DLIList <RefVolume*> &intersection_list);
   
+  //! From a list of bodies, find ones that intersect. 
   static void report_intersected_bodies(DLIList <Body*> &ref_bodies,
                                         DLIList <Body*> &intersection_list);
-
-  static RefFace* valid_start( DLIList <RefFace*> &all_faces );
-
-  static void face_list_from_volume_list( DLIList <RefVolume*> &input_vols,
-                                          DLIList <RefFace*> &all_faces );
   
+  //! Finds lists of surfaces sharing common curves.  Lists are found in the returned RefGroup. 
   static void find_shells( DLIList <RefVolume*> &input_vols,
                            RefGroup *&owner_groups,
                            int &number_of_shells);
-
-  static void ratio_of_shells_to_volumes(int number_of_shells,
-                                         DLIList <RefVolume*> &ref_volumes,
-                                         int &number_of_volumes,
-                                         double &ratio);
   
-  
+  //! Gets the points in ordered loops that are used to facet the boundary
+  //! of the surface.
   static CubitStatus get_boundary_points( RefFace *ref_face,
                                           PointLoopList &boundary_point_loops,
                                           double seg_length_tol);
-    ///
-    ///Gets the points in ordered loops that are used to facet the boundary
-    ///of the surface.
-    ///
 
+  //! Get the points that approximate the curve, use the graphics facets.
   static CubitStatus get_curve_facets( RefEdge* curve,
                                        PointList &segments,
                                        double seg_length_tol );
-    ///
-    ///Get the points that approximate the curve, use the graphics facets.
-    ///  
 
+  //! Converts the loops of points to line segments.  Can fail if it
+  //! can't determine the owner of the line segment. The refface may
+  //! be needed to help determine ownership.
   static CubitStatus convert_to_lines(PointLoopList &boundary_point_loops,
                                       SegLoopList &boundary_line_loops,
                                       RefFace *ref_face );
-    ///
-    ///Converts the loops of points to line segments.  Can fail if it
-    ///can't determine the owner of the line segment. The refface may
-    ///be needed to help determine ownership.
-    ///
 
+  //! Prints a summary of all of the surface information.
+  //! min curve length, max adjacent curve ratios, min angle, max angle,
+  //! min area, max area, min hydraulic radius, min distance between loops,
+  //! min distance between a single loop.
   static void print_surface_measure_summary( DLIList <RefFace*> &ref_faces );
-    ///
-    ///Prints a summary of all of the surface information.
-    ///min curve length, max adjacent curve ratios, min angle, max angle,
-    ///min area, max area, min hydraulic radius, min distance between loops,
-    ///min distance between a single loop.
-    ///
 
+  //! Prints summary of all the volume information, including the
+  //! information of the
+  //! surfaces in the volumes.
   static void print_volume_measure_summary(DLIList <RefVolume*> &ref_volumes);
-    ///
-    /// Prints summary of all the volume information, including the
-    /// information of the
-    /// surfaces in the volumes.
-    ///
 
 #ifdef BOYD14
   static void print_body_measure_summary(DLIList <Body*> &bodies);
@@ -346,64 +384,74 @@
     ///
 #endif
 
+  //! Finds the max ratio of adjacent face areas (big face area
+  //! divided by  small face area);
   static void find_adjacent_face_ratios(RefVolume *curr_volume,
                                         double &max_face_ratio,
                                         RefFace *&big_face,
                                         RefFace *&small_face);
-    ///
-    /// Finds the max ratio of adjacent face areas (big face area
-    /// divided by  small face area);
-    ///
+  
+  //! Finds narrow surfaces in the specified volumes.
+  static void find_narrow_faces(DLIList<RefVolume*> &ref_vols,
+                                        double small_curve_size,
+                                        DLIList<RefFace*> &narrow_faces,
+                                        DLIList<RefFace*> &surfs_to_ignore);
 
+  //! Finds the curves with lengths less than the given tol in specified volume.
+  static RefEdge* find_first_small_curve(RefVolume* vol,
+                                         double tol);
+
+  //! Finds the curves with lengths less than the given tol.
   static void find_small_curves( DLIList <RefVolume*> &ref_vols,
                                  double tol,
                                  DLIList <RefEdge*> &small_curves,
                                  DLIList <double> &small_lengths);
-    ///
-    /// Finds the curves with lengths less than the given tol.
-    ///
 
+  //! Finds the curves with lengths less than the given tol.
+  static void find_surfs_with_narrow_regions( DLIList <RefVolume*> &ref_vols,
+                                 double tol,
+                                 DLIList <RefFace*> &surfs_with_narrow_regions);
+
+  //! Finds the faces with areas less than the given ammount.
   static void find_small_faces( DLIList <RefVolume*> &ref_vols,
                                 double tol,
                                 DLIList <RefFace*> &small_faces);
-    ///
-    /// Finds the faces with areas less than the given ammount.
-    ///
 
+  //! Finds the faces with hydraulic radii less than tol.
+  //! The hydraulic radus is defined by 4*(A/P) where
+  //! A is the area of the surface and P is the total perimiter
+  //! length around the surface.
+  //! Also finds the % surfaces that are planar.   And finds
+  //! the % surfaces that are planar and conical.
+  //! This is based on the geometry type, not some actual measurement.
   static void find_small_faces_hydraulic_radius( DLIList <RefVolume*> &ref_vols,
                                                  double tol,
                                                  DLIList <RefFace*> &small_faces,
                                                  DLIList <double> &small_hyd_rad,
                                                  double &percent_planar,
                                                  double &percent_pl_co);
-    ///
-    /// Finds the faces with hydraulic radii less than tol.
-    /// The hydraulic radus is defined by 4*(A/P) where
-    /// A is the area of the surface and P is the total perimiter
-    /// length around the surface.
-    /// Also finds the % surfaces that are planar.   And finds
-    /// the % surfaces that are planar and conical.
-    /// This is based on the geometry type, not some actual measurement.
-    ///
   
+  //! Finds the volumes with volumes less than tol.
   static void find_small_volumes( DLIList <RefVolume*> &ref_vols,
                                   double tol,
                                   DLIList <RefVolume*> &small_volumes);
-    ///
-    /// Finds the volumes with volumes less than tol.
-    ///
 
+  //! Measures the hydraulic radii for the volumes by 6*(V/A) where
+  //! V is the volume of the volume and A is the total area of all
+  //! the volume's surfaces.  Volumes with small hydraulic radii (compared
+  //! to tol) are stored in the small_volumes list.
   static void find_small_volumes_hydraulic_radius( DLIList <RefVolume*> &ref_vols,
                                                    double tol,
                                                    DLIList <RefVolume*> &small_volumes,
                                                    DLIList <double> &small_hyd_rad);
-    ///
-    /// Measures the hydraulic radii for the volumes by 6*(V/A) where
-    /// V is the volume of the volume and A is the total area of all
-    /// the volume's surfaces.  Volumes with small hydraulic radii (compared
-    /// to tol) are stored in the small_volumes list.
-    ///
   
+  //! For each surface in the volume, find the interior angles
+  //! defined by the curves in the surfaces that are either below or
+  //! greater than the the upper and lower bounds.  The angles
+  //! and therefor bounds, are tracked in degrees.
+  //! Curves that fit into these categories are stored pairwise in the
+  //! large or small edge_angles lists.  The corresponding angle
+  //! measurements are stored in the respective small and large angles lists.
   static void find_interior_curve_angles( RefVolume* ref_volume,
                                           double upper_bound,
                                           double lower_bound,
@@ -414,34 +462,24 @@
                                           int &total_interior,
                                           int &total_fuzzy);
   
-    ///
-    /// For each surface in the volume, find the interior angles
-    /// defined by the curves in the surfaces that are either below or
-    /// greater than the the upper and lower bounds.  The angles
-    /// and therefor bounds, are tracked in degrees.
-    /// Curves that fit into these categories are stored pairwise in the
-    /// large or small edge_angles lists.  The corresponding angle
-    /// measurements are stored in the respective small and large angles lists.
-    ///
-
+  //! Find the tangential meetings in the volume.
+  //! This specifically looks for surfaces that meet tangentially
+  //! that would be a problem.  Usually these are surfaces that
+  //! come into a side 180 degrees and on top there is a
+  //! sharpe angle.  Usually if there isn't a sharpe curve
+  //! angle these meetings are not bad.
+  //! Note that this function assumes that you are passing
+  //! in sets of curve edges that have small interior angles between them.
+  //! It also assumes that the edge pairs are ordered as they would
+  //! be found in the surfaces (first edge then next edge).
+  //! Basically, call the funciton, find_interior_curve_angles
+  //! before calling this function, and pass this function those results.
   static void find_sharp_tangential_meets( RefVolume *ref_volume,
                                            DLIList <RefEdge*> &small_angle_edge_pairs,
                                            DLIList <RefFace*> &tangential_surface_pairs );
-    ///
-    /// Find the tangential meetings in the volume.
-    /// This specifically looks for surfaces that meet tangentially
-    /// that would be a problem.  Usually these are surfaces that
-    /// come into a side 180 degrees and on top there is a
-    /// sharpe angle.  Usually if there isn't a sharpe curve
-    /// angle these meetings are not bad.
-    /// Note that this function assumes that you are passing
-    /// in sets of curve edges that have small interior angles between them.
-    /// It also assumes that the edge pairs are ordered as they would
-    /// be found in the surfaces (first edge then next edge).
-    /// Basically, call the funciton, find_interior_curve_angles
-    /// before calling this function, and pass this function those results.
-    ///
 
+  //! Finds the large and small angles or rather the surfaces on the volumes
+  //! that make them.
   static void find_dihedral_angles( DLIList<RefVolume*> &ref_vols,
                                     double upper_bound,
                                     double lower_bound,
@@ -452,12 +490,12 @@
                                     int &total_interior,
                                     int &total_fuzzy,
                                     int &total_not_flat);
-    ///
-    /// Finds the large and small angles or rather the surfaces on the volumes
-    /// that make them.
-    ///
   
 
+  //! Finds the surfaces that have big and small angles compared to the upper
+  //! and lower bounds (these should be in degrees...).
+  //! The faces that make these angles are paired (one after the other)
+  //! in the lists large and small angles.
   static void find_dihedral_angles( RefVolume *curr_volume,
                                     double lower_bound,
                                     double upper_bound,
@@ -468,40 +506,30 @@
                                     int &total_interior,
                                     int &total_fuzzy,
                                     int &total_not_flat);
-    ///             
-    /// Finds the surfaces that have big and small angles compared to the upper
-    /// and lower bounds (these should be in degrees...).
-    /// The faces that make these angles are paired (one after the other)
-    /// in the lists large and small angles.
-    ///
 
+  //! Finds the surfaces with multiple loops that have small, relative
+  //! to tol, distances between the loops.
+  //! Note that all the lists are syncronized to be connected.
+  //! The pairs of close edges with the small_lengths and
+  //! the surfaces that they are on.  The close_loop_faces list
+  //! may not contain distinct instances of faces, as they
+  //! may be repeated.  Note that this will only find the
+  //! closest edge pair, within tol, for each loop.
   static void find_close_loops(DLIList <RefVolume*> &ref_vols,
                                DLIList <RefEdge*> &close_edges,
                                DLIList <RefFace*> &close_loop_faces,
                                DLIList <double> &small_lengths,
                                double tol);
-    ///
-    /// Finds the surfaces with multiple loops that have small, relative
-    /// to tol, distances between the loops.
-    /// Note that all the lists are syncronized to be connected.
-    /// The pairs of close edges with the small_lengths and
-    /// the surfaces that they are on.  The close_loop_faces list
-    /// may not contain distinct instances of faces, as they
-    /// may be repeated.  Note that this will only find the
-    /// closest edge pair, within tol, for each loop.
-    ///
 
+  //! Finds the edges of the loops that are within some tol.  The
+  //! edges are stored in successive pairs in close_edges while
+  //! the actual distances are stored in the small_lengths list.
+  //! These lists are syncronized (and are assumed to be empty upon
+  //! entrance to the function).
   static void find_close_loops(RefFace *face,
                                DLIList <RefEdge*> &close_edges,
                                DLIList <double> &small_lengths,
                                double tol);
-    ///
-    /// Finds the edges of the loops that are within some tol.  The
-    /// edges are stored in successive pairs in close_edges while
-    /// the actual distances are stored in the small_lengths list.
-    /// These lists are syncronized (and are assumed to be empty upon
-    /// entrance to the function).
-    ///
 
 #ifdef BOYD14
   static void count_entities(DLIList<RefVolume*> &ref_vols,
@@ -514,69 +542,139 @@
     ///
 #endif
 
+  //! Measures the area of the curr_face.  Uses
+  //! the GeomDataObserver class to cache the area on the face.
+  //! After calling this function, curr_face will have
+  //! a GeomDataObserver observing it.  It will get removed if
+  //! the surface is altered or changed.
   static double measure_area(RefFace* curr_face);
-    ///
-    /// Measures the area of the curr_face.  Uses
-    /// the GeomDataObserver class to cache the area on the face.
-    /// After calling this function, curr_face will have
-    /// a GeomDataObserver observing it.  It will get removed if
-    /// the surface is altered or changed.
-    ///
 
+  //! This function simply gets the bad entities of the volume.  This
+  //! assumes the volume is from some solid modelar where this function
+  //! is defined. If not, it will just be empty...
   static void find_bad_geometry(RefVolume *volume,
                                 DLIList <RefEntity*> &bad_ents);
-    ///
-    /// This function simply gets the bad entities of the volume.  This
-    /// assumes the volume is from some solid modelar where this function
-    /// is defined. If not, it will just be empty...
-    ///
 
+  //@{
+  //! Find the irregular vertex valences.
+  //! Find things like vertices with valences greater than 4.
+  //! Assume for now that the volumes are not merged..
   static void find_irregular_valence( DLIList <RefVolume*> &ref_volumes,
                                       DLIList <RefVertex*> &irregular_vertices);
   static void find_irregular_valence( RefVolume* ref_volume,
                                       DLIList <RefVertex*> &irregular_vertices);
-    ///
-    /// Find the irregular vertex valences.
-    /// Find things like vertices with valences greater than 4.
-    /// Assume for now that the volumes are not merged..
-    ///
+  //@}
 
+  //!  Find fillets and rounds.
+  //!
+  //!  ====IMPORTANT====
+  //!  Calling functions BEWARE, YOU MUST DELETE THE LISTS OF
+  //!  BLEND SURFACES IN THE BLEND GROUPS AFTER CALLING THIS FUNCTION!!!!
+  //!  ====IMPORTANT====
   static void find_blends( RefVolume *ref_volume,
                            DLIList <RefFace*> &blend_faces,
                            DLIList<DLIList<RefFace*>*> &blend_groups);
-    ///   
-    ///  Find fillets and rounds.
-    ///
-    ///  ====IMPORTANT====
-    ///  Calling functions BEWARE, YOU MUST DELETE THE LISTS OF
-    ///  BLEND SURFACES IN THE BLEND GROUPS AFTER CALLING THIS FUNCTION!!!!
-    ///  ====IMPORTANT====
-    ///
-    ///
 
+  //! Determines if a face is a blend surface, returns the
+  //! ref_edge on one side of the blend and other_edge on
+  //! the opposite side.  For this type of blend, only ref_edge 
+  //! must be tangentially meeting with another surface.  
+  //! Other_edge must be oriented orthogonally to it and may 
+  //! or may not blend with another surface.  This assumes a
+  //! rectangular blend surface, without holes.
   static CubitBoolean is_face_blend(RefFace *ref_face,
                                     RefVolume *ref_volume,
                                     RefEdge *&ref_edge,
                                     RefEdge *&other_edge);
-    ///
-    /// Determines if a face is a blend surface, returns the
-    /// ref_edge on one side of the blend and other_edge on
-    /// the opposite side.  For this type of blend, only ref_edge 
-    /// must be tangentially meeting with another surface.  
-    /// Other_edge must be oriented orthogonally to it and may 
-    /// or may not blend with another surface.  This assumes a
-    /// rectangular blend surface, without holes.
-    ///
+
+  //! Determines if a face is a vertex blend surface.  It
+  //! assumes that a vertex blend will be tangent to all
+  //! adjoining surfaces and that the curvatures will be
+  //! shared at the edges.
+  static CubitBoolean is_vertex_blend(RefFace *ref_face, 
+                                      RefVolume *ref_volume);
+
+  //! Given a starting blend surface find a chain of blends from
+  //! that surface.  
+  //!
+  //! Note that this function intentionally does _not_
+  //! clear the blend_face list so that additional chains can be added.
+  static CubitStatus find_blend_chains( RefFace *start_face,
+                             std::vector<std::vector< RefFace*> > &blend_chains);
+
+  //! should this one be private?
+  //! Given a blend surface and one of the cross curves, find the
+  //! blends connected along the edge in the one direction.
+  static void find_blends_from_edge( RefVolume* ref_volume, 
+                                         RefFace *start_face, 
+                                         RefEdge* start_edge,
+                                         std::vector <RefFace*> &blend_faces);
+
+  //! Takes the area-weighted average of all display facet
+  //! centroids and updates the passed in CubitVector to be 
+  //! that location.  Also updates the tot_area variable to 
+  //! give the total facet area for the passed in ref_face.
+  static CubitStatus get_centroid( RefFace *ref_face, 
+                                   CubitVector &centroid, double &tot_area );
+  
+  //! Finds averge center of specified surfaces. 
+  static CubitStatus center( DLIList<RefFace*> ref_faces );
  
-  static CubitStatus get_centroid( RefFace *ref_face, CubitVector &centroid, double &tot_area );
-	///
-    /// Takes the area-weighted average of all display facet
-    /// centroids and updates the passed in CubitVector to be 
-    /// that location.  Also updates the tot_area variable to 
-    /// give the total facet area for the passed in ref_face.
-    ///
+  //! Finds the 'n' closest vertex-vertex pairs and their distances apart.
+  static CubitStatus find_closest_vertex_vertex_pairs(
+                                  DLIList<RefVolume*> &vol_list,
+                                  int &num_to_return,
+                                  DLIList<RefVertex*> &vert_list1,
+                                  DLIList<RefVertex*> &vert_list2,
+                                  DLIList<double> &distances);
 
-  static CubitStatus center( DLIList<RefFace*> ref_faces );
+  //! Finds the 'n' closest vertex-curve pairs and their distances apart.
+  static CubitStatus find_closest_vertex_curve_pairs(
+                                  DLIList<RefVolume*> &vol_list,
+                                  int &num_to_return,
+                                  DLIList<RefVertex*> &vert_list,
+                                  DLIList<RefEdge*> &curve_list,
+                                  DLIList<double> &distances);
+
+  //! Finds coincident vertex-vertex pairs where each vertex is in a separate volume.
+  //! The two vertices in a vertex-vertex pairs are within high_tol of each other. 
+  static CubitStatus find_near_coincident_vertices_unique( 
+                            DLIList<RefVolume*> &ref_volumes,
+                            double high_tol,
+                            std::map <RefVertex*, DLIList<dist_vert_struct*>*> &vert_dist_map);
+
+  //! Finds coincident vertex-vertex pairs where the vertices in the pair are
+  //! between low_tol and high_tol of one another. 
+  static CubitStatus find_near_coincident_vertices( 
+                                        DLIList<RefVolume*> &ref_volumes,
+                                        DLIList<RefVertex*> &ref_vertices_out,
+                                        DLIList<double> &distances,
+                                        double low_tol,
+                                        double high_tol,
+                                        bool filter_same_volume_cases = false);
+
+  //! Finds coincident vertex-curve pairs where with distance between the 
+  //! vertex and curve is greater than low_tol but less than high_tol.
+  static CubitStatus find_near_coincident_vertex_curve_pairs( 
+                                DLIList<RefVolume*> &ref_vols,
+                                DLIList<RefEdge*> &ref_edges,
+                                DLIList<RefVertex*> &ref_verts,
+                                DLIList<double> &distances,
+                                double low_tol,
+                                double high_tol,
+                                bool filter_same_volume_cases = false);
+
+  //! Finds coincident vertex-surface pairs where with distance between the 
+  //! vertex and surface is greater than low_tol but less than high_tol.
+  static CubitStatus find_near_coincident_vertex_surface_pairs( 
+                                DLIList<RefVolume*> &ref_vols,
+                                DLIList<RefFace*> &ref_faces,
+                                DLIList<RefVertex*> &ref_verts,
+                                DLIList<double> &distances,
+                                double low_tol,
+                                double high_tol,
+                                bool filter_same_volume_cases = false);
+
 };
 #endif
 

Modified: cgm/branches/cubit/geom/GeometryFeatureTool.hpp
===================================================================
--- cgm/branches/cubit/geom/GeometryFeatureTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryFeatureTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -30,6 +30,8 @@
     //! destructor
     ~GeometryFeatureTool();
 
+   static void delete_instance() { if(instance_) delete instance_;};  
+
     //! add a feature engine to the list
     void add_gfe( GeometryFeatureEngine *gfe_ptr );
 

Modified: cgm/branches/cubit/geom/GeometryHealerTool.cpp
===================================================================
--- cgm/branches/cubit/geom/GeometryHealerTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryHealerTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -294,8 +294,15 @@
 
    GeometryHealerEngine* GHEPtr = get_engine(body_list.get());
    if (GHEPtr)
-      return GHEPtr->auto_heal_bodies(body_list, new_body_list, bad_geometry,
+   {
+      CubitStatus healer_status = GHEPtr->auto_heal_bodies(body_list, new_body_list, bad_geometry,
                                       rebuild, keep_old, make_tolerant, logfile_ptr);
+
+     // if( healer_status == CUBIT_SUCCESS )
+        CubitObserver::notify_static_observers(NULL, HEALER_COMPLETED);
+
+      return healer_status;
+   }
    else
       PRINT_ERROR( "Bodies are of a geometry engine without a healer\n"
                    "         and cannot be healed.\n");

Modified: cgm/branches/cubit/geom/GeometryHealerTool.hpp
===================================================================
--- cgm/branches/cubit/geom/GeometryHealerTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryHealerTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -35,9 +35,9 @@
 class RefEdge;
 
 class Body;
-
 // *** END FORWARD DECLARATIONS *** //
 
+//!  Class used for healing geometry.  ACIS-specific.
 class CUBIT_GEOM_EXPORT GeometryHealerTool
 {
    public:
@@ -45,6 +45,15 @@
       // singleton pattern class instance interface
       static GeometryHealerTool* instance( GeometryHealerEngine* GHEPtr = NULL );
 
+      static void delete_instance() 
+      {
+        if (instance_)
+        {
+          delete instance_;
+          instance_ = NULL;
+        }
+      };
+
       // destructor
       ~GeometryHealerTool();
 
@@ -53,7 +62,7 @@
       // set the default healer engine
 //      void set_default_engine( GeometryHealerEngine *ghe_ptr );
 
-      // add a healer engine to the list
+      //! add a healer engine to the list
       void add_ghe( GeometryHealerEngine *ghe_ptr );
 
       // remove a healer engine from the list
@@ -76,6 +85,9 @@
 
       // *** BEGIN HEALER FUNCTIONS *** //
    public:
+      //! Uses the autohealer to heal the given body list.  The rebuild option
+      //! can be used for more rigorous healing, where each surface is pulled off,
+      //! healed, and then stitched back into a body.
       CubitStatus auto_heal_bodies( DLIList<Body*> &body_list, 
                                     DLIList<Body*> &new_body_list,
                                     DLIList<TopologyEntity*> &bad_geometry,
@@ -83,10 +95,10 @@
                                     CubitBoolean keep_old = CUBIT_FALSE,
                                     CubitBoolean make_tolerant = CUBIT_FALSE,
                                     FILE* logfile_ptr = NULL );
-      // Uses the autohealer to heal the given body list.  The rebuild option
-      // can be used for more rigorous healing, where each surface is pulled off,
-      // healed, and then stitched back into a body.
 
+      //! Heals the input bodies, using either autoheal or incremental,
+      //! depending on the switches that are setup.  Writes to the logfile
+      //! if it's been opened.
       CubitStatus heal_bodies( DLIList<Body*> &body_list, 
                                DLIList<Body*> &new_body_list,
                                DLIList<TopologyEntity*> &bad_geometry,
@@ -94,29 +106,74 @@
                                CubitBoolean keep_old = CUBIT_FALSE,
                                CubitBoolean make_tolerant = CUBIT_FALSE,
                                FILE* logfile_ptr = NULL );
-      // Heals the input bodies, using either autoheal or incremental,
-      // depending on the switches that are setup.  Writes to the logfile
-      // if it's been opened.
 
+      //! Uses the healing husk to find bad geometry and give feedback to 
+      //! the user.  A lot more could be done here - this is just a quick 
+      //! overview for the user (the user will have no idea why the identified 
+      //! geometry is bad).  A logfile can give a little more information.
       CubitStatus analyze_badgeom( DLIList<Body*> &body_list, 
                                    DLIList<TopologyEntity*> &bad_geometry,
                                    FILE* logfile = NULL );
-      // Uses the healing husk to find bad geometry and give feedback to 
-      // the user.  A lot more could be done here - this is just a quick 
-      // overview for the user (the user will have no idea why the identified 
-      // geometry is bad).  A logfile can give a little more information.
 
+      //! Shows the bad geometry.  The geometry must have been analyzed first.
+      //! If body_list is empty, shows only for those bodies that have been
+      //! analyzed.
       CubitStatus get_badgeom( DLIList<Body*> &body_list, 
                                DLIList<TopologyEntity*> &bad_geometry );
-      // Shows the bad geometry.  The geometry must have been analyzed first.
-      // If body_list is empty, shows only for those bodies that have been
-      // analyzed.
 
+      //! Get tolerant curves.  If the body list is empty, all tolerant 
+      //! curves are retrieved.
       CubitStatus get_tcurves( DLIList<Body*> &body_list,
                                DLIList<RefEdge*> &t_curves );
-      // Get tolerant curves.  If the body list is empty, all tolerant 
-      // curves are retrieved.
 
+      //! Uses the healing husk to perform one or more healing operations.
+      //! Which operations are performed is determined by switches in the
+      //! healer.  The user can set default tolerances (separate from this 
+      //! function, override the defaults with this function, or just use the 
+      //! tolerances calculated by the healer (preferred).
+      //!
+      //! The possible healing steps are:
+      //!    1) preprocess - removes zero-length edges, sliver faces, duplicate 
+      //!                    vertices. This is the first step which is always 
+      //!                    done (user shouldn't suppress this).  Tolerance is resabs.
+      //!    2) simplify - simplify NURBS into analytic.   
+      //!                     Default simplify_tol = .0001
+      //!    3) stitch - stitch geometry together.  Iterative from min to max 
+      //!                tolerance.
+      //!                   Default min tol = 10e-5
+      //!                   Default max tol = 1
+      //!    4) geombuild - geometry-related healing.  
+      //!                      Default geombuild_tol = .01
+      //!                      Default analytic_tangency_tol = .01
+      //!                      Default isolspline_solver_tol = .01      
+      //!          Individual geombuild steps can be (instead of doing all):
+      //!             analytic - performs all of the stages of the analytic solver 
+      //!                        subphase of the geometry building phase. The analytic 
+      //!                        solver subphase attempts to heal all edges and 
+      //!                        vertices shared by analytic surfaces. 
+      //!             isospline - performs all of the stages of the isospline solver
+      //!                         subphase of the geometry building phase. The 
+      //!                         isospline solver attempts to heal all edges shared 
+      //!                         by tangential isoparametric surfaces (e.g., the 
+      //!                         intersection curve is an isoparametric curve of 
+      //!                         both splines in the intersection). 
+      //!             reblend - future option
+      //!             sharpedge - performs all of the stages of the sharp edge solver 
+      //!                         subphase of the geometry building phase. The sharp 
+      //!                         edge solver attempts to heal all edges and vertices 
+      //!                         that are shared by surfaces that intersect sharply. 
+      //!                         This includes nontangential surface junctions. 
+      //!             genericspline - performs all of the stages of the generic spline 
+      //!                             solver subphase of the geometry building phase. 
+      //!                             The generic spline solver attempts to heal 
+      //!                             generic tangential spline junctions, (e.g., the 
+      //!                             intersection curve is not an isoparametric curve 
+      //!                             of both splines in the intersection). 
+      //!             wrapup - handles remaining pcurves, wraps up
+      //!                      geometry buiilding phase (user shouldn't suppress)
+      //!    5) postprocess - correction of neg-area faces, duplicate vertices, edge groups;
+      //!                     last step - always done (user shouldn't suppress)
+      //! \brief Uses the healing husk to perform one or more healing operations.
       CubitStatus heal_incremental( DLIList<Body*> &body_list, 
                                     DLIList<Body*> &new_bodies,
                                     DLIList<TopologyEntity*> &bad_geometry,
@@ -131,60 +188,20 @@
                                     CubitBoolean keep_old = CUBIT_FALSE,
                                     CubitBoolean make_tolerant = CUBIT_FALSE,
                                     FILE* logfile_ptr = NULL);
-      // Uses the healing husk to perform one or more healing operations.
-      // Which operations are performed is determined by switches in the
-      // healer.  The user can set default tolerances (separate from this 
-      // function, override the defaults with this function, or just use the 
-      // tolerances calculated by the healer (preferred).
-      //
-      // The possible healing steps are:
-      //    1) preprocess - removes zero-length edges, sliver faces, duplicate 
-      //                    vertices. This is the first step which is always 
-      //                    done (user shouldn't suppress this).  Tolerance is resabs.
-      //    2) simplify - simplify NURBS into analytic.   
-      //                     Default simplify_tol = .0001
-      //    3) stitch - stitch geometry together.  Iterative from min to max 
-      //                tolerance.
-      //                   Default min tol = 10e-5
-      //                   Default max tol = 1
-      //    4) geombuild - geometry-related healing.  
-      //                      Default geombuild_tol = .01
-      //                      Default analytic_tangency_tol = .01
-      //                      Default isolspline_solver_tol = .01      
-      //          Individual geombuild steps can be (instead of doing all):
-      //             analytic - performs all of the stages of the analytic solver 
-      //                        subphase of the geometry building phase. The analytic 
-      //                        solver subphase attempts to heal all edges and 
-      //                        vertices shared by analytic surfaces. 
-      //             isospline - performs all of the stages of the isospline solver
-      //                         subphase of the geometry building phase. The 
-      //                         isospline solver attempts to heal all edges shared 
-      //                         by tangential isoparametric surfaces (e.g., the 
-      //                         intersection curve is an isoparametric curve of 
-      //                         both splines in the intersection). 
-      //             reblend - future option
-      //             sharpedge - performs all of the stages of the sharp edge solver 
-      //                         subphase of the geometry building phase. The sharp 
-      //                         edge solver attempts to heal all edges and vertices 
-      //                         that are shared by surfaces that intersect sharply. 
-      //                         This includes nontangential surface junctions. 
-      //             genericspline - performs all of the stages of the generic spline 
-      //                             solver subphase of the geometry building phase. 
-      //                             The generic spline solver attempts to heal 
-      //                             generic tangential spline junctions, (e.g., the 
-      //                             intersection curve is not an isoparametric curve 
-      //                             of both splines in the intersection). 
-      //             wrapup - handles remaining pcurves, wraps up
-      //                      geometry buiilding phase (user shouldn't suppress)
-      //    5) postprocess - correction of neg-area faces, duplicate vertices, edge groups;
-      //                     last step - always done (user shouldn't suppress)
 
+      //! Lists the current settings for incremental healing
       void list_incremental();
-      // Lists the current settings for incremental healing
 
+      //! Lists out the tolerances of each body, separately
       void list_tolerances( DLIList<Body*> &body_list );
-      // Lists out the tolerances of each body, separately
-
+      
+      //@{
+      //! Functions to set the default tolerances used.  The healer calculates
+      //! the default tolerance per body.  These functions allow the user to override
+      //! these defaults for all bodies healed.  In incremental healing, the user can 
+      //! override these defaults by sending-in tolerances.  For autoheal, these
+      //! defaults are used if they are set, otherwise the healer calculates
+      //! intelligent defaults.  
       double get_default_simplify_tol();
       void set_default_simplify_tol( double tol );
       double get_default_stitch_min_tol();
@@ -203,56 +220,69 @@
       void set_default_reblend_tol( double tol );
       void reset_default_tolerances();
       void list_default_tolerances();
-      // Functions to set the default tolerances used.  The healer calculates
-      // the default tolerance per body.  These functions allow the user to override
-      // these defaults for all bodies healed.  In incremental healing, the user can 
-      // override these defaults by sending-in tolerances.  For autoheal, these
-      // defaults are used if they are set, otherwise the healer calculates
-      // intelligent defaults.
+      //@}
 
+      //! Cleans healer attributes from the bodies.  These can be left if the 
+      //! CleanAtt setting was used when doing analysis or healing.
       void clean_attributes( DLIList<Body*>& body_list );
-      // Cleans healer attributes from the bodies.  These can be left if the 
-      // CleanAtt setting was used when doing analysis or healing.
 
+      //@{
+      //! Get/set flags which determine whether to clean attributes after
+      //! analysis and healing.
       CubitBoolean get_cleanatt_flg();
       void set_cleanatt_flg( CubitBoolean flg );
-      // Get/set flags which determine whether to clean attributes after
-      // analysis and healing.
+      //@}
 
+      //@{
+      //! Method determines how bad geometry is displayed
       int get_show_method(); // 0-none, 1-highlight, 2-draw
       void set_show_method( int method );
-      // Method determines how bad geometry is displayed
+      //@}
 
+      //@{
+      //! Flag to determine whether to list a summary when showing bad geometry
       CubitBoolean get_show_summary_flg();
       void set_show_summary_flg( CubitBoolean flg );
-      // Flag to determine whether to list a summary when showing bad geometry
+      //@}
 
+      //@{
+      //! Flag to determine whether to list details when showing bad geometry
       CubitBoolean get_show_details_flg();
       void set_show_details_flg( CubitBoolean flg );
-      // Flag to determine whether to list details when showing bad geometry
+      //@}
 
+      //@{
+      //! Flag to determine whether to show bad geometry after healing
       CubitBoolean get_show_on_heal_flg();
       void set_show_on_heal_flg( CubitBoolean flg );
-      // Flag to determine whether to show bad geometry after healing
+      //@}
 
+      //@{ 
+      //! Allow for checking of short curves after healing
       CubitBoolean get_check_vol_on_heal_flg();
       void set_check_vol_on_heal_flg( CubitBoolean flg );
       double get_vol_on_heal_limit();
       void set_vol_on_heal_limit( double limit );
-      // Allow for checking of short curves after healing
+      //@} 
 
+      //@{ 
+      //! Allow for checking of small surfaces after healing
       CubitBoolean get_check_surf_on_heal_flg();
       void set_check_surf_on_heal_flg( CubitBoolean flg );
       double get_surf_on_heal_limit();
       void set_surf_on_heal_limit( double limit );
-      // Allow for checking of small surfaces after healing
-
+      //@} 
+      
+      //@{ 
+      //! Allow for checking of short curves after healing
       CubitBoolean get_check_curve_on_heal_flg();
       void set_check_curve_on_heal_flg( CubitBoolean flg );
       double get_curve_on_heal_limit();
       void set_curve_on_heal_limit( double limit );
-      // Allow for checking of short curves after healing
-
+      //@} 
+      
+      //@{
+      //! Get/set for flags for what to show during analysis/show
       CubitBoolean get_show_bad_vertices_flg();
       void set_show_bad_vertices_flg( CubitBoolean flg );
       CubitBoolean get_show_bad_curves_flg();
@@ -269,11 +299,13 @@
       void set_show_bad_volumes_flg( CubitBoolean flg );
       CubitBoolean get_show_bad_bodies_flg();
       void set_show_bad_bodies_flg( CubitBoolean flg );
-      // Get/set for flags for what to show during analysis/show
+      //@}
 
+      //! Function to list to user what the current onshow flags are
       void list_onshow_flgs();
-      // Function to list to user what the current onshow flags are
-
+      
+      //@{
+      // Functions for controlling incremental healing
       CubitBoolean get_inc_preprocess_flg();
       void set_inc_preprocess_flg( CubitBoolean flg );
       CubitBoolean get_inc_simplify_flg();
@@ -296,8 +328,10 @@
       void set_inc_wrapup_flg( CubitBoolean flg );
       CubitBoolean get_inc_postprocess_flg();
       void set_inc_postprocess_flg( CubitBoolean flg );
-      // Functions for controlling incremental healing
+      //@}
 
+      //@{
+      //! Forces a spline surface to be an analytical of the type specified.
       CubitStatus force_simplify_to_plane( DLIList<RefFace*> &ref_face_list, DLIList<Body*>& new_body_list, 
                                            CubitBoolean keep = CUBIT_FALSE );
       CubitStatus force_simplify_to_cylinder( DLIList<RefFace*> &ref_face_list, DLIList<Body*>& new_body_list, 
@@ -308,7 +342,7 @@
                                             CubitBoolean keep = CUBIT_FALSE );
       CubitStatus force_simplify_to_torus( DLIList<RefFace*> &ref_face_list, DLIList<Body*>& new_body_list, 
                                            CubitBoolean keep = CUBIT_FALSE );
-      // Forces a spline surface to be an analytical of the type specified.
+      //@}
 
       // *** END HEALER FUNCTIONS *** //
 

Modified: cgm/branches/cubit/geom/GeometryModifyEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/GeometryModifyEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryModifyEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,4 +4,12 @@
 
 #include "GeometryModifyEngine.hpp"
 
-                            
+
+
+CubitStatus GeometryModifyEngine::split_free_curve( Curve *curve, 
+                                                    CubitVector &split_location,
+                                                    DLIList<Curve*> &new_curves )
+{
+  return CUBIT_FAILURE;
+}
+

Modified: cgm/branches/cubit/geom/GeometryModifyEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/GeometryModifyEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryModifyEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,5 +1,5 @@
 //-------------------------------------------------------------------------
-// Filename      : GeoemtricModifyEngine.hpp
+// Filename      : GeometryModifyEngine.hpp
 //
 // Purpose       : Define the interface for all solid model modify
 //                 engines.
@@ -24,7 +24,6 @@
 class CubitPlane;
 template <class X> class DLIList;
 
-
 class TopologyBridge;
 class Point;
 class Curve;
@@ -34,6 +33,7 @@
 class LoopSM;
 class GeometryEntity;
 class GeometryQueryEngine;
+class CubitBox;
 
 class CUBIT_GEOM_EXPORT GeometryModifyEngine
 {
@@ -43,6 +43,10 @@
   virtual ~GeometryModifyEngine() {}
     //- virtual destructor
 
+  virtual bool supports_interoperability() = 0;
+    //- Returns whether intermixing of real and virtual geometry operations
+    //- is supported for the current geometry kernel.
+
   virtual Point* make_Point( CubitVector const& position ) const = 0;
     //R Point*
     //R- Returned pointer to a Point object.
@@ -64,7 +68,10 @@
                              const CubitVector *third_point = NULL) const = 0;
     //- Create a curve exactly on the give ref_face.
     //- Make sure the points are on the underlying surface.
-  
+
+  virtual Curve* make_Curve( DLIList<CubitVector*>& point_list,
+                             DLIList<CubitVector*>& point_tangents) const = 0;
+
   virtual Curve* make_Curve( GeometryType curve_type,
                              Point const* point1_ptr,
                              Point const* point2_ptr,
@@ -133,6 +140,21 @@
     //- This function creates a new surface from an existing one.
     //- 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 = 0;
+    //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 extended 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,
@@ -298,6 +320,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 = 0;
       //- Imprints a list of Bodies with a list of RefEdges.  All
@@ -307,6 +330,7 @@
 
       virtual CubitStatus imprint( DLIList<Surface*> &ref_face_list,
                                    DLIList<Curve*> &ref_edge_list,
+                                   DLIList<TopologyBridge*> &temporary_bridges,
                                    DLIList<BodySM*>& new_body_list,
                                    bool keep_old_body ) const = 0;
       //- Imprints a list of Surfaces with a list of RefEdges.  This is
@@ -317,7 +341,10 @@
       virtual CubitStatus imprint( DLIList<Surface*> &surface_list,
                                    DLIList<DLIList<Curve*>*> &curve_lists_list,
                                    BodySM*& new_body,
-                                   bool keep_old_body ) const = 0;
+                                   bool keep_old_body,
+                                   bool expand = true,
+                                   DLIList<TopologyBridge*> *new_tbs = NULL,
+                                   DLIList<TopologyBridge*> *att_tbs = NULL ) const = 0;
       //- Imprints a list of Surfaces with list of Curves, sorted per
       //- Surface (ie., curve_lists_list is same length as surface_list).
       //- All input surfaces must be from the same body.
@@ -327,10 +354,22 @@
                                    DLIList<BodySM*>& new_body_list,
                                    bool keep_old_body,
                                    DLIList<TopologyBridge*> *new_tbs = NULL,
-                                   DLIList<TopologyBridge*> *att_tbs = NULL ) const = 0;
+                                   DLIList<TopologyBridge*> *att_tbs = NULL,
+                                   double *tol_in = NULL,
+                                   bool clean_up_slivers = true) const = 0;
       //- Imprints a list of bodies with a list of vectors.  Useful for
       //- splitting curves and creating hardpoints on surfaces.
 
+      virtual CubitStatus tolerant_imprint(DLIList<Surface*> &surfs_in,
+                             DLIList<BodySM*> &new_bodysm_list) const = 0;
+      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 = 0; 
+
       virtual CubitStatus tolerant_imprint( DLIList<BodySM*> &bodies_in,
                                             DLIList<BodySM*> &new_bodies,
                                    DLIList<TopologyBridge*> *new_tbs = NULL,
@@ -353,6 +392,12 @@
                                        bool keep_free_edges) const = 0;
       //- Imprints a list of Bodies with a list of RefEdges which are projected
       //- to a list of Surfaces
+      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 = 0;
 
       virtual CubitStatus project_edges( 
                              DLIList<Surface*> &ref_face_list,
@@ -360,6 +405,10 @@
                              DLIList<Curve*> &ref_edge_list_new,
                              bool print_error = true ) const = 0;
       //- Projects list RefEdges to a list of Surfaces
+      
+      virtual CubitStatus curve_surface_intersection( Surface *surface, 
+                                                      Curve* curve,
+                                                      DLIList<Curve*> &new_curves ) const = 0;
   
       virtual CubitStatus intersect(BodySM* tool_body_ptr,
                                     DLIList<BodySM*> &from_bodies,
@@ -419,9 +468,8 @@
     //- argument is assigned a NULL value and the function returns 
     //- CUBIT_FAILURE.
 
-
      virtual CubitStatus flip_normals( DLIList<Surface*>& face_list ) const = 0;
-            //R CubitStatus
+    //R CubitStatus
     //R-the result of the flip_normal operation: Success or Failure
     //I bodies
     //I-DLIList<Surface*>: a list of Face pointers that will be fliped
@@ -429,7 +477,8 @@
     //- for some reason, the flip operation did not go well, the output
     //- returns CUBIT_FAILURE.
 	  
-	  
+	  virtual void get_possible_invalid_tbs(DLIList<TopologyBridge*> &bridges_in,
+                             DLIList<TopologyBridge*> &bridges_out) = 0;
 	  virtual CubitStatus unite( DLIList<BodySM*> &bodies, 
                                DLIList<BodySM*> &newBodies,
 				                       bool keep_old = false) const = 0;
@@ -489,6 +538,17 @@
                                    double draft_angle = 0.0,
                                    int draft_type = 0,
                                    bool rigid = false ) const= 0;
+      virtual CubitStatus sweep_to_body(
+                                   DLIList<Curve*> curve_list,
+                                   BodySM *target_body,
+                                   CubitVector distance, 
+                                   DLIList<BodySM*> &new_bodies,
+                                   bool unite) const = 0;
+      virtual CubitStatus sweep_to_body(
+                                   Surface  *source_surface,
+                                   BodySM *target_body,
+                                   CubitVector distance, 
+                                   DLIList<BodySM*> &new_bodies) const = 0;
      
 
       virtual CubitStatus scale( BodySM *&body, const CubitVector& factors ) = 0;
@@ -498,8 +558,10 @@
                                   const CubitVector &v1,
                                   const CubitVector &v2,
                                   const CubitVector &v3,
+                                  DLIList<BodySM*>& neighbor_imprint_list,
                                   DLIList<BodySM*>& results_list,
-                                  bool imprint = false ) const = 0;
+                                  ImprintType imprint_type = NO_IMPRINT,
+                                  bool preview = false) const = 0;
       //R int
       //R- Number of bodies that were webcut ( >= 0 )
       //I webcut_body_list
@@ -518,8 +580,10 @@
 
       virtual CubitStatus webcut(DLIList<BodySM*>& webcut_body_list, 
                                  BodySM const* tool_body,
+                                 DLIList<BodySM*>& neighbor_imprint_list,
                                  DLIList<BodySM*>& results_list,
-                                 bool imprint = false ) const = 0 ;
+                                 ImprintType imprint_type = NO_IMPRINT,
+                                 bool preview = false) const = 0 ;
       //R int       
       //R- Number of bodies that were webcut ( >= 0 )
       //I webcut_body_list
@@ -535,23 +599,29 @@
       //- This function webcuts a list of bodies using another body
       //- as the webcutting tool. The newly created bodies are 
       //- merged and imprinted depeding on the respective flags.
+
       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 = 0;
+                                              ImprintType imprint_type = NO_IMPRINT,
+                                              bool preview = false) const = 0;
      
 	  	  
-	  //- R status
+	    //- R status
       //- R-results_list of bodies affected, or created from webcut.
       //- I- Bodies to be webcut, plane to define cuts, and imprint merge flags.
-      //- This is an experimental function, hooked to the GUI for making
+      //- This is an experimental function, hooked to the Cat GUI for making
       //- bodies one to one sweeps.
+
       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) = 0;
+                                            ImprintType imprint_type = NO_IMPRINT,
+                                            bool preview = false) = 0;
       //- webcuts a body using a sheet body.
       //- It splits the sheet into two single sided bodies.
       //- it then subtracts this with the webcut body.
@@ -559,14 +629,16 @@
       //- if the webcut body is a topological torus, this routine
       //- will fail...
   
-      virtual CubitStatus webcut_with_extended_surf(
+      virtual CubitStatus webcut_with_extended_sheet(
                                             DLIList<BodySM*> &webcut_body_list,
-                                            Surface *extend_from,
+                                            DLIList<Surface*> &surface_list,
+                                            DLIList<BodySM*>& neighbor_imprint_list,
                                             DLIList<BodySM*> &new_bodies,
                                             int &num_cut,
-                                            bool imprint = false ) = 0;
-      //- creates a surface by extending one from the given surface then
-      //- webcuts using the this sheet.(see webcut_with_sheet.
+                                            ImprintType imprint_type = NO_IMPRINT,
+                                            bool preview = false) = 0;
+      //- creates a sheet by extending the given surfaces then webcuts using
+      //- this sheet.(see webcut_with_sheet).
  
       virtual CubitStatus webcut_with_sweep_surfaces(
                             DLIList<BodySM*> &blank_bodies,
@@ -578,8 +650,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) = 0;
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean preview = false) = 0;
 
       virtual CubitStatus webcut_with_sweep_curves(
                             DLIList<BodySM*> &blank_bodies,
@@ -588,8 +662,10 @@
                             bool through_all, 
                             Surface *stop_surf, 
                             Curve *curve_to_sweep_along, 
+                            DLIList<BodySM*>& neighbor_imprint_list,
                             DLIList<BodySM*> &results_list,
-                            CubitBoolean imprint = false) = 0;
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean preview = false) = 0;
 
       virtual CubitStatus webcut_with_sweep_curves_rotated(
                             DLIList<BodySM*> &blank_bodies,
@@ -598,8 +674,10 @@
                             const CubitVector &sweep_axis,
                             double angle,
                             Surface *stop_surf, 
+                            DLIList<BodySM*>& neighbor_imprint_list,
                             DLIList<BodySM*> &results_list,
-                            CubitBoolean imprint = false) = 0;
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean preview = false) = 0;
 
       virtual CubitStatus webcut_with_sweep_surfaces_rotated(
                             DLIList<BodySM*> &blank_bodies,
@@ -609,16 +687,19 @@
                             double angle, 
                             Surface *stop_surf, 
                             bool up_to_next, 
+                            DLIList<BodySM*>& neighbor_imprint_list,
                             DLIList<BodySM*> &results_list,
-                            CubitBoolean imprint = false) = 0;
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean preview = false) = 0;
 
       virtual CubitStatus webcut_with_cylinder( 
-                                        DLIList<BodySM*> &webcut_body_list,                                        
-                                        double radius,
+                                        DLIList<BodySM*> &webcut_body_list,                                                                       double radius,
                                         const CubitVector &axis,
                                         const CubitVector &center,
+                                        DLIList<BodySM*>& neighbor_imprint_list,
                                         DLIList<BodySM*>& results_list,
-                                        bool imprint = false) = 0;
+                                        ImprintType imprint_type = NO_IMPRINT,
+                                        CubitBoolean preview = false) = 0;
       //- webcuts a body using a cylinder give the input parameters.
 
       virtual CubitStatus webcut_with_brick( 
@@ -626,8 +707,10 @@
                                      const CubitVector &center, 
                                      const CubitVector axes[3], 
                                      const CubitVector &extension,
+                                     DLIList<BodySM*>& neighbor_imprint_list,
                                      DLIList<BodySM*> &results_list,
-                                     bool imprint = false ) = 0;
+                                     ImprintType imprint_type = NO_IMPRINT,
+                                     CubitBoolean preview = false) = 0;
       /**<  Webcuts the bodies in the list with a cutting brick.
         *  The brick is created by the given parameters - center of
         *  brick, xyz axes, and extension.  Extension is 1/2 width,
@@ -642,8 +725,10 @@
                                             const CubitVector &center, 
                                             const CubitVector axes[2],
                                             double width, double height,
+                                            DLIList<BodySM*>& neighbor_imprint_list,
                                             DLIList<BodySM*> &results_list,
-                                            bool imprint = false ) = 0;
+                                            ImprintType imprint_type = NO_IMPRINT,
+                                            bool preview = false) = 0;
       /**<  Webcuts the bodies in the list with a cutting planar sheet.
         *  The sheet is created by the given parameters - center of
         *  sheet, xy axes, and width and height. Sheet creation is done 
@@ -653,8 +738,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) = 0;
+                                         ImprintType imprint_type = NO_IMPRINT,
+                                         bool preview = false) = 0;
       //- webcuts a body list using a temp sheet body created from the curve loop
 
 
@@ -673,6 +760,15 @@
                                       DLIList<BodySM*> &new_bodies ) = 0;
       //- Splits a body with multiple volumes into multiple bodies
       //- each having only one volume.
+
+      virtual CubitStatus split_free_curve( Curve *curve,
+                                        CubitVector &split_location,
+                                        DLIList<Curve*> &new_curves );
+
+      virtual CubitStatus separate_surfaces( DLIList<Surface*> &surf_list,
+                                             DLIList<BodySM*> &new_bodies ) = 0;
+      //- Separates surfaces from sheet bodies into separate bodies.  Connected
+      //- surfaces will remain connected but be placed in a new body.
   
       virtual CubitStatus reverse_body( BodySM *body_to_reverse ) = 0;
       //- Reverse body (turn it inside-out).
@@ -686,12 +782,11 @@
       //- Removes all unnecessary faces, edges and vertices from the body.   
       
 	    virtual CubitStatus regularize_entity( GeometryEntity *old_entity_ptr,  
-                                             BodySM *&new_body_ptr ) = 0;
+                                             BodySM *&new_body_ptr) = 0;
       //- Removes all all unnessesary faces, curves, vertices and associated
       //- data from a refentity.
+	    virtual CubitStatus test_regularize_entity( GeometryEntity *old_entity_ptr) = 0;
    
-
-      // Added by CAT
       virtual CubitStatus offset_curves( DLIList<Curve*>& ref_edge_list, 
                                          DLIList<Curve*>& result_curve_list,
                                          double offset_distance, 
@@ -702,7 +797,15 @@
       //- 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.
 
-      virtual Curve* trim_curve( Curve* trim_curve, 
+      virtual CubitStatus  split_curve( Curve* curve_to_split,
+										const CubitVector& split_location,
+										DLIList<Curve*>& created_curves ) = 0;
+	  //- 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
+	  
+	  
+	  virtual Curve* trim_curve( Curve* trim_curve, 
                                       const CubitVector& trim_vector, 
                                       const CubitVector& keep_vector,
                                       bool keep_old = false ) = 0;
@@ -711,11 +814,12 @@
       //- is not free, the curve is automatically copied before trimming (so
       //- a new curve results).
 
-      virtual CubitStatus create_body_from_surfs( 
+      virtual CubitStatus create_solid_bodies_from_surfs( 
                                       DLIList<Surface*> &ref_face_list, 
-                                      BodySM *&new_body,
+                                      DLIList<BodySM*> &new_bodies,
                                       bool keep_old = false,
-                                      bool heal = true) const = 0;
+                                      bool heal = true,
+                                      bool sheet = false ) const = 0;
       //- Creates a single body from a set of faces.  The faces can only be attached
       //- to bodies if they are sheet bodies.  It is assumed that the calling code will
       //- check for this, ie GeometryTool.
@@ -813,6 +917,20 @@
 					       BodySM *body_to_trim_to,
 					       BodySM *&midsurface_body ) const = 0;
 
+ 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 ) const = 0;
+
   virtual CubitStatus tweak_chamfer( DLIList<Curve*> &curve_list, 
                                      double left_offset,
                                      DLIList<BodySM*> &new_bodysm_list,
@@ -886,26 +1004,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 = 0;
   /**<  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 = 0;
   /**<  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 = 0;
   /**<  Remove surfaces from a body or bodies and then extend the adjoining
@@ -924,37 +1045,83 @@
   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 = 0;
   /**<  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 = 0;
+                                    CubitBoolean preview = CUBIT_FALSE,
+                                    double max_area_increase = 0 ) const = 0;
   /**<  Tweak specified edges of a surface or set of surfaces (in sheet
     *   bodies) up to a set of connected target surfaces.  This essentially
-    *   extends or trims the attached surfaces of the sheet body.
+    *   extends or 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. The max_area_increase is a percentage increase for
+    *   which the geometry will not be tweaked if the resulting surface area surpasses.
     */
 
   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 = 0;
+                                    CubitBoolean preview = CUBIT_FALSE,
+                                    double max_area_increase = 0) const = 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 surface created
-    *   by thickening the owning surface of the target curve.
+    *   by thickening the owning surface of the target curve.  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 = 0;
+  /**<  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 *bodies, double lengthlimit ) const = 0;
 
-
   virtual CubitStatus create_net_surface( DLIList<Surface*>& ref_face_list, BodySM *& new_body,
                                           DLIList<DLIList<CubitVector*>*> &vec_lists_u, 
                                           DLIList<DLIList<CubitVector*>*> &vec_lists_v, 
@@ -966,9 +1133,24 @@
 
   virtual CubitStatus create_offset_surface( Surface* ref_face_ptr, BodySM*& new_body, double offset_distance ) const = 0;
 
+  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 = 0;
+  /**< 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 = 0;
 
-  virtual CubitStatus create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body ) const = 0;
+  virtual CubitStatus create_skin_surface( DLIList<Curve*>& curves, BodySM*& new_body,
+                                           DLIList<Curve*>& guides) const = 0;
 
   virtual CubitStatus loft_surfaces( Surface *face1, const double &takeoff1,
                                      Surface *face2, const double &takeoff2,
@@ -980,22 +1162,32 @@
                                      CubitBoolean simplify_option = CUBIT_FALSE) const = 0;
 
   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 = 0;
+                                             Surface *face2, const double &takeoff2,
+					     BodySM*& new_body,
+				             CubitBoolean arc_length_option,
+					     CubitBoolean twist_option,
+				             CubitBoolean align_direction,
+					     CubitBoolean perpendicular,
+					     CubitBoolean simplify_option) const = 0;
     
   virtual CubitStatus create_surface( DLIList<CubitVector*>& vec_list,
                                       BodySM *&new_body, Surface *ref_face_ptr, 
 			                             CubitBoolean project_points ) const = 0;
 
+  virtual CubitStatus create_surface( DLIList<Point*> &points,
+                                      BodySM *&new_body ) const = 0;
+
   virtual CubitStatus create_weld_surface( CubitVector &root,
                                            Surface *ref_face1, double leg1, Surface *ref_face2, double leg2,
                                            BodySM *&new_body ) const = 0;
 
+  virtual CubitBoolean bodies_interfering( BodySM *body1,  BodySM *body2 ) const {return CUBIT_FALSE;}
+
+  virtual CubitStatus stitch( DLIList<BodySM*> &bodies_to_stitch,
+                      DLIList<BodySM*> &new_bodies,
+                      bool tighten_gaps,
+                      double tolerance )const = 0; 
+
   protected: 
   
   private:
@@ -1003,4 +1195,3 @@
 };
 
 #endif
-

Modified: cgm/branches/cubit/geom/GeometryModifyTool.cpp
===================================================================
--- cgm/branches/cubit/geom/GeometryModifyTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryModifyTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,4 +1,3 @@
-
 //-------------------------------------------------------------------------
 // Filename      : GeometryModifyTool.cpp
 //
@@ -12,11 +11,12 @@
 //
 //-------------------------------------------------------------------------
 
-
 #include <string.h>
 #include <assert.h>
 #include <stdlib.h>
 #include <math.h>
+#include <sstream>
+//#include <iostream>
 
 #include "GeometryModifyTool.hpp"
 #include "CubitDefines.h"
@@ -32,6 +32,7 @@
 #include "TopologyBridge.hpp"
 #include "ModelQueryEngine.hpp"
 #include "CADefines.hpp"
+#include "GeomMeasureTool.hpp"
 
 #include "RefEntity.hpp"
 #include "RefEntityFactory.hpp"
@@ -65,6 +66,7 @@
 #include "CubitVector.hpp"
 #include "CubitPlane.hpp"
 #include "CubitTransformMatrix.hpp"
+#include "GfxPreview.hpp"
 
 #include "DLIList.hpp"
 
@@ -82,22 +84,30 @@
 #include "BridgeManager.hpp"
 #include "SplitSurfaceTool.hpp"
 #include "OffsetSplitTool.hpp"
+#include "AutoMidsurfaceTool.hpp"
+#include "TDSurfaceOverlap.hpp"
+#include "GfxDebug.hpp"
 
+#include "CubitUndo.hpp"
 
-
-
 /* Work around stupid #define hz equal to HZ on IBM */
 #ifdef hz
 #  undef hz
 #endif
+#ifdef PROE
+#include "CompositeTool.hpp"
+#endif
 
 GeometryModifyTool* GeometryModifyTool::instance_ = 0;
 CubitBoolean GeometryModifyTool::allEdgesImprint = CUBIT_TRUE;
 CubitBoolean GeometryModifyTool::groupImprint = CUBIT_TRUE;
 CubitBoolean GeometryModifyTool::newIds = CUBIT_FALSE;
 CubitBoolean GeometryModifyTool::sepAfterWebcut = CUBIT_TRUE;
-CubitBoolean GeometryModifyTool::booleanRegularize= CUBIT_TRUE;
+CubitBoolean GeometryModifyTool::booleanRegularize = CUBIT_TRUE;
+CubitBoolean GeometryModifyTool::uniteMixedModels = CUBIT_TRUE;
 CubitBoolean GeometryModifyTool::oldNames = CUBIT_FALSE;
+CubitBoolean GeometryModifyTool::meshAutodelete = CUBIT_TRUE;
+CubitBoolean GeometryModifyTool::meshAutodeleteRemesh = CUBIT_FALSE;
 RefEntity* GeometryModifyTool::copyingEntity = NULL;
 
 //-------------------------------------------------------------------------
@@ -164,6 +174,24 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : Deletes instance variable
+//
+// Special Notes :
+//
+// Creator       : Corey Ernst
+//
+// Creation Date : 12/31/07
+//-------------------------------------------------------------------------
+void GeometryModifyTool::delete_instance()
+{
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : Creates a Body corresponding to a sphere with the
 //                 given radius
 //
@@ -173,7 +201,12 @@
 //
 // Creation Date : 09/18/96
 //-------------------------------------------------------------------------
-Body* GeometryModifyTool::sphere(double radius)
+Body* GeometryModifyTool::sphere(double radius,
+                                 int x_shift,
+                                 int y_shift,
+                                 int z_shift,
+                                 double inner_radius,
+                                 bool delete_side )
 {
    if (0 == gmeList.size())
    {
@@ -190,15 +223,98 @@
       return NULL ;
    }
 
-   BodySM* body_sm = gmeList.get()->sphere(radius);
-   if (!body_sm)
-   {
-      PRINT_ERROR("In GeometryModifyTool::sphere\n"
-                  "       Problems building a volume from the sphere.\n");
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
+  GeometryModifyEngine *gme = gmeList.get();
+
+  BodySM* body_sm = gme->sphere(radius);
+
+  if (x_shift != 0 || y_shift != 0 || z_shift != 0)
+  {
+    BodySM *brick = gme->brick( 2.0 * radius,
+                                2.0 * radius,
+                                2.0 * radius);
+
+    CubitVector delta( x_shift * radius,
+                       y_shift * radius,
+                       z_shift * radius );
+
+    gme->get_gqe()->translate( brick, delta );
+
+    DLIList<BodySM*> new_sms;
+    DLIList<BodySM*> from_bodies(1);
+    from_bodies.append( body_sm );
+    bool keep_old = true;
+    CubitStatus bool_status;
+    if( delete_side == false )
+       bool_status = gme->intersect( brick, from_bodies, new_sms, keep_old );
+    else
+    {
+      DLIList<BodySM*> tool_bodies(1);
+      tool_bodies.append( brick );
+      bool imprint = false;
+      bool_status = gme->subtract( tool_bodies, from_bodies, new_sms, imprint, keep_old );
+    }
+
+    //delete the old bodies
+    gme->get_gqe()->delete_solid_model_entities( body_sm );
+    gme->get_gqe()->delete_solid_model_entities( brick );
+
+    if( bool_status == CUBIT_FAILURE || new_sms.size() == 0 )
+    {
+      PRINT_ERROR("Problems creating sphere.\n" );
       return NULL ;
-   }
+    }
 
-   return GeometryQueryTool::instance()->make_Body(body_sm);
+    body_sm = new_sms.get();
+  }
+
+  Body *new_body = NULL;
+  BodySM* inner_body_sm = NULL;
+  if( inner_radius )
+  {
+    inner_body_sm = gme->sphere(inner_radius);
+    DLIList<BodySM*> new_sms;
+    DLIList<BodySM*> from_bodies(1);
+    DLIList<BodySM*> tool_bodies(1);
+    from_bodies.append( body_sm );
+    tool_bodies.append( inner_body_sm );
+    bool imprint = false;
+    bool keep_old = true;
+    CubitStatus subtract_status =
+       gme->subtract( tool_bodies, from_bodies, new_sms, imprint, keep_old );
+
+     //delete the old bodies
+    gme->get_gqe()->delete_solid_model_entities( body_sm );
+    gme->get_gqe()->delete_solid_model_entities( inner_body_sm );
+
+    if( subtract_status == CUBIT_FAILURE || new_sms.size() == 0 )
+    {
+      PRINT_ERROR("Problems creating sphere with inner radius.\n" );
+      return NULL ;
+    }
+
+    body_sm = new_sms.get();
+  }
+
+  if (!body_sm)
+  {
+     PRINT_ERROR("In GeometryModifyTool::sphere\n"
+                 "       Problems building a volume from the sphere.\n");
+  }
+  else
+    new_body = GeometryQueryTool::instance()->make_Body(body_sm);
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -229,16 +345,29 @@
       return NULL;
    }
 
-   BodySM* bodyPtr = gmeList.get()->brick(width, depth, height) ;
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
 
+   Body *new_body = NULL;
+   BodySM* bodyPtr = gmeList.get()->brick(width, depth, height);
+
    if (bodyPtr == NULL)
    {
       PRINT_ERROR("In GeometryModifyTool::brick\n"
                   "       Problem creating a brick.\n") ;
-      return NULL ;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
 
-   return GeometryQueryTool::instance()->make_Body(bodyPtr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+   return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -309,19 +438,30 @@
          return planar_sheet( center, sheet_axes, width, height );
       }
    }
-
    else
    {
+      if( CubitUndo::get_undo_enabled() )
+        CubitUndo::save_state();
+
       BodySM* bodyPtr = gmeList.get()->brick(center, axes, extension) ;
-
+      Body *new_body = NULL;
       if (bodyPtr == NULL)
       {
          PRINT_ERROR("In GeometryTool::brick\n"
             "       Problem creating a brick.\n") ;
-         return NULL;
       }
+      else
+        new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
 
-      return GeometryQueryTool::instance()->make_Body(bodyPtr);
+      if( CubitUndo::get_undo_enabled() )
+      {
+        if( new_body )
+          CubitUndo::note_result_body( new_body );
+        else
+          CubitUndo::remove_last_undo();
+      }
+
+      return new_body;
    }
 }
 
@@ -361,17 +501,29 @@
       return NULL;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
      // Create a Body that represents the prism
    BodySM* bodyPtr = gmeList.get()->prism(height,  sides, major, minor) ;
-
+   Body *new_body = NULL;
    if (bodyPtr == NULL)
    {
       PRINT_ERROR("In GeometryModifyTool::prism\n"
                   "       Problems building a volume from the prism.\n") ;
-      return NULL;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
 
-   return GeometryQueryTool::instance()->make_Body(bodyPtr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+   return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -409,16 +561,29 @@
       return NULL;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
      // Create a Body that represents the prism
    BodySM* bodyPtr = gmeList.get()->pyramid ( height, sides, major, minor, top);
+   Body *new_body = NULL;
    if (bodyPtr == NULL)
    {
       PRINT_ERROR("In GeometryModifyTool::pyramid\n"
                   "      Problems building a volume from the pyramid.\n");
-      return NULL;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
 
-   return GeometryQueryTool::instance()->make_Body(bodyPtr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+   return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -456,17 +621,30 @@
       return NULL;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
      // Create a Body that represents the prism
    BodySM* bodyPtr = gmeList.get()->cylinder( hi, r1, r2, r3);
+   Body *new_body = NULL;
 
    if (bodyPtr == NULL)
    {
       PRINT_ERROR("In GeometryModifyTool::cylinder\n"
                   "       Problems building a volume from the conical frustum.\n");
-      return NULL;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
 
-   return GeometryQueryTool::instance()->make_Body(bodyPtr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+   return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -498,17 +676,30 @@
       return NULL;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
      // Create a Body that represents the torus
    BodySM* bodyPtr = gmeList.get()->torus(r1, r2) ;
+   Body *new_body = NULL;
 
    if (bodyPtr == NULL)
    {
       PRINT_ERROR("In GeometryModifyTool::torus\n"
                   "       Problems building a volume from the torus.\n") ;
-      return NULL ;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(bodyPtr);
 
-   return GeometryQueryTool::instance()->make_Body(bodyPtr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+   return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -531,17 +722,29 @@
       return NULL;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
   // Create a Body that represents the sheet
   BodySM* body_ptr = gmeList.get()->planar_sheet(p1, p2, p3, p4) ;
-
+  Body *new_body = NULL;
   if( body_ptr == NULL )
   {
     PRINT_ERROR("In GeometryTool::planar_sheet\n"
       "       Problems building a volume from the sheet.\n") ;
-    return NULL;
   }
+  else
+    new_body = GeometryQueryTool::instance()->make_Body(body_ptr);
 
-  return GeometryQueryTool::instance()->make_Body(body_ptr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -573,17 +776,30 @@
    p2.next_point( axes[0], -width, p3 );
    p3.next_point( axes[1], -height, p4 );
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
    // Create a Body that represents the sheet
    BodySM* body_ptr = gmeList.get()->planar_sheet(p1, p2, p3, p4) ;
+   Body *new_body = NULL;
 
    if( body_ptr == NULL )
    {
       PRINT_ERROR("In GeometryTool::planar_sheet\n"
          "       Problems building a volume from the sheet.\n") ;
-      return NULL;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(body_ptr);
 
-   return GeometryQueryTool::instance()->make_Body(body_ptr);
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body )
+      CubitUndo::note_result_body( new_body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  return new_body;
 }
 
 //-------------------------------------------------------------------------
@@ -617,19 +833,88 @@
                                extension, p1, p2, p3, p4 ) == CUBIT_FAILURE )
       return NULL;
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
    // Create a Body that represents the sheet
    BodySM* body_ptr = gmeList.get()->planar_sheet(p1, p2, p3, p4) ;
+   Body *new_body = NULL;
 
    if( body_ptr == NULL )
    {
       PRINT_ERROR("In GeometryModifyTool::planar_sheet\n"
          "       Problems building a volume from the sheet.\n") ;
-      return NULL ;
    }
+   else
+     new_body = GeometryQueryTool::instance()->make_Body(body_ptr);
 
-   return GeometryQueryTool::instance()->make_Body(body_ptr);
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( new_body )
+       CubitUndo::note_result_body( new_body );
+     else
+       CubitUndo::remove_last_undo();
+   }
+
+   return new_body;
 }
 
+RefVertex* GeometryModifyTool::make_RefVertex( RefVertex *vertex ) const
+{
+  if ( vertex == NULL )
+  {
+    PRINT_ERROR("Vertex is NULL\n");
+    return NULL;
+  }
+
+  TopologyBridge* bridge = 0;
+  GeometryModifyEngine* engine = get_engine(vertex, &bridge);
+  if (engine == NULL)
+  {
+     PRINT_ERROR( "%s (vertex %d) does not have a modify engine.\n",
+                  vertex->entity_name().c_str(),
+                  vertex->id() );
+     return 0;
+  }
+  
+  CubitVector point = vertex->coordinates();
+
+  // Call the default GeometryModifyEngine to create a new Point
+  Point* point_ptr = engine->make_Point(point);
+  
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
+  // Use the Point to create a RefVertex
+  RefVertex* ref_vertex_ptr = RefEntityFactory::instance()->construct_RefVertex(point_ptr) ;
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( ref_vertex_ptr )
+      CubitUndo::note_result_entity( ref_vertex_ptr );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  //transfer the names
+  DLIList<CubitString*> names;
+  vertex->entity_names( names );
+
+  int i;
+  for( i=names.size(); i--; )
+  {
+    CubitString *tmp_name = names.get_and_step();
+    ref_vertex_ptr->entity_name( *tmp_name ); 
+  }
+
+  // Send a message to the model indicating the vertex was created
+  CubitObserver::notify_static_observers(ref_vertex_ptr, FREE_REF_ENTITY_GENERATED);
+
+  // Return the newly created RefVertex
+  return ref_vertex_ptr ;
+}
+
+
 //-------------------------------------------------------------------------
 // Purpose       : This function takes a type information and a location
 //                 to create a RefVertex. The underlying representation
@@ -665,9 +950,20 @@
       return (RefVertex *)NULL ;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state();
+
      // Use the Point to create a RefVertex
    RefVertex* ref_vertex_ptr = RefEntityFactory::instance()->construct_RefVertex(point_ptr) ;
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( ref_vertex_ptr )
+      CubitUndo::note_result_entity( ref_vertex_ptr );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
    ref_vertex_ptr->color(color);
 
      // Send a message to the model indicating the vertex was created
@@ -699,7 +995,8 @@
 //
 // Creation Date : 10/9/97
 //-------------------------------------------------------------------------
-RefEdge* GeometryModifyTool::make_RefEdge(RefEdge *ref_edge_ptr, bool copy_attribs ) const
+RefEdge* GeometryModifyTool::make_RefEdge(RefEdge *ref_edge_ptr,
+                                          bool copy_attribs ) const
 {
   if ( ref_edge_ptr == NULL )
   {
@@ -746,10 +1043,16 @@
     new_curve = CAST_TO( new_curve_bridge, Curve);
   }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
   // Complete the task of linking this new Curve into the rest of the
   // geometry datastructures and return the new RefEdge.
   RefEdge *new_ref_edge = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_entity( new_ref_edge );
+
   return new_ref_edge;
 }
 
@@ -907,7 +1210,220 @@
   CGMApp::instance()->restore_previous_attribute_states();
   return CUBIT_SUCCESS;
 }
+#ifdef PROE
+CubitStatus GeometryModifyTool::prepare_for_topology_update( BodySM* old_bodysm )
+{
+  DLIList<BodySM*> old_bodysms;
+  old_bodysms.append(old_bodysm);
 
+  do_attribute_setup();
+  push_vg_attributes_before_modify( old_bodysms );
+
+  return CUBIT_SUCCESS;
+}
+CubitStatus GeometryModifyTool::finish_topology_update( BodySM* new_bodysm,
+                                                        Body* old_body )
+{
+  DLIList<Body*> input_bodies,result_bodies;
+  DLIList<BodySM*> new_bodysms, old_bodysms;
+  input_bodies.append(old_body);
+  new_bodysms.append(new_bodysm);
+  old_bodysms.clean_out();
+
+  DLIList<int> merged_surface_ids;
+  DLIList<int> merged_curve_ids;
+
+
+  get_merged_curve_and_surface_ids( input_bodies, merged_surface_ids, merged_curve_ids );
+  ///*
+  //Store information about what surfaces were originally merged
+  //
+  //This fixes a problem caused by the lack of support
+  //for automatically remerging surfaces that contain any
+  //virtual geometry.
+  //This should be removed if this issue is ever fixed - AHH
+  std::map< int , DLIList<Surface*> > merged_map;
+  for(int i=0; i< merged_surface_ids.size(); i++ )
+    {
+    int refface_id = merged_surface_ids.get_and_step();
+    RefFace* old_merged_refface = RefEntityFactory::instance()->get_ref_face( refface_id );
+    if( old_merged_refface && old_merged_refface->bridge_manager()->number_of_bridges() > 1 )
+      {
+      DLIList<Surface*> merged_surfsms;
+      DLIList<TopologyBridge*> bridge_list;
+      old_merged_refface->bridge_manager()->get_bridge_list( bridge_list );
+      for(int j=0; j< bridge_list.size(); j++ )
+        {
+        Surface* merging_surf = CAST_TO(bridge_list.get_and_step(),Surface);
+        if( merging_surf )
+          merged_surfsms.append_unique( merging_surf );
+        }
+      merged_map[ refface_id ] = merged_surfsms;
+      }
+    }
+  //*/
+  /*
+  //check to see if any curves have been orphaned inside virtual geometry
+  DLIList<Point*> point_list;
+  new_bodysm->points( point_list );
+  CubitBoolean loop = CUBIT_TRUE;
+  while( loop )
+    {
+    for(i=0; i< point_list.size(); i++)
+      {
+      //loop all the points and see if any will be on only one live curve
+      Point* curr_point = point_list.get_and_step();
+      DLIList<Curve*> curves_on_point;
+      DLIList<Curve*> curves_to_keep;
+      curr_point->curves( curves_on_point );
+      for(int j=0; j< curves_on_point.size(); j++)
+        {
+        Curve* curr_curve = curves_on_point.get_and_step();
+        DLIList<CubitSimpleAttrib*> attrib_list;
+        CubitSimpleAttrib* attrib = CompositeEngine::find_attribute_by_name( curr_curve, "COMPOSITE_GEOM" );
+        if( attrib )
+          {
+          attrib_list.append(attrib);
+          }
+        else
+          curves_to_keep.append_unique( curr_curve );
+        //curr_curve->get_simple_attribute( "COMPOSITE_GEOM", attrib_list );
+        //if ( !attrib_list.size() )
+          //curves_to_keep.append_unique( curr_curve );
+        }
+      //if all but one curve on this point will be removed we need to remove the other one too
+      if( curves_to_keep.size() == 1 )
+        {
+        CubitString name("COMPOSITE_GEOM");
+        DLIList<CubitString*> string_list;
+        string_list.append( &name );
+        CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
+        curves_to_keep.get()->append_simple_attribute_virt( &geom_attrib );
+        curr_point->append_simple_attribute_virt( &geom_attrib );
+        loop = CUBIT_FALSE;
+        }
+      else if( curves_to_keep.size() == 0 )
+        {
+        DLIList<CubitSimpleAttrib*> attrib_list;
+        curr_point->get_simple_attribute( "COMPOSIT_GEOM", attrib_list );
+        if( !attrib_list.size() )
+          {
+          CubitString name("COMPOSITE_GEOM");
+          DLIList<CubitString*> string_list;
+          string_list.append( &name );
+          CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
+          curr_point->append_simple_attribute_virt( &geom_attrib );
+          loop = CUBIT_TRUE;
+          }
+        }
+      }
+    if( loop )
+      loop = CUBIT_FALSE;
+    else
+      loop = CUBIT_TRUE;
+    }
+  */
+  GeometryModifyEngine* gme = GeometryModifyTool::instance()->get_engine(old_body);
+
+  restore_vg_after_modify(new_bodysms, input_bodies, gme);
+
+
+  DLIList<RefVolume*> volume_list;
+
+  int i;
+  for(i=new_bodysms.size(); i--;)
+  {
+    BodySM *bsm = new_bodysms.get_and_step();
+    Body *body = dynamic_cast<Body*>(bsm->topology_entity());
+    if(body)
+    {
+      // Append to the total list of volumes.
+      body->ref_volumes(volume_list);
+    }
+  }
+  // get all child entities (only get entities below volumes)
+  DLIList<RefEntity*> child_list, ref_ent_list;
+  CAST_LIST_TO_PARENT(volume_list, ref_ent_list);
+  RefEntity::get_all_child_ref_entities( ref_ent_list, child_list );
+
+  // Only push the id attributes if we are doing persistent ids.
+  for(i=child_list.size(); i--;)
+  {
+  child_list.get_and_step()->auto_actuate_cubit_attrib(CUBIT_FALSE,CUBIT_TRUE);
+  }
+
+  remove_pushed_attributes(new_bodysms, input_bodies);
+
+  finish_sm_op( input_bodies, new_bodysms , result_bodies);
+
+  fixup_merged_entities( merged_surface_ids, merged_curve_ids);
+
+  //Look for RefEdges that are orphaned inside of virtual surfaces
+  CubitBoolean loop = CUBIT_TRUE;
+  DLIList<RefVertex*> vertex_list;
+  while(loop)
+    {
+    loop = CUBIT_FALSE;
+    vertex_list.clean_out();
+    for(i=0; i< volume_list.size(); i++)
+      {
+      RefVolume* curr_volume = volume_list.get_and_step();
+      curr_volume->ref_vertices( vertex_list );
+      }
+    for(i=0; i< vertex_list.size(); i++)
+      {
+      RefVertex* curr_vertex = vertex_list.get_and_step();
+      DLIList<RefEdge*> edges_on_vertex;
+      curr_vertex->ref_edges( edges_on_vertex );
+      edges_on_vertex.uniquify_unordered();
+      if( edges_on_vertex.size() == 1 )
+        {
+        RefEdge* edge_to_remove = edges_on_vertex.get();
+        CompositeTool::instance()->remove_edge(edge_to_remove);
+        loop = CUBIT_TRUE;
+        break;
+        }
+      }
+    }
+  ///*
+  //Force merge faces that were missed by finish_sm_op
+  //
+  //This fixes a problem caused by the lack of support
+  //for automatically remerging surfaces that contain any
+  //virtual geometry.
+  //This should be removed if this issue is ever fixed - AHH
+  for(i=0; i< merged_surface_ids.size(); i++)
+    {
+    int refface_id = merged_surface_ids.get_and_step();
+    DLIList<RefFace*> ref_faces_to_remerge;
+    if(merged_map.find( refface_id ) != merged_map.end())
+      {
+      DLIList<Surface*> merged_surfsms = merged_map[ refface_id ];
+      for(int k=0; k< merged_surfsms.size(); k++)
+        {
+        Surface* merging_surf = merged_surfsms.get_and_step();
+        RefFace* merging_refface = CAST_TO(merging_surf->topology_entity(),RefFace);
+        if(merging_refface)
+          ref_faces_to_remerge.append_unique(merging_refface);
+        }
+      }
+    if( ref_faces_to_remerge.size() == 2 )
+      {
+      RefFace* first_remerge_face = ref_faces_to_remerge.get_and_step();
+      RefFace* second_remerge_face = ref_faces_to_remerge.get_and_step();
+      int first_id = first_remerge_face->id();
+      int second_id = second_remerge_face->id();
+      MergeTool::instance()->force_merge( first_remerge_face , second_remerge_face );
+      PRINT_WARNING("Remerging Surfaces %i and %i\n",first_id,second_id);
+      }
+    }
+  //*/
+  //do_attribute_cleanup();
+
+  return CUBIT_SUCCESS;
+}
+
+#endif
 GeometryModifyEngine*
 GeometryModifyTool::make_RefEdge_common( RefVertex* start_vertex,
                                          RefVertex* end_vertex,
@@ -1012,7 +1528,9 @@
    ref_face_ptr->move_to_surface(vert_1);
    ref_face_ptr->move_to_surface(vert_2);
 
-   if (!ref_vertex_1->coordinates().within_tolerance(vert_1, GEOMETRY_RESABS))
+   GeometryQueryEngine *gqe = ref_face_ptr->get_geometry_query_engine();
+
+   if (!ref_vertex_1->coordinates().within_tolerance(vert_1, gqe->get_sme_resabs_tolerance()))
    {
       PRINT_ERROR("vertices must lie within tolerance to the given"
                   " surface.\n"
@@ -1023,7 +1541,7 @@
                   ref_face_ptr->id() );
       return (RefEdge*)NULL;
    }
-   else if (!ref_vertex_2->coordinates().within_tolerance(vert_2, GEOMETRY_RESABS))
+   else if (!ref_vertex_2->coordinates().within_tolerance(vert_2, gqe->get_sme_resabs_tolerance() ))
    {
       PRINT_ERROR("vertices must lie within tolerance to the given"
                   " surface.\n"
@@ -1072,6 +1590,9 @@
      // Make sure that we get back valid Points
    assert ( point_ptr1 != NULL && point_ptr2 != NULL );
 
+
+
+
      // Request the GME to create a Curve using the Points
    Curve *curve_ptr;
    curve_ptr = GMEPtr->make_Curve( point_ptr1,
@@ -1091,9 +1612,25 @@
       return (RefEdge *)NULL ;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     //if endpoints are free vertices, need to save them out
+     DLIList<RefVertex*> verts_to_save;
+     verts_to_save.append( ref_vertex_1 );
+     verts_to_save.append( ref_vertex_2 );
+     bool save_only_if_free = true;
+     CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
+   }
+
      // Complete the task of linking this new Curve into the rest of the
      // geometry datastructures and return the new RefEdge.
-   return GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+   RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( new_edge )
+       CubitUndo::note_result_entity( new_edge );
+   }
+   return new_edge;
 }
 
 //-------------------------------------------------------------------------
@@ -1127,8 +1664,6 @@
    Point* point_ptr2 = NULL;
    Surface* surface_ptr = NULL;
 
-
-
    // Look for a common GeometryModifyEngine
   GMEPtr = make_RefEdge_common( ref_vertex_1, ref_vertex_2,
                                 point_ptr1, point_ptr2,
@@ -1139,6 +1674,16 @@
      // Make sure that we get back valid Points
    assert ( point_ptr1 != NULL && point_ptr2 != NULL );
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     //if endpoints are free vertices, need to save them out
+     DLIList<RefVertex*> verts_to_save;
+     verts_to_save.append( ref_vertex_1 );
+     verts_to_save.append( ref_vertex_2 );
+     bool save_only_if_free = true;
+     CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
+   }
+
      // Request the GME to create a Curve using the Points
    Curve* curve_ptr = GMEPtr->make_Curve(ref_edge_type,
                                          point_ptr1,
@@ -1160,7 +1705,13 @@
 
      // Complete the task of linking this new Curve into the rest of the
      // geometry datastructures and return the new RefEdge.
-   return GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+   RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( new_edge )
+       CubitUndo::note_result_entity( new_edge );
+   }
+   return new_edge;
 }
 
 //-------------------------------------------------------------------------
@@ -1198,6 +1749,16 @@
      // Make sure that we get back valid Points
    assert ( point_ptr1 != NULL && point_ptr2 != NULL ) ;
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     //if endpoints are free vertices, need to save them out
+     DLIList<RefVertex*> verts_to_save;
+     verts_to_save.append( ref_vertex_1 );
+     verts_to_save.append( ref_vertex_2 );
+     bool save_only_if_free = true;
+     CubitUndo::save_state_with_cubit_file( verts_to_save, save_only_if_free );
+   }
+
      // Request the GME to create a Curve using the Points
    Curve* curve_ptr = GMEPtr->make_Curve(ref_edge_type,
                                          point_ptr1,
@@ -1218,8 +1779,15 @@
 
      // Complete the task of linking this new Curve into the rest of the
      // geometry datastructures and return the new RefEdge.
-   return GeometryQueryTool::instance()->make_free_RefEdge( curve_ptr );
+   RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge( curve_ptr );
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( new_edge )
+       CubitUndo::note_result_entity( new_edge );
+   }
+   return new_edge;
 }
+
 //-------------------------------------------------------------------------
 // Purpose       : This function creates a RefFace from an existing RefFace.
 //                 The new face is a sheet body, double sided face with no
@@ -1254,17 +1822,16 @@
       return (RefFace*)NULL;
    }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
   //this list will get all the TB's what we'll be copying
-#ifdef BOYD17
-  DLIList<TopologyBridge*> original_bridges;
-#endif
   TopologyBridge *top_bridge = old_surface_ptr;
   if( !extended_from )
   {
     prepare_for_copy( from_ref_face, top_bridge );
   }
 
-
   Surface *tmp_surface = CAST_TO( top_bridge, Surface );
   Surface* new_surface_ptr = engine->make_Surface( tmp_surface,
                                                     extended_from );
@@ -1274,6 +1841,10 @@
     PRINT_ERROR("Surface copy failed.\n");
     if( !extended_from )
       clean_up_from_copy_failure( old_surface_ptr );
+
+   if( CubitUndo::get_undo_enabled() )
+        CubitUndo::remove_last_undo();
+
     return 0;
   }
 
@@ -1289,10 +1860,75 @@
   new_Body->ref_faces(ref_faces);
   assert(ref_faces.size() > 0);
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_Body )
+      CubitUndo::note_result_body( new_Body );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
   return ref_faces.get();
 }
 
 //-------------------------------------------------------------------------
+// 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 : 02/28/08
+//-------------------------------------------------------------------------
+Body*
+GeometryModifyTool::make_extended_sheet( DLIList<RefFace*> &ref_face_list,
+                                         CubitBox *clip_box_ptr,
+                                         bool preview ) const
+{
+  if( !ref_face_list.size() )
+    return 0;
+
+  // Check for virtual geometry
+  DLIList<RefEntity*> ref_ent_list;
+  CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
+  if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+  {
+    PRINT_ERROR("EXTENDING surfaces containing virtual geometry is not\n"
+      "       allowed. Delete virtual geometry on these surfaces\n"
+      "       before operation.\n" );
+    return 0;
+  }
+
+  // Look for a common GeometryModifyEngine for all of the RefFaces
+  int count = ref_face_list.size();
+  DLIList<TopologyBridge*> bridge_list(count);
+  DLIList<TopologyEntity*> entity_list(count);
+  CAST_LIST_TO_PARENT( ref_face_list, entity_list );
+
+  GeometryModifyEngine* GME_ptr =
+    common_modify_engine( entity_list, bridge_list );
+  if(! GME_ptr )
+  {
+     PRINT_ERROR("Cannot construct an extended sheet using surfaces that\n"
+                 "       do not share a common geometry engine.\n");
+     return 0;
+  }
+
+  DLIList<Surface*> surface_list(count);
+  CAST_LIST( bridge_list, surface_list, Surface );
+
+  BodySM *bodySM_ptr = GME_ptr->make_extended_sheet( surface_list, 
+    clip_box_ptr, preview );
+
+  if( bodySM_ptr )
+    return GeometryQueryTool::instance()->make_Body(bodySM_ptr);
+  else
+    return 0;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : This function takes a type information and a list of
 //                 RefEdges to create a Body with just one RefFace. The
 //                 underlying representation of the RefFace is determined
@@ -1311,6 +1947,7 @@
 
 RefFace* GeometryModifyTool::make_RefFace(GeometryType ref_face_type,
                                     DLIList<RefEdge*>& ref_edge_list,
+                                    bool is_free_face,
                                     RefFace *ref_face_ptr,
                                     bool check_edges ) const
 {
@@ -1328,7 +1965,7 @@
   if(! GME_ptr )
   {
      PRINT_ERROR("Cannot construct a Surface using entities that do "
-                 "not share a common GeometryModifyEngine.\n");
+                 "not share a common geometry engine.\n");
      return 0;
   }
 
@@ -1336,6 +1973,44 @@
    if (ref_face_ptr)
     old_surface_ptr = dynamic_cast<Surface*>(bridge_list.pop());
 
+   //Collect all the names on vertices to propagate after you create
+   //the surface
+   DLIList<CubitVector> vertex_coordinates;
+   DLIList<CubitString*> vertex_names;
+   DLIList<RefEdge*> free_ref_edges;
+   int kk;
+   for( kk=ref_edge_list.size(); kk--; )
+   {
+     DLIList<CubitString*> tmp_names;
+     RefEdge *tmp_edge = ref_edge_list.get_and_step();
+
+     if( tmp_edge->num_parent_ref_entities() == 0 )
+       free_ref_edges.append( tmp_edge );
+
+     RefVertex *s_vertex = tmp_edge->start_vertex();
+     RefVertex *e_vertex = tmp_edge->end_vertex();
+     int jj;
+
+     s_vertex->entity_names( tmp_names );
+     for( jj=tmp_names.size(); jj--; )
+     {
+       CubitVector tmp_vec = tmp_edge->start_vertex()->coordinates();
+       CubitString *name = tmp_names.get_and_step();
+       vertex_coordinates.append( tmp_vec );
+       vertex_names.append( new CubitString(*name) );
+     }
+
+     tmp_names.clean_out();
+     e_vertex->entity_names( tmp_names );
+     for( jj=tmp_names.size(); jj--; )
+     {
+       CubitVector tmp_vec = tmp_edge->end_vertex()->coordinates();
+       CubitString *name = tmp_names.get_and_step();
+       vertex_coordinates.append( tmp_vec );
+       vertex_names.append( new CubitString(*name) );
+     }
+   }
+
    DLIList<Curve*> curve_list(ref_edge_list.size());
    CAST_LIST( bridge_list, curve_list, Curve );
 
@@ -1349,74 +2024,46 @@
    }
 
    GeometryQueryTool* const gqt = GeometryQueryTool::instance();
-   RefFace* result_face = gqt->make_free_RefFace(surface_ptr);
+
+   RefFace* result_face = gqt->make_free_RefFace(surface_ptr, is_free_face);
    gqt->cleanout_deactivated_geometry();
-   return result_face;
-}
 
-//-------------------------------------------------------------------------
-// Purpose       : This function takes a type information and a list of
-//                 RefFaces to create a RefVolume. The underlying
-//                 representation of the RefVolume is determined by the
-//                 GeometryModifyEngine of the RefFaces. All the
-//                 RefFaces in the list must be associated with the same
-//                 GeometryModifyEngine. The return value can be a
-//                 NULL pointer, if the RefVolume cannot be succesfully
-//                 made for some reason.
-//
-// Special Notes :
-//
-// Creator       : Raikanta Sahu
-//
-// Creation Date : 03/29/97
-//-------------------------------------------------------------------------
-/*
-RefVolume*
-GeometryModifyTool::make_RefVolume( DLIList<RefFace*>& ref_face_list) const
-{
-  GeometryModifyEngine* GME_ptr = 0;
-
-  DLIList<TopologyEntity*> entity_list(ref_face_list.size());
-  DLIList<TopologyBridge*> bridge_list(ref_face_list.size());
-
-    //Look for a common GeometryModifyEngine
- CAST_LIST_TO_PARENT( ref_face_list, entity_list );
- GME_ptr = common_modify_engine( entity_list, bridge_list );
-
-  if( !GME_ptr )
+   //send out events for free curves saying that their 'free' status has
+   //be changed
+  
+  for( kk=0; kk<free_ref_edges.size(); kk++ )
   {
-    PRINT_ERROR("The surfaces are not owned by the same geometry "
-      "engine.  Cannot create a volume from them.\n");
-    return 0;
+    RefEdge *free_edge = free_ref_edges.get_and_step();
+    CubitObserver::notify_static_observers( free_edge, TOP_LEVEL_ENTITY_DESTRUCTED );
+    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, free_edge );
+    GeometryQueryTool::instance()->history().add_event(evt);
   }
 
-    //Get the list of surfaces.
-  DLIList<Surface*> surface_list(ref_face_list.size());
-  CAST_LIST( bridge_list, surface_list, Surface );
-  surface_list.remove_all_with_value(0);
-  assert(surface_list.size() == ref_face_list.size());
 
-     // Use the Surfaces to create a Lump
-   Lump* lump_ptr = GME_ptr->make_Lump(surface_list) ;
+   //look for a vertex at the same location of the original
+   //vertex(s).  Add the name to this new vertex.
+   DLIList<RefVertex*> tmp_verts;
+   result_face->ref_vertices( tmp_verts);
+   for( kk=vertex_coordinates.size(); kk--; )
+   {
+     CubitVector tmp_coord = vertex_coordinates.get_and_step();
+     CubitString *tmp_name = vertex_names.get_and_step();
 
-     // If we get a NULL pointer, give a warning message and return
-     // a NULL pointer.
-   if (lump_ptr == NULL)
-   {
-      PRINT_WARNING("In GeometryModifyTool::make_RefVolume\n"
-                    "         Got a NULL pointer to a Lump.\n"
-                    "         Cannot make a RefVolume.\n") ;
-      return (RefVolume *)NULL;
+     int jj;
+     for( jj=tmp_verts.size(); jj--; )
+     {
+       RefVertex *tmp_vert = tmp_verts.get_and_step();
+       if( tmp_coord.distance_between( tmp_vert->coordinates() ) < GEOMETRY_RESABS )
+       {
+         //add the name if it doesn't already exist
+         RefEntityName::instance()->add_refentity_name( tmp_vert, *tmp_name );
+       }
+     }
    }
 
-     // Use the Lump to make a RefVolume
-    RefVolume* ref_volume_ptr =
-      GeometryQueryTool::instance()->make_RefVolume(lump_ptr);
+   return result_face;
+}
 
-     // Return the new RefVolume
-   return ref_volume_ptr ;
-}
-*/
 //-------------------------------------------------------------------------
 // Purpose       : This function takes a list of RefVolumes to create a
 //                 Body. The underlying representation of the Body is
@@ -1482,9 +2129,11 @@
 Body* GeometryModifyTool::make_Body(RefFace *from_ref_face,
                               CubitBoolean extended_from) const
 {
+   bool is_free_face = false;
+
      // Given the arguments, make a RefFace.
    RefFace* new_ref_face = this->make_RefFace(from_ref_face,
-                                              extended_from);
+                                              extended_from );
    if (!new_ref_face)
    {
       return (Body *)NULL;
@@ -1525,10 +2174,16 @@
                               DLIList<RefEdge*>& ref_edge_list,
                               RefFace *ref_face_ptr) const
 {
+   if( CubitUndo::get_undo_enabled() )
+     CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  
+   bool is_free_face = false;
+
      // Given the arguments, make a RefFace.
    RefFace* new_ref_face = this->make_RefFace(ref_face_type,
                                               ref_edge_list,
-                                              ref_face_ptr) ;
+                                              is_free_face,
+                                              ref_face_ptr);
 
    if( new_ref_face == NULL )
       return NULL;
@@ -1548,6 +2203,14 @@
      bodies.append( body );
    }
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( bodies.size() )
+       CubitUndo::note_result_entity( bodies.get() ); 
+     else
+      CubitUndo::remove_last_undo();
+   }
+
      // Return the body containing the new RefFace.
    return bodies.get();
 }
@@ -1627,29 +2290,48 @@
 {
   CubitStatus ret = CUBIT_SUCCESS;
 
-  if(strcmp(op, "WEBCUT") &&
-     strcmp(op, "CHOP") &&
-     strcmp(op, "IMPRINT") &&
-     strcmp(op, "SPLIT"))
+  Body *b = webcut_body_list.get();
+  if(b)
   {
-    if ( contains_intermediate_geom(webcut_body_list) )
+    GeometryModifyEngine *gme = get_engine(b);
+    if(gme)
     {
-      PRINT_ERROR("Performing %s on volumes containing geometry from\n"
-                  "different modeling engines is not allowed.\n"
-                  "Delete uncommon geometry on these volumes before operation.\n\n",
-                  op);
-      ret = CUBIT_FAILURE;
+      if(!gme->supports_interoperability() &&
+          contains_intermediate_geom(webcut_body_list))
+      {
+        PRINT_ERROR("Intermixing real and virtual geometry operations using the current solid modeling kernel is not allowed.\n");
+        ret = CUBIT_FAILURE;
+      }
     }
   }
-  else
+
+  if(ret == CUBIT_SUCCESS)
   {
-    if(contains_partitions(webcut_body_list))
+    // If the operation is not one of the ones below...
+    if(strcmp(op, "WEBCUT") &&
+      strcmp(op, "CHOP") &&
+      strcmp(op, "UNITE") &&
+      strcmp(op, "TWEAK") &&
+      strcmp(op, "IMPRINT") &&
+      strcmp(op, "REGULARIZE") &&
+      strcmp(op, "SPLIT_SURFACE") &&
+      strcmp(op, "REMOVE_TOPOLOGY") &&
+      strcmp(op, "SPLIT"))
     {
-      PRINT_ERROR("Performing %s on volumes containing virtual partitions.\n"
-                  "This is currently not supported.\n\n",
-                  op);
-      ret = CUBIT_FAILURE;
+      if (contains_intermediate_geom(webcut_body_list))
+      {
+        PRINT_ERROR("Performing %s on volumes containing virtual geometry is not allowed.\n", op);
+        ret = CUBIT_FAILURE;
+      }
     }
+    else
+    {
+      if(contains_partitions(webcut_body_list))
+      {
+        PRINT_ERROR("Performing %s on volumes containing virtual partitions is not allowed.\n", op);
+        ret = CUBIT_FAILURE;
+      }
+    }
   }
 
   return ret;
@@ -1670,6 +2352,8 @@
                                                CubitBoolean merge,
                                                CubitStatus status,
                                                DLIList<Body*>& result_list,
+                                               DLIList<int> *merged_surface_ids,
+                                               DLIList<int> *merged_curve_ids,
                                                CubitBoolean print_info) const
 {
    if (!finish_sm_op(webcut_body_list, result_body_sms, result_list,(bool)print_info))
@@ -1682,10 +2366,12 @@
      result_list = temp_result_list;
    }
 
+   if( merged_surface_ids && merged_curve_ids )
+     fixup_merged_entities( *merged_surface_ids, *merged_curve_ids );
+
    if (merge && status)
    {
      DLIList<Body*> temp_results(result_list);
-     temp_results += webcut_body_list;
      status = MergeTool::instance()->merge_bodies( temp_results );
    }
 
@@ -1713,6 +2399,13 @@
   DLIList<int> updated_ids, created_ids, destroyed_ids;
   DLIList<int> updated_vol_ids, created_vol_ids, destroyed_vol_ids;
 
+  // traverse the body object and remove any meshes from modified objects
+  int b;
+  for (b = 0; b < input_bodies.size(); b++) {
+	  Body* body = input_bodies.get_and_step();
+	  body_premodify(body);
+  }
+
     // Remove dead bodies
   input_bodies.reset();
   for (i = input_bodies.size(); i--;)
@@ -1816,14 +2509,45 @@
                                        const CubitVector &axis,
                                        const CubitVector &center,
                                        DLIList<Body*>& results_list,
-                                       CubitBoolean imprint,
-                                       CubitBoolean merge)
+                                       DLIList<Body*> &neighboring_bodies,
+                                       ImprintType imprint_type,
+                                       CubitBoolean merge,
+                                       CubitBoolean preview)
 {
   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
     return CUBIT_FAILURE;
 
   CubitStatus rval = CUBIT_SUCCESS;
 
+  if (preview)
+  {
+    // find the bounding box for the cylinder
+    CubitBox bounding_box;
+    Body* body_ptr = webcut_body_list.get_and_step();
+    bounding_box = body_ptr->bounding_box();
+
+    int i;
+    for( i=1; i<webcut_body_list.size(); i++ )
+    {
+       body_ptr = webcut_body_list.get_and_step();
+       bounding_box |= body_ptr->bounding_box();
+    }
+
+    int color = CUBIT_BLUE;
+    GfxPreview::clear();
+    GfxPreview::draw_cylinder(axis, center, bounding_box, (float) radius, color);
+    GfxPreview::flush();
+    return rval;
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<Body*> bodies_to_save;
+    bodies_to_save += webcut_body_list;
+    bodies_to_save += neighboring_bodies;
+    CubitUndo::save_state_with_cubit_file( bodies_to_save );
+  }
+
   const int count = webcut_body_list.size();
   DLIList<BodySM*> result_sm_list;
   DLIList<Body*> body_list(webcut_body_list);
@@ -1831,20 +2555,61 @@
   DLIList<Body*> engine_bodies(count);
   GeometryModifyEngine* gme = 0;
 
-  do_attribute_setup();
+  if(!preview)
+    do_attribute_setup();
 
   while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
   {
-    push_vg_attributes_before_modify(engine_body_sms);
+    //get all bodysms that we might modify in this operation
+    DLIList<BodySM*> neighbor_imprint_list;
+    DLIList<BodySM*> bodies_sm_to_modify;
+    DLIList<Body*> bodies_to_modify;
+    bodies_to_modify += engine_bodies;
+    int i;
+    for( i=neighboring_bodies.size(); i--; )
+    {
+      Body *tmp_body = neighboring_bodies.get_and_step();
+      BodySM *tmp_body_sm = tmp_body->get_body_sm_ptr();
+      if( gme == get_engine(tmp_body_sm ) )
+      {
+        neighbor_imprint_list.append( tmp_body_sm ); 
+        bodies_to_modify.append( tmp_body );
+      }
+    }
 
+    DLIList<int> merged_surface_ids;
+    DLIList<int> merged_curve_ids;
+
+    if(!preview)
+    {
+      bodies_sm_to_modify += neighbor_imprint_list;
+
+      push_vg_attributes_before_modify( bodies_sm_to_modify );
+      //get all the child entities that have been merged
+      get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+    }
+
+    // note that preview actually gets handled before this point
     CubitStatus status = gme->webcut_with_cylinder(engine_body_sms, radius, axis,
-              center, result_sm_list, imprint );
+              center, neighbor_imprint_list, result_sm_list, imprint_type, preview );
 
-    restore_vg_after_modify(result_sm_list, engine_bodies);
-
     if ( status != CUBIT_FAILURE )
-      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list );
+    {
+      if(!preview)
+      {
+        restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
+        remove_pushed_attributes(result_sm_list, bodies_to_modify);
+      }
+      status = finish_webcut( engine_bodies, result_sm_list, merge, status,
+                              results_list, &merged_surface_ids, &merged_curve_ids );
+    }
+    else
+    {
+      if(!preview)
+        remove_pushed_attributes(result_sm_list, engine_bodies);
+    }
 
+
     engine_bodies.clean_out();
     engine_body_sms.clean_out();
     result_sm_list.clean_out();
@@ -1856,8 +2621,17 @@
     }
   }
 
-  do_attribute_cleanup();
+  if(!preview)
+    do_attribute_cleanup();
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( rval == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( results_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
   return rval;
 }
 
@@ -1865,6 +2639,19 @@
 {
   //save attribute settings
   CGMApp::instance()->save_current_attribute_states();
+  
+  //Turn off all attributes
+  CubitAttribManager *attrib_manager = CGMApp::instance()->attrib_manager();
+  attrib_manager->set_all_auto_update_flags( CUBIT_FALSE ); 
+  attrib_manager->set_all_auto_actuate_flags( CUBIT_FALSE ); 
+  attrib_manager->set_all_auto_write_flags( CUBIT_FALSE ); 
+  attrib_manager->set_all_auto_read_flags( CUBIT_FALSE );  
+
+  CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ENTITY_NAME, CUBIT_TRUE);
+  CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_ENTITY_NAME, CUBIT_TRUE);
+  CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_ENTITY_NAME, CUBIT_TRUE);
+  CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_ENTITY_NAME, CUBIT_TRUE);
+
   // enable update, actuate, write, read for composite attributes
   CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_COMPOSITE_VG, CUBIT_TRUE);
   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_COMPOSITE_VG, CUBIT_TRUE);
@@ -1875,6 +2662,13 @@
   CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_PARTITION_VG, CUBIT_TRUE);
   CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_PARTITION_VG, CUBIT_TRUE);
   CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_PARTITION_VG, CUBIT_TRUE);
+  // enable update, actuate, write, read for entity ids
+  // We will use these ID atts to make sure the ref entities associated with unmodified
+  // virtual bridges will maintain the same ids after real operations.
+  CGMApp::instance()->attrib_manager()->set_auto_update_flag(CA_ENTITY_ID, CUBIT_TRUE);
+  CGMApp::instance()->attrib_manager()->set_auto_actuate_flag(CA_ENTITY_ID, CUBIT_TRUE);
+  CGMApp::instance()->attrib_manager()->set_auto_write_flag(CA_ENTITY_ID, CUBIT_TRUE);
+  CGMApp::instance()->attrib_manager()->set_auto_read_flag(CA_ENTITY_ID, CUBIT_TRUE);
 }
 
 void GeometryModifyTool::do_attribute_cleanup(void)
@@ -1886,6 +2680,31 @@
 // topology.
 void GeometryModifyTool::push_vg_attributes_before_modify(DLIList<BodySM*> &old_sms)
 {
+  // Get all of the ref entities involved and push CA_ENTITY_ID attributes
+  // on to them.  This will help us maintain ids on virtual that doesn't
+  // get modified by the real operation.
+  int i;
+  DLIList<RefVolume*> volume_list; 
+
+  for(i=old_sms.size(); i--;)
+  {
+    BodySM *bsm = old_sms.get_and_step();
+    Body *body = dynamic_cast<Body*>(bsm->topology_entity());
+    if(body)
+    {
+      // Append to the total list of volumes.
+      body->ref_volumes(volume_list);
+    }
+  }
+  // get all child entities (only get entities below volumes)
+  DLIList<RefEntity*> child_list, ref_ent_list;
+  CAST_LIST_TO_PARENT(volume_list, ref_ent_list);
+  RefEntity::get_all_child_ref_entities( ref_ent_list, child_list );  
+
+  // Only push the id attributes if we are doing persistent ids.
+  if(!get_new_ids())
+    CubitAttribUser::auto_update_cubit_attrib(child_list);
+
   DLIList<TopologyBridge*> top_bridges;
   CAST_LIST_TO_PARENT(old_sms, top_bridges);
   GeometryQueryTool::instance()->ige_export_geom(top_bridges);
@@ -1898,6 +2717,12 @@
   GeometryQueryTool::instance()->ige_push_imprint_attributes_before_modify(body_sms);
 }
 
+void GeometryModifyTool::push_named_attributes_to_curves_and_points(DLIList<TopologyBridge*> &tb_list,
+                                                             const char *name_in)
+{
+  GeometryQueryTool::instance()->ige_push_named_attributes_to_curves_and_points(tb_list, name_in);
+}
+
 // Cleanup imprint attributes that were pushed onto the underlying solid
 // model topology.
 void GeometryModifyTool::remove_imprint_attributes_after_modify(DLIList<BodySM*> &old_sms,
@@ -1912,8 +2737,9 @@
                                           RefFace *ref_face_top,
                                           RefFace *ref_face_bottom,
                                           DLIList<Body*> &results_list,
-                                          CubitBoolean imprint,
-                                          CubitBoolean merge )
+                                          ImprintType imprint_type,
+                                          CubitBoolean merge,
+                                          CubitBoolean preview)
 {
   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
     return CUBIT_FAILURE;
@@ -1940,18 +2766,26 @@
   DLIList<BodySM*> result_sm_list, webcut_sm_list(bridge_list.size());
   CAST_LIST(bridge_list, webcut_sm_list, BodySM);
 
-  do_attribute_setup();
-  push_vg_attributes_before_modify(webcut_sm_list);
+  if (!preview)
+  {
+    do_attribute_setup();
+    push_vg_attributes_before_modify(webcut_sm_list);
+  }
 
+  DLIList<BodySM*> neighbor_list;
   CubitStatus result_val = gme->webcut_across_translate (
-    webcut_sm_list, surface_top, surface_bottom, result_sm_list, imprint );
+    webcut_sm_list, surface_top, surface_bottom, result_sm_list, neighbor_list, imprint_type, preview );
 
-  restore_vg_after_modify(result_sm_list, original_body_list);
+  // if we're doing the real thing (not preview) finish the process
+  if (!preview)
+  {
+    restore_vg_after_modify(result_sm_list, original_body_list, gme);
+    remove_pushed_attributes(result_sm_list, original_body_list);
+    result_val = finish_webcut( webcut_body_list, result_sm_list, merge,
+                                result_val, results_list);
+    do_attribute_cleanup();
+  }
 
-  result_val = finish_webcut( webcut_body_list, result_sm_list, merge,
-                              result_val, results_list);
-  do_attribute_cleanup();
-
   return result_val;
 }
 #endif
@@ -1970,14 +2804,16 @@
                                          DLIList<Body*>& webcut_body_list,
                                          DLIList<RefEdge*>& refedge_list,
                                          DLIList<Body*>& results_list,
-                                         CubitBoolean imprint)
+                                         DLIList<Body*> &neighboring_bodies,
+                                         ImprintType imprint_type,
+                                         CubitBoolean merge,
+                                         CubitBoolean preview)
 
 {
   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
     return CUBIT_FAILURE;
 
    int i;
-   DLIList<Body*> original_body_list = webcut_body_list;
    const int count = webcut_body_list.size() + refedge_list.size();
    DLIList<TopologyEntity*> entity_list(count);
    DLIList<TopologyBridge*> bridge_list(count);
@@ -1995,25 +2831,76 @@
       return CUBIT_FAILURE;
    }
 
-   DLIList<BodySM*> webcut_sm_list(webcut_body_list.size()), result_sm_list;
+   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+   {
+     DLIList<Body*> bodies_to_save;
+     bodies_to_save += webcut_body_list;
+     bodies_to_save += neighboring_bodies;
+     CubitUndo::save_state_with_cubit_file( bodies_to_save );
+   }
+
+   DLIList<BodySM*> body_sm_list(webcut_body_list.size()), result_sm_list;
    DLIList<Curve*> curve_list(refedge_list.size());
-   CAST_LIST(bridge_list, webcut_sm_list, BodySM);
+   CAST_LIST(bridge_list, body_sm_list, BodySM);
    CAST_LIST(bridge_list, curve_list, Curve);
-   assert(webcut_sm_list.size() == webcut_body_list.size());
+   assert(body_sm_list.size() == webcut_body_list.size());
    assert(curve_list.size() == refedge_list.size());
 
-   do_attribute_setup();
-   push_vg_attributes_before_modify(webcut_sm_list);
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<Body*> bodies_to_modify;
 
+   if (!preview)
+   {
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
+
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
+  
+
    CubitStatus result_val = gme->webcut_with_curve_loop(
-                     webcut_sm_list, curve_list, result_sm_list, imprint) ;
+                     body_sm_list, curve_list,
+                     neighbor_imprint_list,
+                     result_sm_list,
+                     imprint_type, preview) ;
 
-   restore_vg_after_modify(result_sm_list, original_body_list);
+   // finish up if we're doing the real thing
+   if (!preview)
+   {
+     restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
+     remove_pushed_attributes(result_sm_list, bodies_to_modify);
 
-   result_val = finish_webcut( webcut_body_list, result_sm_list, CUBIT_FALSE,
-                               result_val, results_list );
-   do_attribute_cleanup();
+     result_val = finish_webcut( webcut_body_list, result_sm_list, merge,
+                                 result_val, results_list,
+                                 &merged_surface_ids, &merged_curve_ids );
+     do_attribute_cleanup();
+   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( result_val == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( results_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
    return result_val;
 }
 
@@ -2033,8 +2920,10 @@
                                       DLIList<Body*>& webcut_body_list,
                                       RefFace* refFace,
                                       DLIList<Body*>& results_list,
-                                      CubitBoolean imprint,
-                                      CubitBoolean merge)
+                                      DLIList<Body*> &neighboring_bodies,
+                                      ImprintType imprint_type,
+                                      CubitBoolean merge,
+                                      CubitBoolean preview)
 {
   //make sure that this refface is planar, or you'll get unexpected results
   if( refFace->geometry_type() != PLANE_SURFACE_TYPE )
@@ -2051,7 +2940,8 @@
    CubitVector vector2 = refFace->position_from_u_v(0, 0) ;
 
    CubitStatus result_val = this->webcut_with_plane(webcut_body_list, vector1,
-                                  vector2, vector3, results_list, imprint, merge) ;
+                                  vector2, vector3, results_list, neighboring_bodies,
+                                  imprint_type, merge, preview) ;
 
    return result_val;
 }
@@ -2072,16 +2962,17 @@
                                    DLIList<Body*>& webcut_body_list,
                                    Body* tool_body,
                                    DLIList<Body*>& results_list,
-                                   CubitBoolean imprint,
-                                   CubitBoolean merge)
+                                   DLIList<Body*> &neighboring_bodies,
+                                   ImprintType imprint_type,
+                                   CubitBoolean merge,
+                                   CubitBoolean preview)
 {
+
+  CubitStatus ret;
+
   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
     return CUBIT_FAILURE;
 
-  if( tool_body->is_sheet_body() )
-    return webcut_with_sheet( webcut_body_list, tool_body, results_list, imprint );
-
-  DLIList<Body*> original_body_list = webcut_body_list;
   DLIList<BodySM*> body_sm_list(webcut_body_list.size()), result_sm_list;
   BodySM* tool_sm = tool_body->get_body_sm_ptr();
   GeometryModifyEngine* gme = 0;
@@ -2093,7 +2984,8 @@
   }
 
   webcut_body_list.reset();
-  for (int i = webcut_body_list.size(); i--; )
+  int i;
+  for (i = webcut_body_list.size(); i--; )
   {
     Body* body_ptr = webcut_body_list.get_and_step();
     BodySM* sm_ptr = body_ptr->get_body_sm_ptr();
@@ -2109,20 +3001,70 @@
     body_sm_list.append(sm_ptr);
   }
 
-  do_attribute_setup();
+  DLIList<int> merged_surface_ids;
+  DLIList<int> merged_curve_ids;
+  DLIList<BodySM*> neighbor_imprint_list;
+  DLIList<Body*> bodies_to_modify;
 
-  push_vg_attributes_before_modify(body_sm_list);
+  if (!preview)
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    {
+      DLIList<Body*> bodies_to_save;
+      bodies_to_save += webcut_body_list;
+      bodies_to_save += neighboring_bodies;
+      CubitUndo::save_state_with_cubit_file( bodies_to_save );
+    }
 
-  int count = gme->webcut(body_sm_list, tool_sm, result_sm_list, imprint);
+    int i;
+    for( i=neighboring_bodies.size(); i--; )
+    {
+      Body *neighbor_body = neighboring_bodies.get_and_step();
+      BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+      GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+      
+      if( gme == neighbor_gme )
+        neighbor_imprint_list.append( tmp_body ); 
+    }
 
-  restore_vg_after_modify(result_sm_list, original_body_list);
+    do_attribute_setup();
+    DLIList<BodySM*> bodies_sm_to_modify;
+    bodies_sm_to_modify += body_sm_list;
+    bodies_sm_to_modify += neighbor_imprint_list;
+    push_vg_attributes_before_modify( bodies_sm_to_modify );
+    bodies_to_modify += webcut_body_list;
+    bodies_to_modify += neighboring_bodies;
+    get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+  }
 
-  CubitStatus ret = finish_webcut(webcut_body_list, result_sm_list, merge,
-                        count > 0 ? CUBIT_SUCCESS : CUBIT_FAILURE,
-                        results_list);
 
-  do_attribute_cleanup();
+  int count = gme->webcut(body_sm_list, tool_sm,
+                          neighbor_imprint_list,
+                          result_sm_list, imprint_type, preview);
 
+  // finish up if we're doing the real thing
+  if (!preview)
+  {
+    restore_vg_after_modify(result_sm_list, bodies_to_modify, gme);
+    remove_pushed_attributes(result_sm_list, bodies_to_modify );
+
+    ret = finish_webcut(webcut_body_list, result_sm_list, merge,
+                          count > 0 ? CUBIT_SUCCESS : CUBIT_FAILURE,
+                          results_list, &merged_surface_ids, &merged_curve_ids );
+
+    do_attribute_cleanup();
+  }
+  else
+    ret = count > 0 ? CUBIT_SUCCESS : CUBIT_FAILURE;
+
+  if( preview == CUBIT_FALSE && CubitUndo::get_undo_enabled() )
+  {
+    if( ret == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( results_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
   return ret;
 }
 
@@ -2145,22 +3087,48 @@
    DLIList<BodySM*> engine_body_sms(count);
    DLIList<Body*> engine_bodies(count);
    GeometryModifyEngine* gme = 0;
+
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old )
+       CubitUndo::save_state();
+     else
+       CubitUndo::save_state_with_cubit_file( section_body_list );
+   }
+
    while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
    {
+      //get all the child entities that have been merged
+      DLIList<int> merged_surface_ids;
+      DLIList<int> merged_curve_ids;
+      get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
+
       CubitStatus result = gme->section( engine_body_sms,
                                          point_1, point_2, point_3,
                                          result_sm_list,
                                          keep_normal_side, keep_old );
+
       if (!finish_sm_op( engine_bodies, result_sm_list, new_body_list ))
         result = CUBIT_FAILURE;
       if (!result)
         rval = CUBIT_FAILURE;
 
+      if( merged_surface_ids.size() || merged_curve_ids.size() )
+        fixup_merged_entities( merged_surface_ids, merged_curve_ids);
+
       engine_body_sms.clean_out();
       engine_bodies.clean_out();
       result_sm_list.clean_out();
    }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body_list.size() ) //if there are new bodies...something succeeded
+      CubitUndo::note_result_bodies( new_body_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
    return rval;
 }
 
@@ -2182,6 +3150,9 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
   DLIList<Curve*> curve_list(bridge_list.size()), result_list;
   CAST_LIST(bridge_list, curve_list, Curve);
   assert(curve_list.size() == ref_edge_list.size());
@@ -2190,9 +3161,22 @@
                         offset_distance, offset_direction, gap_type );
   assert( rval || !result_list.size() );
   result_list.reset();
+
+  DLIList<RefEntity*> created_edges;
   for (int i = result_list.size(); i--; )
-    GeometryQueryTool::instance()->make_free_RefEdge(result_list.get_and_step());
+  {
+    RefEdge *new_edge = GeometryQueryTool::instance()->make_free_RefEdge(result_list.get_and_step());
+    created_edges.append( new_edge );
+  }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( created_edges.size() )
+      CubitUndo::note_result_entities( created_edges );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
   return rval;
 }
 
@@ -2248,6 +3232,13 @@
    CubitVector my_vector = my_face->normal_at( my_center, ref_vol );
    CubitVector target_vector = target_face->normal_at( target_center );
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     DLIList<Body*> align_list(1);
+     align_list.append( body_ptr );
+     CubitUndo::save_state_with_cubit_file( align_list );
+   }
+
    axis = my_vector * target_vector;
      //Move the body so that the center of my_face
      //is at the origin.
@@ -2261,6 +3252,11 @@
 
         //Now we have the angle and the axis to rotate about...
       angle = 180.0*angle/CUBIT_PI;
+      
+      //if the angle is greater 180, we want the normals pointing
+      //into one another, not in the same direction
+      if( angle > 90 )
+        angle = angle - 180;
 
         //Now rotate the body about the axis.
       GeometryQueryTool::instance()->rotate( body_ptr, axis, angle );
@@ -2331,6 +3327,13 @@
          return CUBIT_FAILURE;
       }
 
+      if( CubitUndo::get_undo_enabled() )
+      {
+        DLIList<Body*> align_list(1);
+        align_list.append( body_ptr );
+        CubitUndo::save_state_with_cubit_file( align_list );
+      }
+
       //translate body so surface's centroid is at 0,0,0
       GeometryQueryTool::instance()->translate( body_ptr, -my_center_1 );
 
@@ -2355,6 +3358,13 @@
         GeometryQueryTool::instance()->rotate( body_ptr, second_vector, angle );
       }
 
+      if( CubitUndo::get_undo_enabled() )
+      {
+        DLIList<Body*> align_list(1);
+        align_list.append( body_ptr );
+        CubitUndo::save_state_with_cubit_file( align_list );
+      }
+
       //translate body back
       GeometryQueryTool::instance()->translate( body_ptr, my_center_1 );
 
@@ -2409,6 +3419,13 @@
      CubitVector target_vector = first_vector;
      axis_of_rot = my_vector * target_vector;
 
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> align_list(1);
+       align_list.append( body_ptr );
+       CubitUndo::save_state_with_cubit_file( align_list );
+     }
+
      //Move the body so that the center of the vertex
      //is at the origin.
      GeometryQueryTool::instance()->translate( body_ptr, -my_center_1 );
@@ -2465,7 +3482,10 @@
                          "to remain in the positive plane\n",body_ptr->id());
            if ( flip_result == CUBIT_FAILURE )
            {
-              return CUBIT_FAILURE;
+             if( CubitUndo::get_undo_enabled() )
+               CubitUndo::remove_last_undo();
+
+             return CUBIT_FAILURE;
            }
         }
      }
@@ -2605,6 +3625,7 @@
                                      const char* const,
                                      DLIList<Body*>& input_body_list,
                                      DLIList<BodySM*>& new_body_list,
+                                     DLIList<Body*>& output_body_list,
                                      CubitBoolean changed_new_ids )
 {
   int i;
@@ -2620,6 +3641,7 @@
     {
       regen_list.append_unique(bodysm);
       remove_dead_entity_names(body);
+      output_body_list.append( body );
     }
     else
     {
@@ -2633,6 +3655,7 @@
   {
     BodySM* bodysm = regen_list.get_and_step();
     Body* body = gqt->make_Body(bodysm);
+    output_body_list.append( body );
     PRINT_INFO("%s volume %d\n",
       new_body_list.is_in_list(bodysm) ? "Created swept" : "Updated",
       body->ref_volume()->id());
@@ -2668,22 +3691,46 @@
                    change_newids, geom_list))
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    DLIList<RefEdge*> edge_list;
+    DLIList<RefFace*> face_list;
+
+    CAST_LIST( ref_ent_list, edge_list, RefEdge );
+    CAST_LIST( ref_ent_list, face_list, RefFace );
+
+    //Edges aren't consumed, so there's nothing to save out
+    if( edge_list.size() )
+      CubitUndo::save_state();
+    else
+     //Faces will get consumed so you have to save out original entities
+      CubitUndo::save_state_with_cubit_file( face_list );
+  }
+
   DLIList<BodySM*> result_list;
-  CubitStatus status = gePtr1-> sweep_rotational( geom_list,
-                                                   result_list,
-                                                   point,
-                                                   sweep_axis,
-                                                   angle,
-                                                   steps,
-                                                   draft_angle,
-                                                   draft_type,
-                                                   switchside,
-                                                   make_solid,
-                                                   rigid);
-
-  if (!sweep_finish("rotational", body_list, result_list, change_newids))
+  CubitStatus status = gePtr1->sweep_rotational( geom_list,
+                                                 result_list,
+                                                 point,
+                                                 sweep_axis,
+                                                 angle,
+                                                 steps,
+                                                 draft_angle,
+                                                 draft_type,
+                                                 switchside,
+                                                 make_solid,
+                                                 rigid);
+  DLIList<Body*> output_body_list;
+  if (!sweep_finish("rotational", body_list, result_list, output_body_list, change_newids))
     status = CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    if( status == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+    else
+      CubitUndo::note_result_bodies( output_body_list );
+  }
+
   return status;
 }
 
@@ -2703,6 +3750,22 @@
                    change_newids, geom_list))
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    DLIList<RefEdge*> edge_list;
+    DLIList<RefFace*> face_list;
+
+    CAST_LIST( ref_ent_list, edge_list, RefEdge );
+    CAST_LIST( ref_ent_list, face_list, RefFace );
+
+    //Edges aren't consumed, so there's nothing to save out
+    if( edge_list.size() )
+      CubitUndo::save_state();
+    else
+     //Faces will get consumed so you have to save out original entities
+      CubitUndo::save_state_with_cubit_file( face_list );
+  }
+
   DLIList<BodySM*> result_list;
   CubitStatus status = gePtr1->
     sweep_translational( geom_list,
@@ -2713,14 +3776,25 @@
                          switchside,
                          rigid);
 
-  if (!sweep_finish("translational", body_list, result_list, change_newids))
+  DLIList<Body*> output_body_list;
+  if (!sweep_finish("translational", body_list, result_list, output_body_list, change_newids))
     status = CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    if( status == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+    else
+      CubitUndo::note_result_bodies( output_body_list );
+  }
+
   return status;
 }
 
-CubitStatus GeometryModifyTool::sweep_target(CubitPlane ref_plane,
-											 DLIList<RefEntity*>& ref_ent_list)
+//Author:: Jonathan Bugman
+//Sept 10, 2006
+CubitStatus GeometryModifyTool::sweep_curve_target(CubitPlane ref_plane,
+                                             DLIList<RefEntity*>& ref_ent_list)
 {
 	double distance1;
 	double distance2;
@@ -2733,7 +3807,7 @@
 	CubitVector end_point;
 	CubitVector target_end_point;
 	DLIList<RefEdge*> edge_list;
-	CAST_LIST(ref_ent_list, edge_list, RefEdge);	
+	CAST_LIST(ref_ent_list, edge_list, RefEdge);
 	CubitVector result;
 	double max_distance_for_edge=0;
 	CubitVector max_result;
@@ -2808,7 +3882,6 @@
 		{
 			Curve *facet_curve;
 			facet_curve=edge_list[ii]->get_curve_ptr();
-			int num_points;
 			int color = 2;
 			CubitStatus response;
 			GMem g_mem;
@@ -2816,7 +3889,8 @@
 			//get number of points and their locations
 			//on the curve as defined by the drawing geometry algorithm
 			response = facet_curve->get_geometry_query_engine()->
-				get_graphics( facet_curve, num_points, &g_mem );
+				get_graphics( facet_curve, &g_mem );
+			int num_points = g_mem.pointListCount;
 
 			if (response==CUBIT_FAILURE || num_points == 0)
 			{
@@ -2903,25 +3977,24 @@
 		vec2=vec2+target_mid_point;
 		vec3=vec3+target_mid_point;
 
+                DLIList<BodySM*> neighbor_imprint_list;
 		//do a webcut with a plane created from the three projected points above
 		CubitStatus status2 = gePtr1->webcut(sweep_result_list,target_mid_point,
-			vec2,vec3,webcut_results_list);
+			vec2,vec3, neighbor_imprint_list, webcut_results_list);
 
 		if (status2 == 0)
 		{
 			PRINT_ERROR( "Sweep operation worked; however, webcut operation failed.\n" );
 			//delete memory since it failed
 			gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
-			gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
 			return CUBIT_FAILURE;
 		}
 
-		if (webcut_results_list.size()<=0)
+		if (webcut_results_list.size()==0)
 		{
 			PRINT_ERROR( "Number of bodies from webcut is zero, unable to perform rest of sweep operation\n" );
 			//delete memory since it failed
 			gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
-			gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
 			return CUBIT_FAILURE;
 		}
 
@@ -2975,12 +4048,24 @@
 		//delete webcut_results_list memory
 		gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
 
+                if( CubitUndo::get_undo_enabled() )
+                  CubitUndo::save_state();
+
 		//builds ref bodies
-		if (!sweep_finish("translational", body_list, keep_bodies_list, change_newids))
+    DLIList<Body*> output_body_list;
+		if (!sweep_finish("translational", body_list, keep_bodies_list, output_body_list, change_newids))
 		{
 			gePtr1->get_gqe()->delete_solid_model_entities(keep_bodies_list);
 			status = CUBIT_FAILURE;
 		}
+
+    if( CubitUndo::get_undo_enabled())
+    {
+      if( status == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else
+        CubitUndo::note_result_bodies( output_body_list );
+    }
 	}
 	else
 	{
@@ -2988,11 +4073,225 @@
 		return CUBIT_FAILURE;
 	}
 
-	return CUBIT_SUCCESS; 
+	return CUBIT_SUCCESS;
 }
+// Author: Derek Quam
+// Dec. 1, 2008
+CubitStatus GeometryModifyTool::sweep_surface_target(RefFace *face,
+                                                     Body *target_body,
+                                                     CubitVector distance,
+                                                     CubitPlane stop_plane,
+                                                     double magnitude)
+{
+  //  Declare local variables
+  Surface *source_surf;
+  bool set_dist = true, set_plane = true, set_mag = true;
+  CubitVector direction;
+  CubitStatus status;
+  DLIList<Body*> body_list;
+  DLIList<GeometryEntity*> geom_list;
+  GeometryModifyEngine* gePtr1 = 0;
+  CubitBoolean change_newids;
+  DLIList<RefEntity*> ref_ent_list;
+  ref_ent_list.append(face);
 
+  // Check to make sure the target body is a solid
+  if (target_body->is_sheet_body())
+  {
+    PRINT_ERROR("Target body must be a solid body.\n");
+    return CUBIT_FAILURE;
+  }
+
+  // Set up the sweep
+  if (!sweep_setup("target", ref_ent_list, body_list, gePtr1, change_newids, geom_list))
+    return CUBIT_FAILURE;
+
+  // Get the Surface * from the RefFace *
+  source_surf = face->get_surface_ptr();
+
+  // Check if the direction vector and stop plane were specified
+  if (distance.length() < 0.0001)
+    set_dist = false;
+  if (stop_plane.normal().length() < 0.0001)
+    set_plane = false;
+  if (magnitude < 0.0001)
+    set_mag = false;
+
+  // Calculate the direction of the sweep
+  if (!set_dist)
+    direction = face->normal_at(face->center_point());
+  else
+    direction = distance;
+  direction.normalize();
+
+  double length = 0.0;
+  if (!set_mag && !set_plane)
+  {
+    CubitVector center_body = target_body->center_point();
+    CubitVector center_face = face->center_point();
+    length = center_face.distance_between(center_body);
+  }
+  else if (set_plane)
+  {
+    length = stop_plane.intersect(face->center_point(), direction).distance_between(face->center_point());
+  }
+  else
+  {
+    length = magnitude;
+  }
+  if (set_mag && length > magnitude)
+    length = magnitude;
+  direction *= length;
+
+  DLIList<BodySM*> new_bodies;
+  status = gePtr1->sweep_to_body(source_surf, target_body->get_body_sm_ptr(), direction, new_bodies);
+
+  if (status != CUBIT_SUCCESS)
+    return status;
+
+  // Make all the new bodies
+  DLIList<Body*> output_body_list;
+  if (!sweep_finish("target", body_list, new_bodies, output_body_list, change_newids))
+    status = CUBIT_FAILURE;
+    
+  
+  /*
+  for (int i = 0; i < new_bodies.size(); i++)
+    GeometryQueryTool::instance()->make_Body(new_bodies.get_and_step());
+    */
+    
+
+  return CUBIT_SUCCESS;
+}
+
+// Author: Andrew Rout and Derek Quam
+// Nov. 14, 2008
+CubitStatus GeometryModifyTool::sweep_curve_target(DLIList<RefEdge*>& edge_list,
+                                                   Body *target_body,
+                                                   DLIList<Body*> &out_bodies,
+                                                   CubitVector distance,
+                                                   CubitPlane stop_plane,
+                                                   bool unite)
+{
+  DLIList<BodySM*> new_bodies;
+  DLIList<Curve*> curve_list;
+  bool set_dist = true, set_plane = true;
+  double larDist = 1.0;
+  CubitVector dir = distance;
+  CubitStatus status;
+
+  // Check to make sure the target body is a sheetbody
+  if (!target_body->is_sheet_body())
+  {
+    PRINT_ERROR("Target body must be a sheet body.\n");
+    return CUBIT_FAILURE;
+  }
+
+  // Get the Curve *'s from the RefEdge *'s
+  for (int i = 0; i < edge_list.size(); i++)
+  {
+    edge_list[i]->get_curve_ptr()->set_saved_id(edge_list[i]->id());
+    curve_list.append(edge_list[i]->get_curve_ptr());
+  }
+  // Check if the direction vector and stop plane were specified
+  if (distance.length() < 0.0001)
+    set_dist = false;
+  if (stop_plane.normal().length() < 0.0001)
+    set_plane = false;
+
+  // Check inputs
+  if (!set_plane && !set_dist)
+  {
+    PRINT_ERROR("User must specify a stop plane, a direction, or both.\n");
+    return CUBIT_FAILURE;
+  }
+
+  // Calculate the direction vector
+  double begDist, midDist, endDist;
+  for (int i = 0; i < edge_list.size(); i++)
+  {
+    CubitVector beg, mid, end, begP, midP, endP;
+    RefEdge *temp = edge_list.get_and_step();
+
+    // Retrieve the beginning, middle, and end coordinates of the edge
+    beg = temp->start_coordinates();
+    temp->mid_point(mid);
+    end = temp->end_coordinates();
+
+    if (set_plane)
+    {
+      // Project the start, mid, and end point onto the stop plane
+      begP = stop_plane.project(beg);
+      midP = stop_plane.project(mid);
+      endP = stop_plane.project(end);
+
+      // Calculate the distance between the points
+      begDist = beg.distance_between(begP);
+      midDist = mid.distance_between(midP);
+      endDist = end.distance_between(endP);
+    }
+    else  // No stop plane specified
+    {
+      begDist = beg.distance_between(target_body->center_point());
+      midDist = mid.distance_between(target_body->center_point());
+      endDist = end.distance_between(target_body->center_point());
+    }
+
+    // Find the largest distance
+    if (begDist > larDist)
+      larDist = begDist;
+    if (midDist > larDist)
+      larDist = midDist;
+    if (endDist > larDist)
+      larDist = endDist;
+
+    // Make sure the plane normal is pointing the right way
+    if (set_plane)
+    {
+      double planeNorm = stop_plane.normal().interior_angle(beg-begP);
+      if (planeNorm <= 90 || planeNorm >= 270)
+        stop_plane.reverse();
+    }
+
+    if (!set_dist)
+      dir += (midP-mid);
+
+  } // End for loop
+  if (!set_dist)
+    dir /= edge_list.size();
+
+  // Unitize the direction vector
+  dir /= dir.length();
+
+  // Add the magnitude to the direction vector and check for intersection with the stop plane
+  dir *= larDist;
+  if (set_plane)
+  {
+    double angle = dir.interior_angle(stop_plane.normal());
+    if (angle >= 90 && angle <= 270)
+      PRINT_WARNING("Direction vector does not intersect stop plane!\n");
+  }
+
+  // Call the geometry function
+  status = get_gme()->sweep_to_body(curve_list, target_body->get_body_sm_ptr(), dir, new_bodies, unite);
+
+  if (status != CUBIT_SUCCESS)
+    return CUBIT_FAILURE;
+
+  // Make all the new bodies
+  for (int i = 0; i < new_bodies.size(); i++)
+  {
+    out_bodies.append(GeometryQueryTool::instance()->make_Body(new_bodies.get_and_step()));
+    PRINT_INFO("Created volume in body %d\n", out_bodies[i]->id());
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+//Author: Jonathan Bugman
+//Sept 10, 2006
 CubitStatus GeometryModifyTool::sweep_surface_target(CubitPlane ref_plane,
-													 DLIList<RefEntity*>& ref_ent_list)
+                                    DLIList<RefEntity*>& ref_ent_list)
 {
 	DLIList<RefFace*> surface_list;
 	CAST_LIST(ref_ent_list, surface_list, RefFace);
@@ -3014,7 +4313,7 @@
 	//make sure that only one surface has been selected
 	if(surface_list.size() == 0)
 	{
-		PRINT_ERROR( "No edge(s) found - sweep surface to target failed.\n" );
+		PRINT_ERROR( "No surface found - sweep surface to target failed.\n" );
 		return CUBIT_FAILURE;
 	}
 
@@ -3037,7 +4336,7 @@
 				//get midpoint of edge on surface
 				surf_edge_list[j]->mid_point(get_mid_point);
 				//Project the midpoint of each surface edge onto the specified plane
-				target_mid_point = ref_plane.project(get_mid_point);		
+				target_mid_point = ref_plane.project(get_mid_point);
 
 				//Calculate the distance between the mid_point, and target_point
 				distance1 = target_mid_point.distance_between(get_mid_point);
@@ -3114,7 +4413,6 @@
 			{
 				Curve *facet_curve;
 				facet_curve=surf_edge_list[ii]->get_curve_ptr();
-				int num_points;
 				int color = 2;
 				CubitStatus response;
 				GMem g_mem;
@@ -3122,8 +4420,10 @@
 				//get number of points and their locations
 				//on the curve as defined by the drawing geometry algorithm
 				response = facet_curve->get_geometry_query_engine()->
-					get_graphics( facet_curve, num_points, &g_mem );
+					get_graphics( facet_curve, &g_mem );
 
+        int num_points = g_mem.pointListCount;
+
 				if (response==CUBIT_FAILURE || num_points == 0)
 				{
 					PRINT_WARNING("Unable to preview a curve\n" );
@@ -3182,6 +4482,10 @@
 			change_newids, geom_list))
 			return CUBIT_FAILURE;
 
+    if( CubitUndo::get_undo_enabled())
+      //Faces will get consumed so you have to save out original entities
+      CubitUndo::save_state_with_cubit_file( surface_list );
+
 		DLIList<BodySM*> sweep_result_list;
 
 		//below block is default settings to be fed into sweep_translational
@@ -3214,12 +4518,16 @@
 			//print an error to the screen for the user
 			gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
 			PRINT_ERROR( "Error occured in the sweep operation.\n" );
+
+                        if( CubitUndo::get_undo_enabled())
+                          CubitUndo::remove_last_undo();
 			return CUBIT_FAILURE;
 		}
 
+                DLIList<BodySM*> neighbor_imprint_list;
 		//do a webcut with a plane created from the three projected points
 		CubitStatus status2 = gePtr1->webcut(sweep_result_list,target_mid_point,
-			vec2,vec3,webcut_results_list);
+			vec2,vec3,neighbor_imprint_list, webcut_results_list);
 
 		if (status2 == 0)
 		{
@@ -3228,6 +4536,9 @@
 			gePtr1->get_gqe()->delete_solid_model_entities(sweep_result_list);
 			gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
 			PRINT_ERROR( "Error occured in the webcut operation.\n" );
+
+                        if( CubitUndo::get_undo_enabled())
+                          CubitUndo::remove_last_undo();
 			return CUBIT_FAILURE;
 		}
 
@@ -3244,7 +4555,7 @@
 		CubitVector vec_1 = mid_point_surface - target_mid_point_surface;
 		vec_1.normalize();
 
-		//step through the 
+		//step through the
 		for (int counter=0;counter<webcut_results_list.size();counter++)
 		{
 			//find the geometric midpoint of the body and project that point on the target plane
@@ -3272,6 +4583,9 @@
 			PRINT_ERROR( "All sweeped surfaces deleted - sweep_target failed.\n" );
 			PRINT_ERROR( "This may be due to granite engine limitations and/or\n" );
 			PRINT_ERROR( "angle between curve and target surface\n" );
+
+                        if( CubitUndo::get_undo_enabled())
+                          CubitUndo::remove_last_undo();
 			return CUBIT_FAILURE;
 		}
 
@@ -3280,9 +4594,18 @@
 		gePtr1->get_gqe()->delete_solid_model_entities(webcut_results_list);
 
 		//builds ref bodies
-		if (!sweep_finish("translational", body_list, keep_bodies_list, change_newids))
+    DLIList<Body*> output_body_list;
+		if (!sweep_finish("translational", body_list, keep_bodies_list, output_body_list, change_newids))
 			status = CUBIT_FAILURE;
 
+    if( CubitUndo::get_undo_enabled())
+    {
+      if( status == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else
+        CubitUndo::note_result_bodies( output_body_list );
+    }
+
 	}
 	return CUBIT_SUCCESS;
 }
@@ -3303,6 +4626,22 @@
                    change_newids, geom_list))
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    DLIList<RefEdge*> edge_list;
+    DLIList<RefFace*> face_list;
+
+    CAST_LIST( ref_ent_list, edge_list, RefEdge );
+    CAST_LIST( ref_ent_list, face_list, RefFace );
+
+    //Edges aren't consumed, so there's nothing to save out
+    if( edge_list.size() )
+      CubitUndo::save_state();
+    else
+     //Faces will get consumed so you have to save out original entities
+      CubitUndo::save_state_with_cubit_file( face_list );
+  }
+
   DLIList<BodySM*> result_list;
   CubitStatus status = gePtr1->
     sweep_perpendicular( geom_list,
@@ -3313,9 +4652,18 @@
                          switchside,
                          rigid);
 
-  if (!sweep_finish("perpendicular", body_list, result_list, change_newids))
+  DLIList<Body*> output_body_list;
+  if (!sweep_finish("perpendicular", body_list, result_list, output_body_list, change_newids))
     status = CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    if( status == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+    else
+      CubitUndo::note_result_bodies( output_body_list );
+  }
+
   return status;
 }
 CubitStatus GeometryModifyTool::sweep_along_curve(DLIList<RefEntity*>& ref_ent_list,
@@ -3325,38 +4673,61 @@
                                                   CubitBoolean rigid)
 
 {
-   DLIList<GeometryEntity*> geom_list(ref_ent_list.size());
-   DLIList<Curve*> curve_list(ref_edge_list.size());
-   DLIList<Body*> body_list(ref_ent_list.size());
-   GeometryModifyEngine* engine_ptr = 0;
-   CubitBoolean changed_new_ids = CUBIT_FALSE;
-   CubitStatus status = sweep_setup( "along_curve",
-                                     ref_ent_list,
-                                     body_list,
-                                     engine_ptr,
-                                     changed_new_ids,
-                                     geom_list,
-                                     &ref_edge_list,
-                                     &curve_list );
-   if (status != CUBIT_SUCCESS)
-    return status;
+  DLIList<GeometryEntity*> geom_list(ref_ent_list.size());
+  DLIList<Curve*> curve_list(ref_edge_list.size());
+  DLIList<Body*> body_list(ref_ent_list.size());
+  GeometryModifyEngine* engine_ptr = 0;
+  CubitBoolean changed_new_ids = CUBIT_FALSE;
+  CubitStatus status = sweep_setup( "along_curve",
+                                    ref_ent_list,
+                                    body_list,
+                                    engine_ptr,
+                                    changed_new_ids,
+                                    geom_list,
+                                    &ref_edge_list,
+                                    &curve_list );
+  if (status != CUBIT_SUCCESS)
+  return status;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    DLIList<RefEdge*> edge_list;
+    DLIList<RefFace*> face_list;
 
+    CAST_LIST( ref_ent_list, edge_list, RefEdge );
+    CAST_LIST( ref_ent_list, face_list, RefFace );
 
-   DLIList<BodySM*> result_list;
-   status = engine_ptr->sweep_along_curve( geom_list,
-                                           result_list,
-                                           curve_list,
-                                           draft_angle,
-                                           draft_type,
-                                           rigid);
+    //Edges aren't consumed, so there's nothing to save out
+    if( edge_list.size() )
+      CubitUndo::save_state();
+    else
+      //Faces will get consumed so you have to save out original entities
+      CubitUndo::save_state_with_cubit_file( face_list );
+  }
 
-   if (!sweep_finish("along_curve", body_list, result_list, changed_new_ids))
-    status = CUBIT_FAILURE;
+  DLIList<BodySM*> result_list;
+  status = engine_ptr->sweep_along_curve( geom_list,
+                                          result_list,
+                                          curve_list,
+                                          draft_angle,
+                                          draft_type,
+                                          rigid);
 
-   return status;
+  DLIList<Body*> output_body_list;
+  if (!sweep_finish("along_curve", body_list, result_list, output_body_list, changed_new_ids))
+  status = CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled())
+  {
+    if( status == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+    else
+      CubitUndo::note_result_bodies( output_body_list );
+  }
+
+  return status;
 }
+
 void GeometryModifyTool::initialize_settings() {
 
 
@@ -3380,6 +4751,13 @@
             GeometryModifyTool::set_old_names,
             GeometryModifyTool::get_old_names);
 
+  SettingHandler::instance()->add_setting("Mesh Auto Delete",
+					  GeometryModifyTool::set_mesh_autodelete,
+					  GeometryModifyTool::get_mesh_autodelete);
+
+  SettingHandler::instance()->add_setting("Mesh Auto Delete Cache",
+					  GeometryModifyTool::set_mesh_autodelete_remesh,
+					  GeometryModifyTool::is_mesh_autodelete_remesh);
 }
 
 
@@ -3420,8 +4798,10 @@
                                            const CubitVector axes[3],
                                            const CubitVector &extension,
                                            DLIList<Body*> &results_list,
-                                           CubitBoolean imprint,
-                                           CubitBoolean merge )
+                                           DLIList<Body*> &neighboring_bodies,
+                                           ImprintType imprint_type,
+                                           CubitBoolean merge,
+                                           CubitBoolean preview)
 {
    // Make sure that entity creation is possible.  Allow at most
    // only one of the dimensions to be zero - in which case a planar
@@ -3472,12 +4852,21 @@
       }
 
       return webcut_with_planar_sheet (webcut_body_list, center, sheet_axes,
-                          width, height, results_list, imprint, merge);
+                          width, height, results_list, neighboring_bodies,
+                          imprint_type, merge, preview);
    }
 
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
-     return CUBIT_FAILURE;
+     return CUBIT_FAILURE;  
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     DLIList<Body*> bodies_to_save;
+     bodies_to_save += webcut_body_list;
+     bodies_to_save += neighboring_bodies;
+     CubitUndo::save_state_with_cubit_file( bodies_to_save );
+   }
+
    CubitStatus rval = CUBIT_SUCCESS;
 
    const int count = webcut_body_list.size();
@@ -3487,18 +4876,53 @@
    DLIList<Body*> engine_bodies(count);
    GeometryModifyEngine* gme = 0;
 
-   do_attribute_setup();
-
    while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
    {
-      push_vg_attributes_before_modify(engine_body_sms);
+     DLIList<int> merged_surface_ids;
+     DLIList<int> merged_curve_ids;
+     DLIList<BodySM*> neighbor_imprint_list;
+     if (!preview)
+     {
+       int i;
+       for( i=neighboring_bodies.size(); i--; )
+       {
+         Body *neighbor_body = neighboring_bodies.get_and_step();
+         BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+         GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+         
+         if( gme == neighbor_gme )
+         {
+           neighbor_imprint_list.append( tmp_body ); 
+           engine_bodies.append( neighbor_body );
+         }
+       }
 
+       do_attribute_setup();
+       DLIList<BodySM*> bodies_to_modify;
+       bodies_to_modify += engine_body_sms;
+       bodies_to_modify += neighbor_imprint_list;
+       push_vg_attributes_before_modify( bodies_to_modify );
+       get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
+     }
+
       CubitStatus status = gme->webcut_with_brick (
-        engine_body_sms, center, axes, extension, result_sm_list, imprint );
+        engine_body_sms, center, axes, extension,
+        neighbor_imprint_list,
+        result_sm_list, imprint_type, preview );
 
-      restore_vg_after_modify(result_sm_list, engine_bodies);
+      // just continue the loop if previewing
+      if (preview)
+      {
+        rval = status;
+        continue;
+      }
 
-      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list );
+      restore_vg_after_modify(result_sm_list, engine_bodies, gme);
+      remove_pushed_attributes(result_sm_list, engine_bodies);
+
+      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list,
+                              &merged_surface_ids, &merged_curve_ids );
+
       if (!status)
         rval = CUBIT_FAILURE;
 
@@ -3507,8 +4931,17 @@
       result_sm_list.clean_out();
    }
 
-   do_attribute_cleanup();
+   if (!preview)
+     do_attribute_cleanup();
 
+   if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+   {
+     if( results_list.size() ) //if there are new bodies...something succeeded
+       CubitUndo::note_result_bodies( results_list );
+     else
+       CubitUndo::remove_last_undo();
+   }
+
    return rval;
 }
 
@@ -3518,8 +4951,10 @@
                                            const CubitVector axes[2],
                                            double width, double height,
                                            DLIList<Body*> &results_list,
-                                           CubitBoolean imprint,
-                                           CubitBoolean merge )
+                                           DLIList<Body*> &neighboring_bodies,
+                                           ImprintType imprint_type,
+                                           CubitBoolean merge,
+                                           CubitBoolean preview)
 {
    if ( width <= GEOMETRY_RESABS || height <= GEOMETRY_RESABS )
    {
@@ -3534,23 +4969,67 @@
 
    CubitStatus rval = CUBIT_SUCCESS;
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<Body*> bodies_to_save;
+    bodies_to_save += webcut_body_list;
+    bodies_to_save += neighboring_bodies;
+    CubitUndo::save_state_with_cubit_file( bodies_to_save );
+  }
+
    const int count = webcut_body_list.size();
    DLIList<BodySM*> result_sm_list;
    DLIList<Body*> body_list(webcut_body_list);
    DLIList<BodySM*> engine_body_sms(count);
    DLIList<Body*> engine_bodies(count);
    GeometryModifyEngine* gme = 0;
-   do_attribute_setup();
+
    while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
    {
-      push_vg_attributes_before_modify(engine_body_sms);
+     DLIList<int> merged_surface_ids;
+     DLIList<int> merged_curve_ids;
+     DLIList<BodySM*> neighbor_imprint_list;
+     if (!preview)
+     {
+       int i;
+       for( i=neighboring_bodies.size(); i--; )
+       {
+         Body *neighbor_body = neighboring_bodies.get_and_step();
+         BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+         GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+         
+         if( gme == neighbor_gme )
+         {
+           neighbor_imprint_list.append( tmp_body ); 
+           engine_bodies.append( neighbor_body );
+         }
+       }
 
+       do_attribute_setup();
+       DLIList<BodySM*> bodies_sms_to_modify;
+       bodies_sms_to_modify += engine_body_sms;
+       bodies_sms_to_modify += neighbor_imprint_list;
+       push_vg_attributes_before_modify( bodies_sms_to_modify );
+       get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
+     }
+
       CubitStatus status = gme->webcut_with_planar_sheet (
-        engine_body_sms, center, axes, width, height, result_sm_list, imprint );
+        engine_body_sms, center, axes, width, height,
+        neighbor_imprint_list,
+        result_sm_list, imprint_type, preview );
 
-      restore_vg_after_modify(result_sm_list, engine_bodies);
+      // just continue the loop if previewing
+      if (preview)
+      {
+        rval = status;
+        continue;
+      }
 
-      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list );
+      restore_vg_after_modify(result_sm_list, engine_bodies, gme);
+      remove_pushed_attributes(result_sm_list, engine_bodies);
+
+      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list,
+                              &merged_surface_ids, &merged_curve_ids );
       if (!status)
         rval = CUBIT_FAILURE;
 
@@ -3559,8 +5038,17 @@
       result_sm_list.clean_out();
    }
 
-   do_attribute_cleanup();
+   if (!preview)
+     do_attribute_cleanup();
 
+  if( preview == CUBIT_FALSE && CubitUndo::get_undo_enabled() )
+  {
+    if( rval == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( results_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
    return rval;
 }
 
@@ -3570,14 +5058,29 @@
                                     const CubitVector &vector2,
                                     const CubitVector &vector3,
                                     DLIList<Body*>& results_list,
-                                    CubitBoolean imprint,
-                                    CubitBoolean merge)
+                                    DLIList<Body*> &neighboring_bodies,
+                                    ImprintType imprint_type,
+                                    CubitBoolean merge,
+                                    CubitBoolean preview)
 {
   if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
     return CUBIT_FAILURE;
 
   CubitStatus rval = CUBIT_SUCCESS;
+  if (preview)
+  {
+    GeometryModifyTool::plane_preview(webcut_body_list, vector1, vector2, vector3);
+    return rval;
+  }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    DLIList<Body*> bodies_to_save;
+    bodies_to_save += webcut_body_list;
+    bodies_to_save += neighboring_bodies;
+    CubitUndo::save_state_with_cubit_file( bodies_to_save );
+  }
+
   const int count = webcut_body_list.size();
   DLIList<BodySM*> temp_sm_list(webcut_body_list.size());
   DLIList<BodySM*> result_sm_list;
@@ -3586,19 +5089,59 @@
   DLIList<Body*> engine_bodies(count);
   GeometryModifyEngine* gme = 0;
 
-  do_attribute_setup();
+  // all preview stuff handled before this point
+  if(!preview)
+    do_attribute_setup();
 
   while ( (gme = group_bodies_by_engine(body_list, engine_bodies, engine_body_sms)) )
   {
-    push_vg_attributes_before_modify(engine_body_sms);
 
+    //get all the child entities that have been merged
+    DLIList<int> merged_surface_ids;
+    DLIList<int> merged_curve_ids;
+    DLIList<BodySM*> neighbor_imprint_list;
+
+    if (!preview)
+    {
+      int i;
+      for( i=neighboring_bodies.size(); i--; )
+      {
+        Body *neighbor_body = neighboring_bodies.get_and_step();
+        BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+        GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+        
+        if( gme == neighbor_gme )
+        {
+          neighbor_imprint_list.append( tmp_body ); 
+          engine_bodies.append( neighbor_body );
+        }
+      }
+
+      DLIList<BodySM*> bodies_sms_to_modify;
+      bodies_sms_to_modify += engine_body_sms;
+      bodies_sms_to_modify += neighbor_imprint_list;
+      push_vg_attributes_before_modify( bodies_sms_to_modify );
+      get_merged_curve_and_surface_ids( engine_bodies, merged_surface_ids, merged_curve_ids );
+    }
+
     CubitStatus status = gme->webcut(engine_body_sms, vector1, vector2,
-              vector3, result_sm_list, imprint );
+              vector3, neighbor_imprint_list, result_sm_list, imprint_type, preview );
 
-    restore_vg_after_modify(result_sm_list, engine_bodies);
-
     if ( status != CUBIT_FAILURE )
-      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list );
+    {
+      if(!preview)
+      {
+        restore_vg_after_modify(result_sm_list, engine_bodies, gme);
+        remove_pushed_attributes(result_sm_list, engine_bodies);
+      }
+      status = finish_webcut( engine_bodies, result_sm_list, merge, status, results_list,
+                              &merged_surface_ids, &merged_curve_ids );
+    }
+    else
+    {
+      if(!preview)
+        remove_pushed_attributes(result_sm_list, engine_bodies);
+    }
 
     engine_bodies.clean_out();
     engine_body_sms.clean_out();
@@ -3611,18 +5154,28 @@
     }
   }
 
-  do_attribute_cleanup();
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( rval == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( results_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
 
+  if(!preview)
+    do_attribute_cleanup();
+
   return rval;
 }
 
-CubitStatus GeometryModifyTool::restore_vg_after_modify(DLIList<BodySM*> &new_sms,
+void GeometryModifyTool::remove_pushed_attributes(DLIList<BodySM*> &new_sms,
                                                         DLIList<Body*> &old_bodies)
 {
   DLIList<TopologyBridge*> old_bridges(old_bodies.size());
   DLIList<TopologyBridge*> new_bridges(new_sms.size());
   CAST_LIST(new_sms, new_bridges, TopologyBridge);
 
+  // Get bridges for all of the old Bodies.
   int k;
   for(k = old_bodies.size(); k>0; k--)
   {
@@ -3631,37 +5184,106 @@
     if(tb)
     {
       old_bridges.append(tb);
+      DLIList<TopologyBridge*> bridge_list;
+      bridge_list.append(tb);
+      // Add any bodies with composites to the new_sms list so that
+      // make_Body gets called on them.  This will make sure that the
+      // virtual gets ref entities properly built.
+      if(this->contains_composites(bridge_list))
+      {
+        BodySM *bsm = dynamic_cast<BodySM*>(tb);
+        if(bsm)
+          new_sms.append_unique(bsm);
+      }
     }
   }
 
+  // Make a list including all of the bridges passed in.
   DLIList<TopologyBridge*> all_bridges;
   all_bridges = new_bridges;
   for(k=old_bridges.size(); k--;)
     all_bridges.append_unique(old_bridges.get_and_step());
 
-  // After a real geometry operation some of the virtual topology bridges may
-  // have been blown away and some of them may have just had underlying
-  // topology modified.  These calls will try to recognize virtual geometry
-  // that has been modified so that it can be deactivated and rebuilt.
-  // I am calling it on both of these lists because it is not always clear
-  // which one will have the virtual we are interested in.
-  GeometryQueryTool::instance()->ige_remove_modified(all_bridges);
+  // At this point we don't need any more attributes on the underlying
+  // entities so make sure they are cleaned up.
+  GeometryQueryTool::instance()->ige_remove_attributes( all_bridges );
+}
 
-  // Now that we have removed any virtual that was affected by the operation we
-  // can examine the remaining virtual and remove any COMPOSITE_GEOM attributes
-  // that are unneeded since the virtual already exists and wasn't modified by 
-  // the operation.  Another way of saying this is that we don't need to process the
-  // COMPOSITE_GEOM attributes to rebuild the virtual layer if the virtual layer is 
-  // already there.
-  GeometryQueryTool::instance()->ige_remove_attributes_from_unmodifed_virtual(all_bridges);
+CubitStatus GeometryModifyTool::restore_vg_after_modify(DLIList<BodySM*> &new_sms,
+                                                        DLIList<Body*> &old_bodies,
+                                                        GeometryModifyEngine *gme)
+{
+  DLIList<TopologyBridge*> old_bridges(old_bodies.size());
+  DLIList<TopologyBridge*> new_bridges(new_sms.size());
+  CAST_LIST(new_sms, new_bridges, TopologyBridge);
 
+  // Get bridges for all of the old Bodies.
+  int k;
+  for(k = old_bodies.size(); k>0; k--)
+  {
+    Body *body = old_bodies.get_and_step();
+    TopologyBridge *tb = body->bridge_manager()->topology_bridge();
+    if(tb)
+    {
+      old_bridges.append(tb);
+      DLIList<TopologyBridge*> bridge_list;
+      bridge_list.append(tb);
+      // Add any bodies with composites to the new_sms list so that
+      // make_Body gets called on them.  This will make sure that the
+      // virtual gets ref entities properly built.
+      if(this->contains_composites(bridge_list))
+      {
+        BodySM *bsm = dynamic_cast<BodySM*>(tb);
+        if(bsm)
+          new_sms.append_unique(bsm);
+      }
+    }
+  }
+
+  // Make a list including all of the bridges passed in.
+  DLIList<TopologyBridge*> all_bridges;
+  all_bridges = new_bridges;
+  for(k=old_bridges.size(); k--;)
+    all_bridges.append_unique(old_bridges.get_and_step());
+
+  DLIList<TopologyBridge*> tbs_to_check;
+  if(gme)
+    gme->get_possible_invalid_tbs(all_bridges, tbs_to_check);
+
+  DLIList<Surface*> all_surfs;
+  DLIList<Curve*> all_curves;
+  DLIList<Point*> all_points;
+  if(tbs_to_check.size() > 0)
+  {
+    for(k=tbs_to_check.size(); k--;)
+    {
+      TopologyBridge *tb = tbs_to_check.get_and_step();
+      Surface *surf = dynamic_cast<Surface*>(tb);
+      if(surf)
+        all_surfs.append(surf);
+      else
+      {
+        Curve *cur = dynamic_cast<Curve*>(tb);
+        if(cur)
+          all_curves.append(cur);
+        else
+        {
+          Point *pt = dynamic_cast<Point*>(tb);
+          if(pt)
+            all_points.append(pt);
+        }
+      }
+    }
+  }
+
+  // This function has been changed to blown away any virtual (really only doing
+  // composites right now).  The virtual will rebuilt from the attributes stored
+  // on the ACIS entities.
+  GeometryQueryTool::instance()->ige_remove_modified(all_surfs, all_curves, all_points);
+
   //Restore virtual
   GeometryQueryTool::instance()->ige_import_geom( all_bridges );
 
-  // At this point we don't need any more attributes on the underlying
-  // entities so make sure they are cleaned up.
-  GeometryQueryTool::instance()->ige_remove_attributes( all_bridges );
-
   return CUBIT_SUCCESS;
 }
 
@@ -3736,7 +5358,7 @@
 
 CubitStatus GeometryModifyTool::unite( DLIList<BodySM*> &body_sm_list,
                                        DLIList<BodySM*> &new_body_sm_list,
-                                       bool keep_old )
+                                       bool keep_old)
 {
   //this assumes that all bodies have the same modify engine
   GeometryModifyEngine *gme = get_engine( body_sm_list.get() );
@@ -3744,18 +5366,18 @@
   return result;
 }
 
-
-CubitStatus GeometryModifyTool::unite( DLIList<Body*> &bodies,
-                                       DLIList<Body*> &newBodies,
-                                       bool keep_old )
+CubitStatus
+GeometryModifyTool::unite( DLIList<Body*> &bodies,
+                           DLIList<Body*> &new_body_list,
+                           bool keep_old )
 {
-   if (bodies.size() <= 1)
-   {
-      PRINT_WARNING("There is only one body in the list. Nothing modified\n");
-      return CUBIT_FAILURE;
-   }
-   if (!okay_to_modify( bodies, "UNITE" ))
-     return CUBIT_FAILURE;
+  if( bodies.size() <= 1 )
+  {
+    PRINT_WARNING("There is only one volume in the list. Nothing modified.\n");
+    return CUBIT_FAILURE;
+  }
+  if (!okay_to_modify( bodies, "UNITE" ))
+    return CUBIT_FAILURE;
 
   int i;
   const int count = bodies.size();
@@ -3766,72 +5388,223 @@
     entity_list.append_unique(bodies.get_and_step());
   GeometryModifyEngine* gme = common_modify_engine( entity_list, bridge_list );
 
-  if ( !gme )
+  if( !gme )
   {
-      PRINT_ERROR("Performing UNITE with volumes containing geometry from\n"
-                  "different modeling engines is not allowed.\n"
-                  "Delete uncommon geometry on these volumes before operation.\n\n");
-      return CUBIT_FAILURE;
+    PRINT_ERROR("Performing UNITE with volumes containing geometry from\n"
+      "different modeling engines is not allowed.\n"
+      "Delete uncommon geometry on these volumes before operation.\n\n");
+    return CUBIT_FAILURE;
   }
 
-    // give 1st body in "old_bodies" list all the
-    //  names of all bodies being united
+  // Cubit can't mesh mixed sheet/solid bodies that are united together. If
+  // required, separate the unite between these types.
+  CubitStatus result;
+  if( GeometryModifyTool::instance()->unite_mixed_models() )
+    result = unite_all( gme, bodies, new_body_list, keep_old );
+  else
+    result = unite_separately( gme, bodies, new_body_list, keep_old );
 
+  if( result == CUBIT_FAILURE )
+    PRINT_ERROR("UNITE failed\n");
+
+  return result;
+}
+
+CubitStatus
+GeometryModifyTool::unite_separately( GeometryModifyEngine *gme_ptr,
+                                      DLIList<Body*> &bodies,
+                                      DLIList<Body*> &new_body_list,
+                                      bool keep_old )
+{
+  // Cubit can't mesh mixed sheet/solid bodies that are united together. Sort
+  // based on these types.
+  int i;
+  Body *body_ptr;
+  DLIList<Body*> solid_body_list;
+  DLIList<Body*> sheet_body_list;
+  bodies.reset();
+  for( i=bodies.size(); i--; )
+  {
+    body_ptr = bodies.get_and_step();
+
+    if( body_ptr->is_sheet_body() )
+      sheet_body_list.append( body_ptr );
+    else
+      solid_body_list.append( body_ptr );
+  }
+
+  if( sheet_body_list.size() == 1 && solid_body_list.size() == 1 )
+  {
+    PRINT_ERROR( "Cannot unite solid and sheet bodies together\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Setup undo
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( bodies );
+  }
+
+  // Unite solids with each other, and sheets with each other separately
+  CubitStatus result1 = CUBIT_SUCCESS;
+  CubitStatus result2 = CUBIT_SUCCESS;
+  if( solid_body_list.size() > 1 )
+    result1 = unite_private( gme_ptr, solid_body_list, new_body_list, keep_old );
+  if( sheet_body_list.size() > 1 )
+    result2 = unite_private( gme_ptr, sheet_body_list, new_body_list, keep_old );
+
+  // Finish undo
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body_list.size() )
+      CubitUndo::note_result_bodies( new_body_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  // Return success if both unites successful
+  if( result1 == CUBIT_SUCCESS && result2 == CUBIT_SUCCESS )
+    return CUBIT_SUCCESS;
+
+  // Return success if either unite was successful
+  if( solid_body_list.size() > 1 && result1 == CUBIT_SUCCESS ||
+      sheet_body_list.size() > 1 && result2 == CUBIT_SUCCESS )
+  {
+    // Give warning if one or the other failed
+    if( result1 = CUBIT_FAILURE )
+      PRINT_WARNING( "Unite of solid volumes failed\n" );
+    if( result2 = CUBIT_FAILURE )
+      PRINT_WARNING( "Unite of sheet bodies failed\n" );
+
+    return CUBIT_SUCCESS;
+  }
+
+  return CUBIT_FAILURE;
+}
+
+CubitStatus
+GeometryModifyTool::unite_all( GeometryModifyEngine *gme_ptr,
+                               DLIList<Body*> &bodies,
+                               DLIList<Body*> &new_body_list,
+                               bool keep_old )
+{
+  // Setup undo
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( bodies );
+  }
+
+  // Unite solids with each other, and sheets with each other separately
+  CubitStatus result = unite_private( gme_ptr, bodies, new_body_list, keep_old );
+
+  // Finish undo
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_body_list.size() )
+      CubitUndo::note_result_bodies( new_body_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+  
+  return result;
+}
+
+// Private workhorse function for unite
+CubitStatus
+GeometryModifyTool::unite_private( GeometryModifyEngine *gme_ptr,
+                                   DLIList<Body*> &body_list,
+                                   DLIList<Body*> &new_body_list,
+                                   bool keep_old )
+{
+  if( !body_list.size() )
+    return CUBIT_SUCCESS;
+
+  int i, j;
+  Body *body_ptr;
+  CubitStatus result;
+
+  // Give 1st body all the names of all bodies being united
   std::list<CubitString> names_list;
   DLIList<CubitString*> entity_names;
 
-  //Loop through second till end body
-  for (i=0; i < bodies.size(); i++)
+  body_list.reset();
+  for( i=body_list.size(); i--; )
   {
+    body_ptr = body_list.get_and_step();
 
-      //See if body has names
-    if(bodies.get()->num_names())
+    // See if body has names
+    if( body_ptr->num_names() )
     {
-      //Put the names in a list
-      bodies.get()->entity_names( entity_names );
+      // Put the names in a list
+      body_ptr->entity_names( entity_names );
       entity_names.reset();
 
-      //Loop through names
-      for (int ij = 0; ij < entity_names.size(); ij++)
+      // Loop through names
+      for( j=entity_names.size(); j--; )
         names_list.push_back( *entity_names.get_and_step() );
 
       entity_names.clean_out();
-      bodies.get()->remove_entity_names();
+      body_ptr->remove_entity_names();
     }
-    bodies.step();
   }
 
-  DLIList<BodySM*> body_sm_list(bridge_list.size());
-  DLIList<BodySM*> new_bodies;
+  do_attribute_setup();
+
+  DLIList<TopologyEntity*> entity_list(body_list.size());
+  DLIList<TopologyBridge*> bridge_list(body_list.size());
+  body_list.reset();
+  for( i=body_list.size(); i--; )
+    entity_list.append_unique(body_list.get_and_step());
+  common_modify_engine( entity_list, bridge_list );
+
+  DLIList<BodySM*> body_sm_list(body_list.size());
   CAST_LIST(bridge_list, body_sm_list, BodySM);
-  CubitStatus result = unite(body_sm_list, new_bodies, keep_old);
 
+  push_vg_attributes_before_modify(body_sm_list);
+
+  DLIList<int> merged_surface_ids;
+  DLIList<int> merged_curve_ids;
+
+  get_merged_curve_and_surface_ids( body_list, merged_surface_ids, merged_curve_ids );
+
+  DLIList<BodySM*> new_body_sm_list;
+  result = unite( body_sm_list, new_body_sm_list, keep_old );
+
+  restore_vg_after_modify( new_body_sm_list, body_list, gme_ptr );
+  remove_pushed_attributes( new_body_sm_list, body_list );
+
   DLIList<Body*> result_list;
-  if (!finish_sm_op(bodies, new_bodies, result_list))
+  if( !finish_sm_op(body_list, new_body_sm_list, result_list) )
     result = CUBIT_FAILURE;
 
-  if (result)
+  if( keep_old == CUBIT_FALSE )
+    fixup_merged_entities( merged_surface_ids, merged_curve_ids );
+
+  do_attribute_cleanup();
+
+  if( result )
   {
-    newBodies += result_list;
+    new_body_list += result_list;
 
-   int i;
-   for( i=result_list.size(); i--; )
-   {
-     //Add names to 1st body
-     std::list<CubitString>::iterator iter, end = names_list.end();
-     for (iter = names_list.begin(); iter != end; ++iter)
-       result_list.get_and_step()->entity_name( *iter );
-   }
+    for( j=result_list.size(); j--; )
+    {
+      //Add names to 1st body
+      std::list<CubitString>::iterator iter, end = names_list.end();
+      for (iter = names_list.begin(); iter != end; ++iter)
+        result_list.get_and_step()->entity_name( *iter );
+    }
   }
-  else
-  {
-     PRINT_ERROR("UNITE failed\n");
-  }
 
   return result;
 }
 
-CubitStatus GeometryModifyTool::chop( DLIList<Body*>& bodies,
+CubitStatus GeometryModifyTool::chop( DLIList<Body*> &bodies,
                                       DLIList<Body*> &intersectBodies,
                                       DLIList<Body*> &outsideBodies,
                                       Body*& leftoversBody,
@@ -3870,28 +5643,75 @@
    DLIList<BodySM*> intersect_bodies, outside_bodies;
    BodySM *leftovers_body = 0;
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old )
+       CubitUndo::save_state();
+     else
+     {
+       //Get all the bodies associated with the vertex
+       CubitUndo::save_state_with_cubit_file( bodies );
+     }
+   }
+
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<Body*> tmp_bodies(1);
+   tmp_bodies.append( bodies.get() );
+   if( keep_old == CUBIT_FALSE )
+     get_merged_curve_and_surface_ids( tmp_bodies, merged_surface_ids, merged_curve_ids );
+
    do_attribute_setup();
-   push_vg_attributes_before_modify(body_sm_list);
 
+   // Push attributes down onto the blank body (first one in list).
+   DLIList<BodySM*> tmp_body_sm_list;
+   body_sm_list.reset();
+   tmp_body_sm_list.append(body_sm_list.get());
+   push_vg_attributes_before_modify(tmp_body_sm_list);
+
    CubitStatus result = gme->chop( body_sm_list, intersect_bodies,
                           outside_bodies, leftovers_body, keep_old, nonreg );
 
    if( result == CUBIT_FAILURE )
    {
+     if( CubitUndo::get_undo_enabled() )
+       CubitUndo::remove_last_undo();
+
      PRINT_ERROR("CHOP failed\n");
+     remove_pushed_attributes(tmp_body_sm_list, tmp_bodies);
      do_attribute_cleanup();
      return CUBIT_FAILURE;
    }
 
-   restore_vg_after_modify(intersect_bodies, original_body_list);
-   restore_vg_after_modify(outside_bodies, original_body_list);
+   DLIList<BodySM*> all_sms = intersect_bodies;
+   all_sms += outside_bodies;
 
+   restore_vg_after_modify(all_sms, tmp_bodies, gme);
+   remove_pushed_attributes(all_sms, tmp_bodies);
+
    DLIList<Body*> result_bodies;
+
    body_sm_list.clean_out();
    body_sm_list += intersect_bodies;
 
-   if (!finish_sm_op(bodies, body_sm_list, result_bodies))
+   CubitStatus stat = finish_sm_op(bodies, body_sm_list, result_bodies);
+
+   if( keep_old == CUBIT_FALSE )
+     fixup_merged_entities( merged_surface_ids, merged_curve_ids);
+
+   if( CubitUndo::get_undo_enabled() )
    {
+     if( stat == CUBIT_SUCCESS )
+       CubitUndo::note_result_bodies( result_bodies );
+     else
+       CubitUndo::remove_last_undo();
+   }
+
+   if( stat == CUBIT_FAILURE )
+   {
+     if( CubitUndo::get_undo_enabled() )
+       CubitUndo::remove_last_undo();
+
      PRINT_ERROR("CHOP failed\n");
      do_attribute_cleanup();
      return CUBIT_FAILURE;
@@ -3904,6 +5724,9 @@
    result_bodies.clean_out();
    if (!finish_sm_op(bodies, body_sm_list, result_bodies))
    {
+     if( CubitUndo::get_undo_enabled() )
+       CubitUndo::remove_last_undo();
+
      PRINT_ERROR("CHOP failed\n");
      do_attribute_cleanup();
      return CUBIT_FAILURE;
@@ -3917,13 +5740,29 @@
      result_bodies.clean_out();
      if (!finish_sm_op(bodies, body_sm_list, result_bodies))
      {
+       if( CubitUndo::get_undo_enabled() )
+         CubitUndo::remove_last_undo();
+
        PRINT_ERROR("CHOP failed\n");
        do_attribute_cleanup();
        return CUBIT_FAILURE;
      }
      leftoversBody = result_bodies.get();
+
    }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( leftoversBody )
+    {
+      DLIList<Body*> tmp_list(1);
+      tmp_list.append( leftoversBody );
+      CubitUndo::note_result_bodies( tmp_list );
+    }
+    CubitUndo::note_result_bodies( intersectBodies );
+    CubitUndo::note_result_bodies( outsideBodies );
+  }
+
   do_attribute_cleanup();
   return CUBIT_SUCCESS;
 }
@@ -3959,6 +5798,9 @@
      return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state_with_cubit_file( bodies );
+
   DLIList<BodySM*> new_sms(count);
   DLIList<BodySM*> body_sms(count);
   CAST_LIST(bridge_list, body_sms, BodySM);
@@ -3998,6 +5840,14 @@
   if (!finish_sm_op(bodies, new_sms, new_bodies))
     result = CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( new_bodies.size() )
+      CubitUndo::note_result_bodies( new_bodies );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
   // Update graphics
   while (entities_to_update.size())
     entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
@@ -4052,18 +5902,18 @@
    }
 
 
-   DLIList<RefFace*> face_list;
    DLIList<RefFace*> ref_face_list;
    DLIList<RefFace*> free_face_list;
    DLIList<RefFace*> bad_face_list;
 
+   //gather all the faces from all the bodies
    bodies.reset();
+   for( int i=bodies.size(); i--; )
+   {
+     Body* BodyPtr = bodies.get_and_step();
+     BodyPtr->ref_faces(free_face_list);
+   }
 
-   Body* BodyPtr = bodies.get_and_step();
-   BodyPtr->ref_faces(face_list);
-   BodyPtr->ref_faces(free_face_list);
-
-
    RefFace *ref_face_ptr;
    RefFace *inter_face_ptr;
 
@@ -4073,7 +5923,7 @@
    }
    else
    {
-     ref_face_ptr = face_list.get_and_step();
+     ref_face_ptr = free_face_list.get_and_step();
    }
 
    ref_face_list.append(ref_face_ptr);
@@ -4142,11 +5992,12 @@
 
   if (reverse && bad_face_list.size())
   {
-//     CubitStatus result = gePtr1->flip_normals(bad_face_list);
-//     if ( result == CUBIT_FAILURE )
-//     {
-        return CUBIT_FAILURE;
-//    }
+     //CubitStatus result = gePtr1->flip_normals(bad_face_list);
+     CubitStatus result = GeometryModifyTool::instance()->reverse(bad_face_list);
+     if ( result == CUBIT_FAILURE )
+     {
+       return CUBIT_FAILURE;
+    }
   }
   else if(!bad_face_list.size())
   {
@@ -4157,10 +6008,10 @@
 
 
 
-CubitStatus GeometryModifyTool::subtract ( Body* tool_body, DLIList<Body*> &from_bodies,
-                                           DLIList<Body*> &new_bodies,
-                                           bool imprint,
-                                           bool keep_old )
+CubitStatus GeometryModifyTool::subtract( Body* tool_body, DLIList<Body*> &from_bodies,
+                                          DLIList<Body*> &new_bodies,
+                                          bool imprint,
+                                          bool keep_old )
 {
   DLIList<Body*> temp_body_list;
   temp_body_list.append(tool_body);
@@ -4206,83 +6057,255 @@
       return CUBIT_FAILURE;
    }
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old )
+       CubitUndo::save_state();
+     else
+     {
+       //Get all the bodies associated with the vertex
+       DLIList<Body*> bodies;
+       bodies += tool_body_list;
+       bodies += from_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies );
+     }
+   }
+
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   if( keep_old == CUBIT_FALSE )
+     get_merged_curve_and_surface_ids( from_bodies, merged_surface_ids, merged_curve_ids );
+
      // Do the subtract operation
    DLIList<BodySM*> new_sms;
    CubitStatus result = gme->subtract(tool_sms, from_sms, new_sms, imprint, keep_old );
 
-   if (!finish_sm_op(tem_bodies, new_sms, new_bodies))
-      result = CUBIT_FAILURE;
+   if( CubitUndo::get_undo_enabled() && result == CUBIT_FAILURE )
+     CubitUndo::remove_last_undo();
 
+   result = finish_sm_op(tem_bodies, new_sms, new_bodies);
+
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( result == CUBIT_SUCCESS )
+       CubitUndo::note_result_bodies( new_bodies );
+     else
+       CubitUndo::remove_last_undo();
+   }
+
    if ( result == CUBIT_FAILURE )
    {
      PRINT_ERROR("Subtract FAILED\n" );
      return CUBIT_FAILURE;
    }
 
+   if( keep_old == CUBIT_FALSE )
+     fixup_merged_entities( merged_surface_ids, merged_curve_ids);
+
    return CUBIT_SUCCESS;
 }
 
+CubitStatus GeometryModifyTool::intersect( DLIList<Body*> &from_bodies,
+                                           DLIList<Body*> &new_bodies,
+                                           bool keep_old )
+{
+  DLIList<Body*> tem_bodies = from_bodies;
+  if (!okay_to_modify( tem_bodies, "INTERSECT" ))
+    return CUBIT_FAILURE;
 
-CubitStatus GeometryModifyTool::intersect ( Body *tool_body_ptr,
-                                            DLIList<Body*> &from_bodies,
-                                            DLIList<Body*> &new_bodies,
-                                            bool keep_old )
+  DLIList<BodySM*> from_sm_list(tem_bodies.size());
+  GeometryModifyEngine* engine = common_modify_engine(tem_bodies, from_sm_list);
+  if ( NULL == engine )
+  {
+    PRINT_ERROR("Performing INTERSECTION with volumes containing geometry\n"
+                "from different modeling engines is not allowed.\n"
+                "Delete uncommon geometry on these volumes before operation.\n\n");
+    return CUBIT_FAILURE;
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( from_bodies );
+  }
+
+  DLIList<int> merged_surface_ids;
+  DLIList<int> merged_curve_ids;
+  if( keep_old == CUBIT_FALSE )
+    get_merged_curve_and_surface_ids( from_bodies, merged_surface_ids, merged_curve_ids );
+
+  GeometryModifyEngine* gme_ptr = get_engine(from_sm_list.get());
+  GeometryQueryEngine* gqe_ptr = gme_ptr->get_gqe();
+
+  DLIList<BodySM*> all_new_bodysms;
+  int i,j;
+  for( i=0; i<from_sm_list.size(); i++ )
+  {
+    from_sm_list.reset();
+    from_sm_list.step(i);
+    BodySM *body1 = from_sm_list.get_and_step();
+
+    for(j=i+1; j<from_sm_list.size(); j++ )
+    {
+      BodySM *body2 = from_sm_list.get_and_step();
+
+      if( body1 == body2 )
+        continue;
+
+      //copy the bodies
+      BodySM *body1_copy = gme_ptr->copy_body( body1 );
+      BodySM *body2_copy = gme_ptr->copy_body( body2 );
+
+      DLIList<BodySM*> tmp_sm_list(1);
+      tmp_sm_list.append( body2_copy );
+      DLIList<BodySM*> new_sms;
+
+      CubitStatus result =
+          engine->intersect(body1_copy, tmp_sm_list, new_sms, true );
+
+      //delete the copies
+      gqe_ptr->delete_solid_model_entities( body1_copy );
+      gqe_ptr->delete_solid_model_entities( body2_copy );
+
+      if ( result == CUBIT_FAILURE || new_sms.size() == 0 )
+      {
+        RefEntity* ref_ent1 = dynamic_cast<RefEntity*>(body1->topology_entity());
+        RefEntity* ref_ent2 = dynamic_cast<RefEntity*>(body2->topology_entity());
+
+        PRINT_WARNING("INTERSECTION of %s with %s failed\n",
+          ref_ent1->entity_name().c_str(),
+          ref_ent2->entity_name().c_str() );
+        continue;
+
+      }
+
+      all_new_bodysms += new_sms;
+    }
+  }
+
+  //now make all the RefEntities
+  all_new_bodysms.reset();
+  for( i=all_new_bodysms.size(); i--; )
+  {
+    Body *new_body = GeometryQueryTool::instance()->make_Body(all_new_bodysms.get_and_step());
+    if( new_body )
+      new_bodies.append( new_body );
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( all_new_bodysms.size() )
+      CubitUndo::note_result_bodies( new_bodies );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  if( keep_old == CUBIT_FALSE )
+    fixup_merged_entities( merged_surface_ids, merged_curve_ids);
+
+  return CUBIT_SUCCESS;
+}
+
+
+
+CubitStatus GeometryModifyTool::intersect( Body *tool_body_ptr,
+                                           DLIList<Body*> &from_bodies,
+                                           DLIList<Body*> &new_bodies,
+                                           bool keep_old )
 {
-   if(tool_body_ptr == NULL )
-       return CUBIT_FAILURE;
-   if(from_bodies.size() == 0 || from_bodies.get() == NULL )
-       return CUBIT_FAILURE;
+  if(tool_body_ptr == NULL )
+    return CUBIT_FAILURE;
+  if(from_bodies.size() == 0 || from_bodies.get() == NULL )
+    return CUBIT_FAILURE;
 
-   DLIList<Body*> tem_bodies = from_bodies;
-   tem_bodies.append( tool_body_ptr );
-   if (!okay_to_modify( tem_bodies, "INTERSECT" ))
-     return CUBIT_FAILURE;
+  DLIList<Body*> tem_bodies = from_bodies;
+  tem_bodies.append( tool_body_ptr );
+  if (!okay_to_modify( tem_bodies, "INTERSECT" ))
+    return CUBIT_FAILURE;
 
-   DLIList<BodySM*> from_sm_list(tem_bodies.size());
-   GeometryModifyEngine* engine = common_modify_engine(tem_bodies, from_sm_list);
-   if ( NULL == engine )
-   {
-      PRINT_ERROR("Performing INTERSECTION with volumes containing geometry\n"
-                  "from different modeling engines is not allowed.\n"
-                  "Delete uncommon geometry on these volumes before operation.\n\n");
-      return CUBIT_FAILURE;
-   }
+  DLIList<BodySM*> from_sm_list(tem_bodies.size());
+  GeometryModifyEngine* engine = common_modify_engine(tem_bodies, from_sm_list);
+  if ( NULL == engine )
+  {
+    PRINT_ERROR("Performing INTERSECTION with volumes containing geometry\n"
+                "from different modeling engines is not allowed.\n"
+                "Delete uncommon geometry on these volumes before operation.\n\n");
+    return CUBIT_FAILURE;
+  }
 
-   BodySM* tool_sm = from_sm_list.pop();
+  BodySM* tool_sm = from_sm_list.pop();
 
 
-   //cannot intersect tool with itself
-   from_sm_list.remove_all_with_value( tool_sm );
-   if( from_sm_list.size() == 0 )
-   {
-     PRINT_ERROR("Cannot intersect volume %d from itself\n",
-                  tool_body_ptr->ref_volume()->id() );
-     return CUBIT_FAILURE;
-   }
+  //cannot intersect tool with itself
+  from_sm_list.remove_all_with_value( tool_sm );
+  if( from_sm_list.size() == 0 )
+  {
+    PRINT_ERROR("Cannot intersect volume %d from itself\n",
+                 tool_body_ptr->ref_volume()->id() );
+    return CUBIT_FAILURE;
+  }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+    {
+      DLIList<Body*> bodies;
+      bodies.append( tool_body_ptr );
+      bodies += from_bodies;
+      CubitUndo::save_state_with_cubit_file( bodies );
+    }
+  }
+
+  DLIList<int> merged_surface_ids;
+  DLIList<int> merged_curve_ids;
+  if( keep_old == CUBIT_FALSE )
+    get_merged_curve_and_surface_ids( from_bodies, merged_surface_ids, merged_curve_ids );
+
      // Do the intersect operation
-   DLIList<BodySM*> new_sms;
-   CubitStatus result =
-       engine->intersect(tool_sm, from_sm_list, new_sms, keep_old );
-   if(!finish_sm_op(tem_bodies, new_sms, new_bodies))
-      result = CUBIT_FAILURE;
+  DLIList<BodySM*> new_sms;
+  CubitStatus result =
+      engine->intersect(tool_sm, from_sm_list, new_sms, keep_old );
+  result = finish_sm_op(tem_bodies, new_sms, new_bodies);
 
-   if ( result == CUBIT_FAILURE )
-   {
-     PRINT_ERROR("Intersect FAILED\n" );
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( result == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( new_bodies );
+    else
+      CubitUndo::remove_last_undo();
+  }
 
-      return CUBIT_FAILURE;
-   }
+  if ( result == CUBIT_FAILURE )
+  {
+    PRINT_ERROR("Intersect FAILED\n" );
+    return CUBIT_FAILURE;
+  }
 
-   return CUBIT_SUCCESS;
+  if( keep_old == CUBIT_FALSE )
+    fixup_merged_entities( merged_surface_ids, merged_curve_ids);
+
+  return CUBIT_SUCCESS;
 }
 
 CubitStatus GeometryModifyTool::imprint( DLIList<Body*> &from_body_list,
                                          DLIList<Body*> &new_body_list,
                                          CubitBoolean keep_old )
 {
+  if( from_body_list.size() == 1 )
+  {
+    PRINT_WARNING("Need more than 1 body or volume to imprint.\n");
+    return CUBIT_FAILURE;
+  }
+
    if (get_group_imprint() == CUBIT_FALSE)
-     return imprint_singly( from_body_list, new_body_list, keep_old );
+   {
+     CubitStatus result = imprint_singly( from_body_list, new_body_list, keep_old );
+     return result;
+   }
 
      // Check the GeometryEngine for each of the Body's; check to
      // make sure they're all the same
@@ -4304,9 +6327,13 @@
       return CUBIT_FAILURE;
    }
 
-#ifdef BOYD17
-   DLIList<Body*> dummy_body_list;
-#endif
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old )
+       CubitUndo::save_state();
+     else
+       CubitUndo::save_state_with_cubit_file( from_body_list );
+   }
 
    int process_composites = 0;
    if(contains_composites(from_body_list))
@@ -4319,7 +6346,10 @@
       do_attribute_setup();
       push_vg_attributes_before_modify(from_sms);
       // This must be done after pushing the vg atts because it uses them.
-      push_imprint_attributes_before_modify(from_sms);
+      DLIList<TopologyBridge*> tb_list;
+      CAST_LIST(from_sms, tb_list, TopologyBridge);
+      push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
+      push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
    }
 
    DLIList<TopologyBridge*> new_tbs, att_tbs;
@@ -4329,15 +6359,21 @@
    int i, j;
    if(process_composites)
    {
-      // Analyze the results and adjust virtual attributes as necessary.
-      GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
-        new_sms, from_body_list);
+     if(result == CUBIT_SUCCESS)
+     {
+        // Analyze the results and adjust virtual attributes as necessary.
+       DLIList<TopologyBridge*> tb_list;
+       CAST_LIST(new_sms, tb_list, TopologyBridge);
+        GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+          tb_list, from_body_list);
 
-      // Clean up attributes.
-      remove_imprint_attributes_after_modify(from_sms, new_sms);
+        // Clean up attributes.
+        remove_imprint_attributes_after_modify(from_sms, new_sms);
 
-      // Restore the virtual geometry.
-      restore_vg_after_modify(new_sms, from_body_list);
+        // Restore the virtual geometry.
+        restore_vg_after_modify(new_sms, from_body_list, gePtr1);
+     }
+     remove_pushed_attributes(new_sms, from_body_list);
    }
 
    if (get_old_names() == CUBIT_FALSE)
@@ -4345,6 +6381,14 @@
      if (!finish_sm_op(from_body_list, new_sms, new_body_list))
        result = CUBIT_FAILURE;
 
+     if( CubitUndo::get_undo_enabled() )
+     {
+       if( result == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_body_list );
+       else
+         CubitUndo::remove_last_undo();
+     }
+
      if(process_composites)
        do_attribute_cleanup();
 
@@ -4387,16 +6431,55 @@
    }
    GeometryQueryTool::instance()->cleanout_deactivated_geometry();
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( result == CUBIT_SUCCESS )
+       CubitUndo::note_result_bodies( new_body_list );
+     else
+       CubitUndo::remove_last_undo();
+   }
+
    return result;
 }
 
 CubitStatus GeometryModifyTool::scale( Body *&body,
-                                       const CubitVector& factors, bool check_to_transform )
+                                       const CubitVector& factors,
+                                       bool check_to_transform,
+                                       bool preview /*=false*/)
 {
   if( check_to_transform )
     if (!GeometryQueryTool::instance()->okay_to_transform( body ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    GfxPreview::clear();
+    DLIList<RefEdge*> edges;
+    body->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV.x(tempV.x()*factors.x());
+        tempV.y(tempV.y()*factors.y());
+        tempV.z(tempV.z()*factors.z());
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   BodySM* bodysm = body->get_body_sm_ptr();
   GeometryModifyEngine* engine = get_engine( bodysm );
   CubitStatus result;
@@ -4445,9 +6528,6 @@
      //between the two lists.
    from_body_list.uniquify_ordered();
 
-#ifdef BOYD17
-   DLIList<BodySM*> from_sms(from_body_list.size()), new_sms;
-#endif
    DLIList<BodySM*> from_sms(from_body_list.size());
    GeometryModifyEngine* gePtr1 = common_modify_engine(from_body_list, from_sms);
    if ( !gePtr1 )
@@ -4471,6 +6551,14 @@
    new_body_list = from_body_list;
    GeometryQueryTool* gqt = GeometryQueryTool::instance();
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old )
+       CubitUndo::save_state();
+     else
+       CubitUndo::save_state_with_cubit_file( from_body_list );
+   }
+
    int i;
    for (i = 0; i < new_body_list.size(); i++) {
      for (int j = 1; j < new_body_list.size()-i; j++) {
@@ -4539,6 +6627,15 @@
      temp_body = from_body_list.get_and_step();
      while (new_body_list.move_to(temp_body)) new_body_list.remove();
    }
+
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( new_body_list.size() )
+       CubitUndo::note_result_bodies( new_body_list );
+     else
+       CubitUndo::remove_last_undo();
+   }
+
    PRINT_INFO("\n");
    if( DEBUG_FLAG( 153 ) )
    {
@@ -4594,7 +6691,6 @@
    }
    PRINT_INFO("\n");
 
-
    if (reset_new_ids) set_new_ids(CUBIT_FALSE);
 
    return CUBIT_SUCCESS;
@@ -4607,44 +6703,133 @@
                                          CubitBoolean keep_old_body,
                                          CubitBoolean show_messages)
 {
-   // Check the GeometryEngine for each of the bodies; check to
-   // make sure they're all the same
-   body_list.reset();
-   int i;
+  // Check the GeometryEngine for each of the bodies; check to
+  // make sure they're all the same
+  body_list.reset();
+  int i;
 
-   if (!okay_to_modify( body_list, "IMPRINT" ))
-     return CUBIT_FAILURE;
+  if (!okay_to_modify( body_list, "IMPRINT" ))
+    return CUBIT_FAILURE;
 
-   const int count = body_list.size() + ref_edge_list.size();
-   DLIList<TopologyEntity*> entity_list(count);
-   DLIList<TopologyBridge*> bridge_list(count);
-   CAST_LIST_TO_PARENT(body_list, entity_list);
-   ref_edge_list.reset();
-   for (i = ref_edge_list.size(); i--;)
-     entity_list.append(ref_edge_list.get_and_step());
+  const int count = body_list.size() + ref_edge_list.size();
+  DLIList<TopologyEntity*> entity_list(count);
+  DLIList<TopologyBridge*> bridge_list(count);
+  CAST_LIST_TO_PARENT(body_list, entity_list);
+  ref_edge_list.reset();
+  for (i = ref_edge_list.size(); i--;)
+    entity_list.append(ref_edge_list.get_and_step());
 
-   GeometryModifyEngine* gePtr1 = common_modify_engine(entity_list, bridge_list);
-   DLIList<BodySM*> body_sm_list(body_list.size());
-   DLIList<Curve*> curve_list(ref_edge_list.size());
-   CAST_LIST(bridge_list, body_sm_list, BodySM);
-   CAST_LIST(bridge_list, curve_list, Curve);
+  GeometryModifyEngine* gePtr1 = common_modify_engine(entity_list, bridge_list);
 
-   if ( !gePtr1 ||
-        body_sm_list.size() != body_list.size() ||
-        curve_list.size() != ref_edge_list.size() )
+  DLIList<BodySM*> body_sm_list(body_list.size());
+  DLIList<Curve*> curve_list(ref_edge_list.size());
+  CAST_LIST(bridge_list, body_sm_list, BodySM);
+  CAST_LIST(bridge_list, curve_list, Curve);
+
+  if ( !gePtr1 ||
+      body_sm_list.size() != body_list.size() ||
+      curve_list.size() != ref_edge_list.size() )
+  {
+    PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
+                "different modeling engines is not allowed.\n"
+                "Delete uncommon geometry on these volumes before operation.\n\n");
+    return CUBIT_FAILURE;
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( body_list );
+  }
+
+  int process_composites = 0;
+  if(contains_composites(body_list))
+    process_composites = 1;
+
+  if(process_composites)
+  {
+    // Turn certain attributes on.
+    do_attribute_setup();
+    // Push virtual attributes down to solid model topology before
+    // doing the imprint.
+    push_vg_attributes_before_modify(body_sm_list);
+    // Put "ORIGINAL" attributes on the bodies being imprinted and
+    // the curves as these originally existed.
+    DLIList<TopologyBridge*> tb_list;
+    CAST_LIST(body_sm_list, tb_list, TopologyBridge);
+    push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
+    tb_list.clean_out();
+    CAST_LIST(curve_list, tb_list, TopologyBridge);
+    push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
+  }
+
+  DLIList<BodySM*> new_sm_list;
+  // The bridges doing the imprinting often get split during the process but
+  // because of the way we are making copies, the IMPRINTER attribute doesn't
+  // get propagated to them.  temporary_bridges will be filled in with any
+  // additional IMPRINTER bridges we need to consider below when deciding whether to
+  // keep composite attributes.
+  DLIList<TopologyBridge*> temporary_bridges;
+  CubitStatus status = gePtr1->imprint( body_sm_list, curve_list,
+            new_sm_list, temporary_bridges, keep_old_body, show_messages);
+
+  temporary_bridges.uniquify_ordered();
+
+  if(status == CUBIT_FAILURE)
+  {
+    if(process_composites)
+    {
+      remove_pushed_attributes(new_sm_list, body_list);
+      do_attribute_cleanup();
+    }
+
+    while(temporary_bridges.size())
+      delete temporary_bridges.pop();
+
+    return status;
+  }
+  else
+  {
+    if(process_composites)
+    {
+      DLIList<TopologyBridge*> tb_list, new_tbs, att_tbs;
+      // Analyze the results and adjust virtual attributes as necessary.
+      CAST_LIST(new_sm_list, tb_list, TopologyBridge);
+      // The bridges coming back in temporary_bridges may not have IMPRINTER
+      // attributes on them becuase of the way they were generated below.  Make
+      // sure they get IMPRINTER attributes.
+      push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
+      tb_list += temporary_bridges;
+      GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+                                                                    tb_list, body_list);
+
+      // Clean up attributes.
+      remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
+
+      // Restore the virtual geometry.
+      restore_vg_after_modify(new_sm_list, body_list, gePtr1);
+      remove_pushed_attributes(new_sm_list, body_list);
+    }
+  }
+
+  while(temporary_bridges.size())
+    delete temporary_bridges.pop();
+
+   status = finish_sm_op(body_list, new_sm_list, new_body_list);
+
+  if(process_composites)
+    do_attribute_cleanup();
+
+   if( CubitUndo::get_undo_enabled() )
    {
-      PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
-                  "different modeling engines is not allowed.\n"
-                  "Delete uncommon geometry on these volumes before operation.\n\n");
-      return CUBIT_FAILURE;
+     if( status == CUBIT_SUCCESS )
+       CubitUndo::note_result_bodies( new_body_list );
+     else
+       CubitUndo::remove_last_undo();
    }
 
-   DLIList<BodySM*> new_sm_list;
-   CubitStatus status = gePtr1->imprint( body_sm_list, curve_list,
-                                         new_sm_list, keep_old_body, show_messages );
-   if (!finish_sm_op(body_list, new_sm_list, new_body_list))
-     status = CUBIT_FAILURE;
-
    return status;
 }
 
@@ -4654,68 +6839,139 @@
                                          CubitBoolean keep_old_body )
 {
   //get the owning bodies of the faces and edges
-    DLIList<Body*> body_list;
-    int j;
-    for(j=ref_face_list.size(); j--;)
-      ref_face_list.get_and_step()->bodies( body_list );
-    for(j=ref_edge_list.size(); j--;)
-      ref_edge_list.get_and_step()->bodies( body_list );
-    body_list.uniquify_unordered();
-   if (!okay_to_modify( body_list, "IMPRINT" ))
-     return CUBIT_FAILURE;
+  DLIList<Body*> body_list;
+  int j;
+  for(j=ref_face_list.size(); j--;)
+    ref_face_list.get_and_step()->bodies( body_list );
+  for(j=ref_edge_list.size(); j--;)
+    ref_edge_list.get_and_step()->bodies( body_list );
+  body_list.uniquify_unordered();
+  if (!okay_to_modify( body_list, "IMPRINT" ))
+    return CUBIT_FAILURE;
 
-   DLIList<ModelEntity*> temp_list, temp_list_2, body_me_list;
-   CAST_LIST_TO_PARENT(ref_face_list, temp_list);
-   CAST_LIST_TO_PARENT(ref_edge_list, temp_list_2);
-   temp_list += temp_list_2;
-   ModelQueryEngine::instance()->query_model(
-    temp_list, DagType::body_type(), body_me_list );
+  DLIList<ModelEntity*> temp_list, temp_list_2, body_me_list;
+  CAST_LIST_TO_PARENT(ref_face_list, temp_list);
+  CAST_LIST_TO_PARENT(ref_edge_list, temp_list_2);
+  temp_list += temp_list_2;
+  ModelQueryEngine::instance()->query_model(temp_list, DagType::body_type(), body_me_list );
 
-   DLIList<Surface*> surf_list(ref_face_list.size());
-   DLIList<Curve*> curve_list(ref_edge_list.size());
-   GeometryModifyEngine* gePtr1 = common_modify_engine( ref_face_list,
-                                                        ref_edge_list,
-                                                        surf_list,
-                                                        curve_list );
+  DLIList<Surface*> surf_list(ref_face_list.size());
+  DLIList<Curve*> curve_list(ref_edge_list.size());
+  GeometryModifyEngine* gePtr1 = common_modify_engine( ref_face_list,ref_edge_list,surf_list,
+                             curve_list,true);
+  if ( !gePtr1 )
+  {
+    PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
+            "different modeling engines is not allowed.\n"
+            "Delete uncommon geometry on these volumes before operation.\n\n");
+    return CUBIT_FAILURE;
+  }
 
-   if ( !gePtr1 )
-     {
-        PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
-                    "different modeling engines is not allowed.\n"
-                    "Delete uncommon geometry on these volumes before operation.\n\n");
-        return CUBIT_FAILURE;
-     }
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_face_list );
+  }
 
-   body_list.clean_out();
-   CAST_LIST(body_me_list, body_list, Body);
-   DLIList<BodySM*> new_sm_list;
+  int process_composites = 0;
+  if(contains_composites(body_list))
+    process_composites = 1;
 
-   CubitStatus status = gePtr1->imprint( surf_list, curve_list,
+  int i;
+  DLIList<BodySM*> body_sm_list;
+  if(process_composites)
+  {
+    // Turn certain attributes on.
+    do_attribute_setup();
+    for(i=body_list.size(); i--;)
+      body_sm_list.append_unique(body_list.get_and_step()->get_body_sm_ptr());
+    // Push virtual attributes down to solid model topology before
+    // doing the imprint.
+    push_vg_attributes_before_modify(body_sm_list);
+    // Put "ORIGINAL" attributes on the bodies being imprinted and
+    // the curves as these originally existed.
+    DLIList<TopologyBridge*> tmp_tb_list;
+    CAST_LIST(surf_list, tmp_tb_list, TopologyBridge);
+    push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
+  }
+
+  DLIList<BodySM*> new_sm_list;
+  // The bridges doing the imprinting often get split during the process but
+  // because of the way we are making copies, the IMPRINTER attribute doesn't
+  // get propagated to them.  temporary_bridges will be filled in with any
+  // additional IMPRINTER bridges we need to consider below when deciding whether to
+  // keep composite attributes.
+  DLIList<TopologyBridge*> temporary_bridges;
+  CubitStatus status = gePtr1->imprint( surf_list, curve_list, temporary_bridges,
                                          new_sm_list, keep_old_body );
-   if (!finish_sm_op(body_list, new_sm_list, new_body_list))
-     status = CUBIT_FAILURE;
+  temporary_bridges.uniquify_ordered();
 
-   body_list.reset();
-   for (int i = body_list.size(); i--; )
+  if(process_composites)
+  {
+    // Analyze the results and adjust virtual attributes as necessary.
+    DLIList<TopologyBridge*> tb_list;
+    CAST_LIST(new_sm_list, tb_list, TopologyBridge);
+    // The bridges coming back in temporary_bridges may not have IMPRINTER
+    // attributes on them becuase of the way they were generated below.  Make
+    // sure they get IMPRINTER attributes.
+    push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
+    tb_list += temporary_bridges;
+    DLIList<TopologyBridge*> new_tbs, att_tbs;
+    GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+                    tb_list, body_list);
+
+    // Clean up attributes.
+    remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
+
+    restore_vg_after_modify(body_sm_list, body_list, gePtr1);
+    remove_pushed_attributes(body_sm_list, body_list);
+  }
+
+  while(temporary_bridges.size())
+    delete temporary_bridges.pop();
+
+   status = finish_sm_op(body_list, new_sm_list, new_body_list);
+
+  if(process_composites)
+    do_attribute_cleanup();
+
+  if( CubitUndo::get_undo_enabled() )
    {
-     Body* body = body_list.get_and_step();
-     BodySM* bodysm = body->get_body_sm_ptr();
-     assert(!!bodysm);
-     GeometryQueryTool::instance()->make_Body(bodysm);
+     if( status == CUBIT_SUCCESS )
+       CubitUndo::note_result_bodies( new_body_list );
+     else
+       CubitUndo::remove_last_undo();
    }
-   GeometryQueryTool::instance()->cleanout_deactivated_geometry();
 
    return status;
-
 }
 
 CubitStatus GeometryModifyTool::imprint( DLIList<Surface*> &surface_list,
                                          DLIList<DLIList<Curve*>*> &curve_lists_list,
                                          Body*& /*new_body*/,
-                                         CubitBoolean keep_old_body )
+                                         CubitBoolean keep_old_body,
+                                         CubitBoolean expand)
 {
+  int i;
+  DLIList<Curve*> *curve_list_ptr;
+
+  // Check to see if any curves exist - if none, just exit
+  int have_curves = 0;
+  for( i=curve_lists_list.size(); i--; )
+  {
+    curve_list_ptr = curve_lists_list.get_and_step();
+    if( curve_list_ptr->size() )
+    {
+      have_curves++;
+      break;
+    }
+  }
+  if( !have_curves )
+    return CUBIT_SUCCESS;
+
   // Get parent bodies
-  int i;
   DLIList<Body*> old_body_list;
   surface_list.reset();
   for( i=surface_list.size(); i--; )
@@ -4741,13 +6997,35 @@
     return CUBIT_FAILURE;
   }
 
+
+  // In order to support imprinting on composite surfaces we will
+  // get any surfaces underlying the surfaces passed in.  For now
+  // we will only do this if a single surface is coming in but
+  // it could be extended for multiple surfaces as well.
+  DLIList<Surface*> new_surface_list;
+  if(surface_list.size() == 1)
+  {
+    GeometryQueryEngine *gqe = surface_list.get()->get_geometry_query_engine();
+    DLIList<TopologyBridge*> tbs;
+    gqe->get_underlying_surfaces(surface_list.get(), tbs);
+    if(tbs.size() > 0)
+    {
+      for(int k=tbs.size(); k--;)
+        new_surface_list.append(dynamic_cast<Surface*>(tbs.get_and_step()));
+    }
+    else
+      new_surface_list.append(surface_list.get());
+  }
+  else
+    new_surface_list = surface_list;
+
   // Check engines - must all be the same
   GeometryModifyEngine* gme;
-  surface_list.reset();
-  gme = get_engine( surface_list.get() );
-  for( i=surface_list.size(); i--; )
+  new_surface_list.reset();
+  gme = get_engine( new_surface_list.get() );
+  for( i=new_surface_list.size(); i--; )
   {
-    Surface *surf_ptr = surface_list.get_and_step();
+    Surface *surf_ptr = new_surface_list.get_and_step();
     GeometryModifyEngine* gme2 = get_engine( surf_ptr );
     if( gme != gme2 )
     {
@@ -4759,7 +7037,7 @@
   int j;
   for( i=curve_lists_list.size(); i--; )
   {
-    DLIList<Curve*> *curve_list_ptr = curve_lists_list.get_and_step();
+    curve_list_ptr = curve_lists_list.get_and_step();
     for( j=curve_list_ptr->size(); j--; )
     {
       Curve *curve_ptr = curve_list_ptr->get_and_step();
@@ -4772,90 +7050,216 @@
     }
   }
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old_body )
+       CubitUndo::save_state();
+     else
+       CubitUndo::save_state_with_cubit_file( old_body_list );
+   }
+
+  int process_composites = 0;
+  if(contains_composites(old_body_list))
+    process_composites = 1;
+
   BodySM* new_body_sm = 0;
+  DLIList<BodySM*> body_sm_list;
 
-  CubitStatus status = gme->imprint( surface_list, curve_lists_list,
-    new_body_sm, keep_old_body );
+  DLIList<TopologyBridge*> tb_list;
+  if(process_composites)
+  {
+    do_attribute_setup();
+    for(i=old_body_list.size(); i--;)
+      body_sm_list.append_unique(old_body_list.get_and_step()->get_body_sm_ptr());
+    push_vg_attributes_before_modify(body_sm_list);
+ //   push_imprint_attributes_before_modify(body_sm_list);
+    DLIList<TopologyBridge*> tmp_tb_list;
+    CAST_LIST(new_surface_list, tmp_tb_list, TopologyBridge);
+    push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
 
+    for(i=curve_lists_list.size(); i>0; i--)
+    {
+      DLIList<Curve*> *cur_list = curve_lists_list.get_and_step();
+      for(j=cur_list->size(); j>0; j--)
+      {
+        Curve *cur_curve = cur_list->get_and_step();
+        tb_list.append(cur_curve);
+      }
+    }
+    push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
+  }
 
+  DLIList<TopologyBridge*> new_tbs, att_tbs;
+  CubitStatus status = gme->imprint( new_surface_list, curve_lists_list,
+    new_body_sm, keep_old_body, expand, &new_tbs, &att_tbs );
+
   DLIList<Body*> new_body_list;
   DLIList<BodySM*> new_sm_list;
   new_sm_list.append( new_body_sm );
 
-  if (!finish_sm_op(old_body_list, new_sm_list, new_body_list))
-    status = CUBIT_FAILURE;
+  if(process_composites)
+  {
+    // Analyze the results and adjust virtual attributes as necessary.
+       DLIList<TopologyBridge*> tmp_tb_list;
+       CAST_LIST(new_sm_list, tmp_tb_list, TopologyBridge);
+       tb_list += tmp_tb_list;
+    GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+                    tb_list, old_body_list);
 
+    // Clean up attributes.
+    remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
+
+    restore_vg_after_modify(body_sm_list, old_body_list, gme);
+    remove_pushed_attributes(body_sm_list, old_body_list);
+  }
+
+  status = finish_sm_op(old_body_list, new_sm_list, new_body_list);
+
+  if(process_composites)
+    do_attribute_cleanup();
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( status == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( new_body_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
   return status;
 }
 
 CubitStatus GeometryModifyTool::imprint( DLIList<Body*> &body_list,
                                          DLIList<CubitVector*> &vector_list,
                                          DLIList<Body*>& new_body_list,
-                                         CubitBoolean keep_old_body )
+                                         CubitBoolean keep_old_body,
+                                         CubitBoolean merge )
 {
-   // Check the GeometryEngine for each of the RefEdges; check to
-   // make sure they're all the same
-   body_list.reset();
+  // Check the GeometryEngine for each of the RefEdges; check to
+  // make sure they're all the same
+  body_list.reset();
 
-   if (!okay_to_modify( body_list, "IMPRINT" ))
-     return CUBIT_FAILURE;
+  if (!okay_to_modify( body_list, "IMPRINT" ))
+    return CUBIT_FAILURE;
 
-   DLIList<BodySM*> body_sm_list(body_list.size()), new_sm_list;
-   GeometryModifyEngine* gePtr1 = common_modify_engine(body_list, body_sm_list);
-   if ( !gePtr1 )
-   {
-      PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
-                  "different modeling engines is not allowed.\n"
-                  "Delete uncommon geometry on these volumes before operation.\n\n");
-      return CUBIT_FAILURE;
-   }
+  DLIList<BodySM*> body_sm_list(body_list.size()), new_sm_list;
+  GeometryModifyEngine* gePtr1 = common_modify_engine(body_list, body_sm_list);
+  if ( !gePtr1 )
+  {
+    PRINT_ERROR("Performing IMPRINT with volumes containing geometry from\n"
+                "different modeling engines is not allowed.\n"
+                "Delete uncommon geometry on these volumes before operation.\n\n");
+    return CUBIT_FAILURE;
+  }
 
-   int process_composites = 0;
-   if(contains_composites(body_list))
-     process_composites = 1;
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( body_list );
+  }
 
-   if(process_composites)
-   {
-      // Push virtual attributes down to solid model topology before
-      // doing the imprint.
-      do_attribute_setup();
-      push_vg_attributes_before_modify(body_sm_list);
-      // This must be done after pushing the vg atts because it uses them.
-      push_imprint_attributes_before_modify(body_sm_list);
-   }
-   DLIList<TopologyBridge*> new_tbs, att_tbs;
+  int process_composites = 0;
+  if(contains_composites(body_list))
+    process_composites = 1;
 
-   CubitStatus status = gePtr1->imprint( body_sm_list, vector_list,
-                                         new_sm_list, keep_old_body, &new_tbs,
-                                            &att_tbs );
+  int i;
+  DLIList<TopologyBridge*> temporary_bridges;
+  if(process_composites)
+  {
+    // Turn certain attributes on.
+    do_attribute_setup();
+    // Push virtual attributes down to solid model topology before
+    // doing the imprint.
+    push_vg_attributes_before_modify(body_sm_list);
+    // Create temporary bridges for the vector positions.  We do
+    // this so that we can put an IMPRINTER attribute on them
+    // and use them later for deciding whether to keep composite
+    // attributes or not.
+    for(i=vector_list.size(); i>0; i--)
+    {
+      CubitVector *vec = vector_list.get_and_step();
+      Point *pt = gePtr1->make_Point(*vec);
+      temporary_bridges.append(pt);
+    }
+    push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
+    DLIList<TopologyBridge*> tmp_tb_list;
+    CAST_LIST(body_sm_list, tmp_tb_list, TopologyBridge);
+    // Put "ORIGINAL" attributes on the bridges that originally existed.
+    push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
+  }
 
-   int i, j;
+  DLIList<TopologyBridge*> new_tbs, att_tbs;
+  CubitStatus status = gePtr1->imprint( body_sm_list, vector_list,new_sm_list,
+    keep_old_body, &new_tbs,&att_tbs );
 
-   if(process_composites)
+  temporary_bridges.uniquify_ordered();
+
+  if(process_composites)
+  {
+    // Analyze the results and adjust virtual attributes as necessary.
+    DLIList<TopologyBridge*> tb_list;
+    CAST_LIST(new_sm_list, tb_list, TopologyBridge);
+    tb_list += temporary_bridges;
+    GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+                      tb_list, body_list);
+
+    while(temporary_bridges.size())
+      delete temporary_bridges.pop();
+
+    // Clean up attributes.
+    remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
+
+    // Restore the virtual geometry.
+    restore_vg_after_modify(new_sm_list, body_list, gePtr1);
+    remove_pushed_attributes(new_sm_list, body_list);
+  }
+
+  status = finish_sm_op(body_list, new_sm_list, new_body_list);
+
+  if(process_composites)
+    do_attribute_cleanup();
+
+   if( merge )
    {
-      // Analyze the results and adjust virtual attributes as necessary.
-      GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
-                      new_sm_list, body_list);
+     DLIList<Body*> bodies_to_merge;
+     int i;
+     for( i=new_body_list.size(); i--; )
+     {
+       Body *tmp_body = new_body_list.get_and_step();
+       DLIList<RefEdge*> ref_edge_list;
+       tmp_body->ref_edges( ref_edge_list );
 
-      // Clean up attributes.
-      remove_imprint_attributes_after_modify(body_sm_list, new_sm_list);
+       int j;
+       for( j=ref_edge_list.size(); j--; )
+       {
+         RefEdge *tmp_edge = ref_edge_list.get_and_step();
+         DLIList<Body*> body_list;
+         tmp_edge->bodies( body_list );
+         bodies_to_merge.merge_unique( body_list );
+       }
+     }
+     MergeTool::instance()->merge_bodies( bodies_to_merge );
+   }
 
-      // Restore the virtual geometry.
-      restore_vg_after_modify(new_sm_list, body_list);
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( status == CUBIT_SUCCESS )
+       CubitUndo::note_result_bodies( new_body_list );
+     else
+       CubitUndo::remove_last_undo();
    }
 
-   if (!finish_sm_op(body_list, new_sm_list, new_body_list))
-     status = CUBIT_FAILURE;
-
-   if(process_composites)
-     do_attribute_cleanup();
-
    return status;
 }
 CubitStatus GeometryModifyTool::project_edges( DLIList<RefFace*> &ref_face_list,
                                                DLIList<RefEdge*> &ref_edge_list_in,
-                                               DLIList<RefEdge*> &ref_edge_list_new)
+                                               DLIList<RefEdge*> &ref_edge_list_new,
+                                               CubitBoolean trim_projected)
 {
+  int i, j;
+  
    // Check the GeometryEngine for each of the RefEdges; check to
    // make sure they're all the same
   DLIList<Surface*> surface_list(ref_face_list.size());
@@ -4874,17 +7278,73 @@
    CubitStatus status = gme->
      project_edges( surface_list, curve_list_in, curve_list_new);
 
+  if( CubitUndo::get_undo_enabled() && status == CUBIT_SUCCESS )
+    CubitUndo::save_state();
+
+
    curve_list_new.reset();
-   for (int i = curve_list_new.size(); i--; )
+   
+   if(trim_projected){
+     DLIList<Curve*> tmp_curves, all_new_curves;
+     Curve* tmp_curve;
+     Surface* tmp_surface;
+     
+     for(i = 0; i< surface_list.size(); i++){
+       tmp_curves.clean_out();
+       tmp_surface = surface_list.get_and_step();
+       for(j=0; j<curve_list_new.size(); j++){
+         tmp_curve = curve_list_new.get_and_step();
+         status = gme->curve_surface_intersection( tmp_surface, tmp_curve, tmp_curves);
+       }
+       all_new_curves += tmp_curves;
+
+     }
+
+     if(!all_new_curves.size()){
+       if(!curve_list_new.size()){
+         PRINT_ERROR("Projection resulted in no curves.\n");
+         return CUBIT_FAILURE;
+       }
+       else{
+         PRINT_WARNING("No curve remained after trimming operation.  \n \tCurve projection may lie completely outside of trimmed surface.\n");
+       }
+     }
+     
+       //fix this...
+       //can we just cleanout this list or do we need to delete the entities in it.
+     for( i = 0; i< curve_list_new.size(); i++ )
+     {
+       Curve *tmp_curve = curve_list_new.get_and_step();
+       gme->get_gqe()->delete_solid_model_entities( tmp_curve );
+     }
+     
+     curve_list_new.clean_out();
+     curve_list_new = all_new_curves;
+     
+     if( CubitUndo::get_undo_enabled() && status == CUBIT_SUCCESS )
+       CubitUndo::save_state();
+   }
+   
+  
+
+   curve_list_new.reset();
+   for (i = curve_list_new.size(); i--; )
    {
      Curve* curve = curve_list_new.get_and_step();
      RefEdge* new_edge = GeometryQueryTool::instance()->make_free_RefEdge(curve);
      PRINT_INFO("Created Curve %d\n", new_edge->id());
      ref_edge_list_new.append(new_edge);
+     if( CubitUndo::get_undo_enabled() && new_edge )
+       CubitUndo::note_result_entity( new_edge );
    }
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( ref_edge_list_new.size() == 0 )
+       CubitUndo::remove_last_undo();
+   }
+
    return status;
-
 }
 
 CubitStatus
@@ -4916,12 +7376,28 @@
    CAST_LIST(query_output, body_list, Body);
    DLIList<BodySM*> new_sm_list;
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( keep_old_body )
+       CubitUndo::save_state();
+     else
+       CubitUndo::save_state_with_cubit_file( ref_face_list );
+   }
+
    CubitStatus status = gme->imprint_projected_edges( surface_list, curve_list,
                                                       new_sm_list, keep_old_body,keep_free_edges);
 
    if (!finish_sm_op(body_list, new_sm_list, new_body_list))
      status = CUBIT_FAILURE;
 
+   if( CubitUndo::get_undo_enabled() )
+   {
+     if( status == CUBIT_FAILURE )
+       CubitUndo::remove_last_undo();
+     else
+       CubitUndo::note_result_bodies( new_body_list );
+   }
+
    return status;
 }
 
@@ -5010,7 +7486,10 @@
 CubitStatus GeometryModifyTool::webcut_with_sheet( DLIList<Body*> &webcut_body_list,
                                                    Body *sheet_body,
                                                    DLIList<Body*> &new_bodies,
-                                                   CubitBoolean imprint )
+                                                   DLIList<Body*> &neighboring_bodies,
+                                                   ImprintType imprint_type,
+                                                   CubitBoolean merge,
+                                                   CubitBoolean preview)
 {
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
      return CUBIT_FAILURE;
@@ -5027,66 +7506,206 @@
       return CUBIT_FAILURE;
    }
    BodySM* tool_sm = body_sm_list.pop();
+ 
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<Body*> bodies_to_modify;
 
-   do_attribute_setup();
+   if (!preview)
+   {
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> bodies_to_save;
+       bodies_to_save += webcut_body_list;
+       bodies_to_save += neighboring_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies_to_save );
+     }
 
-   push_vg_attributes_before_modify(body_sm_list);
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
 
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
+
    CubitStatus stat = gme->webcut_with_sheet (
-       body_sm_list, tool_sm, new_sms, imprint  );
+       body_sm_list, tool_sm, neighbor_imprint_list,
+       new_sms, imprint_type, preview  );
 
-   restore_vg_after_modify(new_sms, original_body_list);
+   if (!preview)
+   {
+     restore_vg_after_modify(new_sms, bodies_to_modify, gme);
+     remove_pushed_attributes(new_sms, bodies_to_modify );
+   }
 
-   stat = finish_webcut( webcut_body_list, new_sms, false, stat, new_bodies );
-    // leave webcut_body_list as we found it -- remove appended tool body
-   webcut_body_list.pop();
+   if( stat == CUBIT_FAILURE )
+   {
+     do_attribute_cleanup();
 
-   do_attribute_cleanup();
+     if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+     {
+       if( stat == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+     return CUBIT_FAILURE;
+   }
 
+   // finish up if not a preview
+   if (!preview)
+   {
+     stat = finish_webcut( webcut_body_list, new_sms, merge, stat, new_bodies,
+                           &merged_surface_ids, &merged_curve_ids );
+      // leave webcut_body_list as we found it -- remove appended tool body
+     webcut_body_list.pop();
+
+     do_attribute_cleanup();
+
+     if( CubitUndo::get_undo_enabled() ) 
+     {
+       if( stat == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+   }
+
+
    return stat;
 }
 //  Calls solid modeling engine to webcut with a sheet body.
-CubitStatus GeometryModifyTool::webcut_with_extended_surf( DLIList<Body*> &webcut_body_list,
-                                                           RefFace *extend_from,
+CubitStatus GeometryModifyTool::webcut_with_extended_sheet( DLIList<Body*> &webcut_body_list,
+                                                           DLIList<RefFace*> &ref_face_list,
                                                            DLIList<Body*> &new_bodies,
+                                                           DLIList<Body*> &neighboring_bodies,
                                                            int &num_cut,
-                                                           CubitBoolean imprint )
+                                                           ImprintType imprint_type,
+                                                           CubitBoolean merge,
+                                                           CubitBoolean preview)
 {
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
      return CUBIT_FAILURE;
 
-   DLIList<Body*> original_body_list = webcut_body_list;
+   DLIList<RefEntity*> ref_entity_list;
+   CAST_LIST( ref_face_list, ref_entity_list, RefEntity );
+   if( !same_modify_engine( ref_entity_list ) )
+   {
+     PRINT_ERROR( "Extending surfaces from different geometry engines is\n"
+       "       not allowed.\n\n" );
+     return CUBIT_FAILURE;
+   }
+
    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
-   Surface* surf_ptr = 0;
-   if (gme) {
-     TopologyBridge* bridge = extend_from->bridge_manager()->topology_bridge(gme->get_gqe());
-     surf_ptr = dynamic_cast<Surface*>(bridge);
+
+   if( !gme )
+   {
+     PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from\n"
+                  "different modeling engines is not allowed.\n"
+                  "Delete uncommon geometry on these volumes before operation.\n\n");
+      return CUBIT_FAILURE;
    }
 
+   Surface* surf_ptr = 0;
+   TopologyBridge* bridge = ref_face_list.get()->bridge_manager()->topology_bridge(gme->get_gqe());
+   surf_ptr = dynamic_cast<Surface*>(bridge);
+   
    if ( !surf_ptr )
    {
-      PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from\n"
-                  "different modeling engines is not allowed.\n"
+      PRINT_ERROR("Performing WEBCUTS on volumes containing geometry from a\n"
+                  "different modeling engine than the extended surfaces is\n"
+                  "not allowed.\n"
                   "Delete uncommon geometry on these volumes before operation.\n\n");
       return CUBIT_FAILURE;
    }
 
-   do_attribute_setup();
+   GeometryQueryEngine *gqe = gme->get_gqe();
 
-   push_vg_attributes_before_modify(body_sm_list);
+   int i;
+   RefFace *ref_face_ptr;
+   DLIList<Surface*> surf_list;
+   for( i=ref_face_list.size(); i--; )
+   {
+     ref_face_ptr = ref_face_list.get_and_step();
+     bridge = ref_face_ptr->bridge_manager()->topology_bridge(gqe);
+     surf_ptr = dynamic_cast<Surface*>(bridge);
+     surf_list.append( surf_ptr );
+   }   
 
-   //change sjs at cat 1/27/04
-   CubitStatus stat = gme->webcut_with_extended_surf ( //gmeList.get()->webcut_with_extended_surf (
-       body_sm_list, surf_ptr, new_sms, num_cut, imprint  );
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<Body*> bodies_to_modify;
 
-   restore_vg_after_modify(new_sms, original_body_list);
+   if (!preview)
+   {
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> bodies_to_save;
+       bodies_to_save += webcut_body_list;
+       bodies_to_save += neighboring_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies_to_save );
+     }
 
-   CubitStatus ret = finish_webcut(webcut_body_list, new_sms, false, stat, new_bodies );
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
 
-   do_attribute_cleanup();
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
 
-   return ret;
+   CubitStatus stat = gme->webcut_with_extended_sheet( body_sm_list,
+     surf_list, neighbor_imprint_list, new_sms, num_cut, imprint_type,
+     preview );
+
+   if (!preview)
+   {
+     restore_vg_after_modify(new_sms, bodies_to_modify, gme);
+     remove_pushed_attributes(new_sms, bodies_to_modify);
+     stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
+                          &merged_surface_ids, &merged_curve_ids );
+     do_attribute_cleanup();
+
+     if( CubitUndo::get_undo_enabled() ) 
+     {
+       if( stat == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+   }
+
+   return stat;
 }
 
 
@@ -5099,14 +7718,15 @@
                             RefFace* stop_surf,
                             bool up_to_next,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint,
-                            CubitBoolean merge )
+                            DLIList<Body*> &neighboring_bodies,
+                            ImprintType imprint_type,
+                            CubitBoolean merge,
+                            CubitBoolean preview)
 {
 
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
      return CUBIT_FAILURE;
 
-   DLIList<Body*> original_body_list = webcut_body_list;
    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
    DLIList<Surface*> surfaces_to_sweep;
@@ -5130,22 +7750,67 @@
      }
 
      stop_surface = stop_surf->get_surface_ptr();
-   }
+   } 
 
-   do_attribute_setup();
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<Body*> bodies_to_modify;
 
-   push_vg_attributes_before_modify(body_sm_list);
+   if (!preview)
+   {
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> bodies_to_save;
+       bodies_to_save += webcut_body_list;
+       bodies_to_save += neighboring_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies_to_save );
+     }
 
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
+
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
+
    CubitStatus stat = gme->webcut_with_sweep_surfaces_rotated(
        body_sm_list, surfaces_to_sweep, point, sweep_axis, angle,
-       stop_surface, up_to_next, new_sms, imprint );
+       stop_surface, up_to_next, neighbor_imprint_list,
+       new_sms, imprint_type, preview );
 
-   restore_vg_after_modify(new_sms, original_body_list);
+   // if not previewing do the rest of the creation
+   if (!preview)
+   {
+     restore_vg_after_modify(new_sms, bodies_to_modify, gme);
+     remove_pushed_attributes(new_sms, bodies_to_modify);
+     stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
+                          &merged_surface_ids, &merged_curve_ids );
+     do_attribute_cleanup();
 
-   stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies );
+     if( CubitUndo::get_undo_enabled() ) 
+     {
+       if( stat == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+   }
 
-   do_attribute_cleanup();
-
    return stat;
 }
 
@@ -5157,14 +7822,15 @@
                             double angle,
                             RefFace* stop_surf,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint,
-                            CubitBoolean merge )
+                            DLIList<Body*> &neighboring_bodies,
+                            ImprintType imprint_type,
+                            CubitBoolean merge,
+                            CubitBoolean preview)
 {
 
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
      return CUBIT_FAILURE;
 
-   DLIList<Body*> original_body_list = webcut_body_list;
    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
    DLIList<Curve*> curves_to_sweep;
@@ -5193,19 +7859,65 @@
      stop_surface = stop_surf->get_surface_ptr();
    }
 
-   do_attribute_setup();
-   push_vg_attributes_before_modify(body_sm_list);
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<Body*> bodies_to_modify;
 
+   if (!preview)
+   {
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> bodies_to_save;
+       bodies_to_save += webcut_body_list;
+       bodies_to_save += neighboring_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies_to_save );
+     }
+
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
+
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
+
+
    CubitStatus stat = gme->webcut_with_sweep_curves_rotated(
        body_sm_list, curves_to_sweep, point, sweep_axis, angle,
-       stop_surface, new_sms, imprint);
+       stop_surface, neighbor_imprint_list,
+       new_sms, imprint_type, preview);
 
-   restore_vg_after_modify(new_sms, original_body_list);
+   if (!preview)
+   {
+     restore_vg_after_modify(new_sms, bodies_to_modify, gme);
+     remove_pushed_attributes(new_sms, bodies_to_modify);
+     stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
+                          &merged_surface_ids, &merged_curve_ids );
+     do_attribute_cleanup();
 
-   stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies );
+     if( CubitUndo::get_undo_enabled() ) 
+     {
+       if( stat == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+   }
 
-   do_attribute_cleanup();
-
    return stat;
 }
 
@@ -5217,13 +7929,14 @@
                             RefFace *stop_surf,
                             RefEdge* edge_to_sweep_along,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint,
-                            CubitBoolean merge )
+                            DLIList<Body*> &neighboring_bodies,
+                            ImprintType imprint_type,
+                            CubitBoolean merge,
+                            CubitBoolean preview)
 {
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
      return CUBIT_FAILURE;
 
-   DLIList<Body*> original_body_list = webcut_body_list;
    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
    DLIList<Curve*> curves_to_sweep;
@@ -5273,19 +7986,64 @@
      curve_to_sweep_along = edge_to_sweep_along->get_curve_ptr();
    }
 
-   do_attribute_setup();
-   push_vg_attributes_before_modify(body_sm_list);
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<Body*> bodies_to_modify;
 
+   if (!preview)
+   {
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> bodies_to_save;
+       bodies_to_save += webcut_body_list;
+       bodies_to_save += neighboring_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies_to_save );
+     }
+
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
+
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
+
    CubitStatus stat = gme->webcut_with_sweep_curves(
        body_sm_list, curves_to_sweep, sweep_vector, through_all,
-       stop_surface, curve_to_sweep_along, new_sms, imprint );
+       stop_surface, curve_to_sweep_along, neighbor_imprint_list,
+       new_sms, imprint_type, preview );
 
-   restore_vg_after_modify(new_sms, original_body_list);
+   if (!preview)
+   {
+     restore_vg_after_modify(new_sms, bodies_to_modify, gme);
+     remove_pushed_attributes(new_sms, bodies_to_modify);
+     stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
+                          &merged_surface_ids, &merged_curve_ids );
+     do_attribute_cleanup();
 
-   stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies );
+     if( CubitUndo::get_undo_enabled() ) 
+     {
+       if( stat == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+   }
 
-   do_attribute_cleanup();
-
    return stat;
 }
 
@@ -5300,13 +8058,14 @@
                             RefFace* stop_surf,
                             RefEdge* edge_to_sweep_along,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint,
-                            CubitBoolean merge )
+                            DLIList<Body*> &neighboring_bodies,
+                            ImprintType imprint_type,
+                            CubitBoolean merge,
+                            CubitBoolean preview)
 {
    if (!okay_to_modify( webcut_body_list, "WEBCUT" ))
      return CUBIT_FAILURE;
 
-   DLIList<Body*> original_body_list = webcut_body_list;
    DLIList<BodySM*> body_sm_list(webcut_body_list.size()), new_sms;
    GeometryModifyEngine* gme = common_modify_engine(webcut_body_list, body_sm_list);
    DLIList<Surface*> surfaces_to_sweep;
@@ -5350,25 +8109,125 @@
        return CUBIT_FAILURE;
      }
 
+     //make sure that the curve is not part of the surface(s) being swept
+     DLIList<RefFace*> faces_of_edge;
+     edge_to_sweep_along->ref_faces( faces_of_edge );
+      
+     int kk;
+     for( kk=faces_of_edge.size(); kk--; ) 
+     {
+       if( tool_faces.is_in_list( faces_of_edge.get_and_step() ) )
+       {
+         faces_of_edge.back();
+         PRINT_ERROR("Cannot perform sweep.  Curve %d is in Surface %d\n",
+                      edge_to_sweep_along->id(), faces_of_edge.get()->id() );
+         return CUBIT_FAILURE;
+       }
+     }
+
      curve_to_sweep_along = edge_to_sweep_along->get_curve_ptr();
    }
 
-   do_attribute_setup();
-   push_vg_attributes_before_modify(body_sm_list);
+   DLIList<BodySM*> neighbor_imprint_list;
+   DLIList<int> merged_surface_ids;
+   DLIList<int> merged_curve_ids;
+   DLIList<Body*> bodies_to_modify;
 
+   if (!preview)
+   {
+     if( CubitUndo::get_undo_enabled() )
+     {
+       DLIList<Body*> bodies_to_save;
+       bodies_to_save += webcut_body_list;
+       bodies_to_save += neighboring_bodies;
+       CubitUndo::save_state_with_cubit_file( bodies_to_save );
+     }
+
+     int i;
+     for( i=neighboring_bodies.size(); i--; )
+     {
+       Body *neighbor_body = neighboring_bodies.get_and_step();
+       BodySM *tmp_body = neighbor_body->get_body_sm_ptr(); 
+       GeometryModifyEngine *neighbor_gme = get_engine( tmp_body );
+       
+       if( gme == neighbor_gme )
+         neighbor_imprint_list.append( tmp_body ); 
+     }
+
+     do_attribute_setup();
+     DLIList<BodySM*> bodies_sm_to_modify;
+     bodies_sm_to_modify += body_sm_list;
+     bodies_sm_to_modify += neighbor_imprint_list;
+     push_vg_attributes_before_modify( bodies_sm_to_modify );
+     bodies_to_modify += webcut_body_list;
+     bodies_to_modify += neighboring_bodies;
+     get_merged_curve_and_surface_ids( bodies_to_modify, merged_surface_ids, merged_curve_ids );
+   }
+
    CubitStatus stat = gme->webcut_with_sweep_surfaces(
       body_sm_list, surfaces_to_sweep, sweep_vector, sweep_perp, through_all, outward,
-      up_to_next, stop_surface, curve_to_sweep_along, new_sms, imprint );
+      up_to_next, stop_surface, curve_to_sweep_along, neighbor_imprint_list,
+      new_sms, imprint_type, preview );
 
-   restore_vg_after_modify(new_sms, original_body_list);
+   if (!preview)
+   {
+     restore_vg_after_modify(new_sms, bodies_to_modify, gme);
+     remove_pushed_attributes(new_sms, bodies_to_modify);
+     stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies,
+                          &merged_surface_ids, &merged_curve_ids );
+     do_attribute_cleanup();
 
-   stat = finish_webcut(webcut_body_list, new_sms, merge, stat, new_bodies );
+     if( CubitUndo::get_undo_enabled() ) 
+     {
+       if( stat  == CUBIT_SUCCESS )
+         CubitUndo::note_result_bodies( new_bodies );
+       else
+         CubitUndo::remove_last_undo();
+     }
+   }
 
-   do_attribute_cleanup();
-
    return stat;
 }
 
+CubitStatus GeometryModifyTool::split_free_curve( RefEdge *ref_edge,
+                                                  CubitVector &split_location )
+{
+  TopologyBridge* bridge = 0;
+  GeometryModifyEngine* gme_ptr = get_engine(ref_edge, &bridge);
+  Curve *new_curve = 0, *curve = dynamic_cast<Curve*>(bridge);
+  
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefEdge*> tmp_ents(1);
+    tmp_ents.append( ref_edge );
+    CubitUndo::save_state_with_cubit_file( tmp_ents );
+  }
+
+  DLIList<Curve*> new_curves;
+  gme_ptr->split_free_curve( curve, split_location, new_curves );
+ 
+  if (!new_curves.size())
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
+    return CUBIT_FAILURE;
+  }
+
+  GeometryQueryTool::instance()->delete_RefEdge( ref_edge );
+  
+  int i;
+  for( i=0; i<new_curves.size(); i++ )
+  {
+    Curve *new_curve = new_curves.get_and_step();
+    RefEdge* new_edge = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::note_result_entity( new_edge );
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+
 //-------------------------------------------------------------------------
 // Purpose       : split a multiple volume body into several bodies
 //                 each containing a single volume.
@@ -5382,88 +8241,224 @@
 CubitStatus GeometryModifyTool::split_body( Body *body_ptr,
                                             DLIList<Body*> &new_bodies ) const
 {
-   int i;
-   DLIList<RefVolume*> ref_vols;
-   body_ptr->ref_volumes(ref_vols);
-   if ( ref_vols.size() < 2 )
-   {
-       //no need to split...
-     new_bodies.append(body_ptr);
-     return CUBIT_SUCCESS;
-   }
+  int i;
+  DLIList<RefVolume*> ref_vols;
+  body_ptr->ref_volumes(ref_vols);
+  if ( ref_vols.size() < 2 )
+  {
+    //no need to split...
+    new_bodies.append(body_ptr);
+    return CUBIT_SUCCESS;
+  }
 
-   DLIList<Body*> b_list;
-   b_list.append(body_ptr);
-   if (!okay_to_modify( b_list, "SPLIT" ))
-     return CUBIT_FAILURE;
+  DLIList<Body*> b_list;
+  b_list.append(body_ptr);
+  if (!okay_to_modify( b_list, "SPLIT" ))
+    return CUBIT_FAILURE;
 
-     // Call the owning GeometryModifyEngine to split the body
-     // so that there is one volume per body.
-   BodySM* bodysm_ptr = body_ptr->get_body_sm_ptr();
-   GeometryModifyEngine* engine_ptr = get_engine(bodysm_ptr);
-   if (!engine_ptr) {
-     PRINT_ERROR("There is no modify engine available for this volume."
-                 " Volume cannot be split.\n");
-     return CUBIT_FAILURE;
-   }
+  // Call the owning GeometryModifyEngine to split the body
+  // so that there is one volume per body.
+  BodySM* bodysm_ptr = body_ptr->get_body_sm_ptr();
+  GeometryModifyEngine* engine_ptr = get_engine(bodysm_ptr);
+  if (!engine_ptr) {
+    PRINT_ERROR("There is no modify engine available for this volume."
+      " Volume cannot be split.\n");
+    return CUBIT_FAILURE;
+  }
 
-   DLIList<BodySM*> new_sm_list;
-   CubitStatus stat = engine_ptr->split_body( bodysm_ptr, new_sm_list );
-   if ( new_sm_list.size() == 0 )
-   {
-     PRINT_ERROR("failed in splitting volumes, orginal was lost.\n");
-     GeometryQueryTool::instance()->destroy_dead_entity(body_ptr);
-     return CUBIT_FAILURE;
-   }
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<Body*> bodies(1);
+    bodies.append( body_ptr );
+    CubitUndo::save_state_with_cubit_file( bodies );
+  }
 
-   bodysm_ptr = body_ptr->get_body_sm_ptr();
-   if (bodysm_ptr)
-   {
-     remove_dead_entity_names(body_ptr);
-     body_ptr = GeometryQueryTool::instance()->make_Body(bodysm_ptr);
-   }
-   else
-   {
-     GeometryQueryTool::instance()->destroy_dead_entity(body_ptr);
-   }
+  DLIList<BodySM*> new_sm_list;
+  CubitStatus stat = engine_ptr->split_body( bodysm_ptr, new_sm_list );
+  if ( new_sm_list.size() == 0 )
+  {
+    PRINT_ERROR("failed in splitting volumes, orginal was lost.\n");
+    GeometryQueryTool::instance()->destroy_dead_entity(body_ptr);
+    return CUBIT_FAILURE;
+  }
 
-   new_sm_list.reset();
-   for (i = new_sm_list.size(); i--; )
-   {
-     bodysm_ptr = new_sm_list.get_and_step();
-     Body* body = GeometryQueryTool::instance()->make_Body(bodysm_ptr);
-     new_bodies.append(body);
-   }
+  bodysm_ptr = body_ptr->get_body_sm_ptr();
+  if (bodysm_ptr)
+  {
+    remove_dead_entity_names(body_ptr);
+    body_ptr = GeometryQueryTool::instance()->make_Body(bodysm_ptr);
+  }
+  else
+  {
+    GeometryQueryTool::instance()->destroy_dead_entity(body_ptr);
+  }
 
-   if ( !GeometryModifyTool::instance()->get_new_ids())
-   {
-       //Now reuse the body ids.
-     DLIList<RefVolume*> new_ref_vols;
-     for ( int ii = new_bodies.size(); ii > 0; ii-- )
-     {
-       Body *temp_body = new_bodies.get_and_step();
-       new_ref_vols.clean_out();
-       temp_body->ref_volumes(new_ref_vols);
-       int vol_id = new_ref_vols.get()->id();
-       if ( temp_body->id() != vol_id )
-       {
-           //Check to see if this id is being used by
-           //some other body.
-         if ( RefEntityFactory::instance()->get_body(vol_id) == NULL )
-         {
-           temp_body->set_id(vol_id);
-         }
-           //if it is in use, then we shouldn't mess around with it...
-       }
+  new_sm_list.reset();
+  for (i = new_sm_list.size(); i--; )
+  {
+    bodysm_ptr = new_sm_list.get_and_step();
+    Body* body = GeometryQueryTool::instance()->make_Body(bodysm_ptr);
+    new_bodies.append(body);
+  }
 
-     }
-   }
+  if ( !GeometryModifyTool::instance()->get_new_ids())
+  {
+    //Now reuse the body ids.
+    DLIList<RefVolume*> new_ref_vols;
+    for ( int ii = new_bodies.size(); ii > 0; ii-- )
+    {
+      Body *temp_body = new_bodies.get_and_step();
+      new_ref_vols.clean_out();
+      temp_body->ref_volumes(new_ref_vols);
+      int vol_id = new_ref_vols.get()->id();
+      if ( temp_body->id() != vol_id )
+      {
+        //Check to see if this id is being used by
+        //some other body.
+        if ( RefEntityFactory::instance()->get_body(vol_id) == NULL )
+        {
+          temp_body->set_id(vol_id);
+        }
+        //if it is in use, then we shouldn't mess around with it...
+      }
+    }
+  }
 
-   GeometryQueryTool::instance()->cleanout_deactivated_geometry();
-   return stat;
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_bodies( new_bodies );
+
+  GeometryQueryTool::instance()->cleanout_deactivated_geometry();
+  return stat;
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : Separate surfaces from a sheet body into separate bodies.
+//                 Connected surfaces will remain united but be placed in
+//                 a new body.
+//
+// Special Notes :
+//
+// Creator       : Steve Storm
+//
+// Creation Date : 02/23/2008
+//-------------------------------------------------------------------------
+CubitStatus
+GeometryModifyTool::separate_surfaces( DLIList<RefFace*> &ref_face_list,
+                                       DLIList<Body*> &new_bodies )
+{
+  int i;
+  RefFace *ref_face_ptr;
+
+  for( i=ref_face_list.size(); i--; )
+  {
+    ref_face_ptr = ref_face_list.get();
+
+    // Check for no body
+    DLIList<Body*> body_list;
+    ref_face_ptr->bodies( body_list );
+    if( body_list.size()==0 )
+    {
+      PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
+        "       It cannot be separated.\n", ref_face_ptr->id() );
+      return CUBIT_FAILURE;
+    }
+  }
+
+  // Check for virtual geometry
+  DLIList<RefEntity*> ref_ent_list;
+  CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
+  if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+  {
+    PRINT_ERROR("SEPARATING surfaces containing virtual geometry is not\n"
+      "       allowed. Delete virtual geometry on these surfaces\n"
+      "       before operation.\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Prep for undo
+  DLIList<Body*> body_list;
+  for( i=ref_face_list.size(); i--; )
+    ref_face_list.get_and_step()->bodies( body_list );
+  body_list.uniquify_unordered();
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state_with_cubit_file( body_list );
+
+  // Handle surfaces from different modify engines.  Copy the input list since
+  // we will be pulling RefFaces out of it.
+  DLIList<RefFace*> copied_ref_face_list = ref_face_list;
+
+  // Keep track of errors and success
+  int error_occurred = 0;
+  int successful_case = 0;
+
+  GeometryModifyEngine *gme_ptr;
+  while( copied_ref_face_list.size() )
+  {
+    // Need to send in Surfaces
+    DLIList<Surface*> surface_list;
+    DLIList<RefFace*> gme_face_list;
+
+    gme_ptr = pull_common_surfs( copied_ref_face_list, gme_face_list,
+                                 surface_list );
+    if( !gme_ptr )
+      return CUBIT_FAILURE;
+
+    // Get the owning bodies of the faces...needed for finish_sm_op
+    DLIList<Body*> gme_body_list;
+    for( i=gme_face_list.size(); i--; )
+      gme_face_list.get_and_step()->bodies( gme_body_list );
+    gme_body_list.uniquify_unordered();
+    
+    DLIList<BodySM*> new_sm_list;
+    DLIList<Body*> new_body_list;
+    if( gme_ptr->separate_surfaces( surface_list, new_sm_list ) == CUBIT_FAILURE ||
+        finish_sm_op(gme_body_list, new_sm_list, new_body_list ) == CUBIT_FAILURE )
+    {
+      error_occurred++;
+      continue;
+    }
+
+    new_bodies += new_body_list;
+    successful_case++;
+  }
+
+  if( error_occurred && !successful_case )
+    return CUBIT_FAILURE;
+
+  // Following is copied from split_body - to keep same behavior. When all
+  // surfaces are separated from a given body, separate_surfaces just separates
+  // the body. Without the code below we get new body ids.
+  if ( !GeometryModifyTool::instance()->get_new_ids())
+  {
+    //Now reuse the body ids.
+    DLIList<RefVolume*> new_ref_vols;
+    for ( int ii = new_bodies.size(); ii > 0; ii-- )
+    {
+      Body *temp_body = new_bodies.get_and_step();
+      new_ref_vols.clean_out();
+      temp_body->ref_volumes(new_ref_vols);
+      int vol_id = new_ref_vols.get()->id();
+      if ( temp_body->id() != vol_id )
+      {
+        //Check to see if this id is being used by
+        //some other body.
+        if ( RefEntityFactory::instance()->get_body(vol_id) == NULL )
+        {
+          temp_body->set_id(vol_id);
+        }
+        //if it is in use, then we shouldn't mess around with it...
+      }
+    }
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_bodies( new_bodies );
+
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : Reverse a body
 //
 // Special Notes : Moved from Body
@@ -5472,30 +8467,123 @@
 //
 // Creation Date :
 //-------------------------------------------------------------------------
-CubitStatus GeometryModifyTool::reverse( Body* body )
+CubitStatus GeometryModifyTool::reverse( DLIList<Body*> &body_list )
 {
-   BodySM* body_sm = body->get_body_sm_ptr();
-   GeometryModifyEngine* gme = get_engine( body_sm );
-   if (!gme) {
-      PRINT_ERROR("Body %d does not have a modify engine.\n", body->id());
-      return CUBIT_FAILURE;
+   DLIList<Body*> reversed_bodies;
+   int i;
+   for( i=body_list.size(); i--; )
+   {
+     Body *body = body_list.get_and_step();
+     BodySM* body_sm = body->get_body_sm_ptr();
+     GeometryModifyEngine* gme = get_engine( body_sm );
+     if (!gme) {
+        PRINT_ERROR("Body %d does not have a modify engine.\n", body->id());
+        continue;
+     }
+
+     CubitStatus stat = gme->reverse_body( body_sm );
+
+     if ( CUBIT_SUCCESS != stat )
+     {
+       PRINT_ERROR("Reverse failed.\n");
+       continue;
+     }
+     else
+     {
+       reversed_bodies.append( body );
+       GeometryQueryTool::instance()->make_Body( body_sm );
+       body->notify_all_observers( GEOMETRY_MODIFIED );
+       PRINT_INFO("Reversed body %d.\n", body->id());
+       continue;
+     }
    }
 
-   CubitStatus stat = gme->reverse_body( body_sm );
-   if ( CUBIT_SUCCESS != stat )
+   if( CubitUndo::get_undo_enabled() )
    {
-     PRINT_ERROR("Reverse failed.\n");
-     return CUBIT_FAILURE;
+     CubitString undo_command("reverse body ");
+     for( i=reversed_bodies.size(); i--; )
+     {
+       undo_command += reversed_bodies.get_and_step()->id();
+       undo_command += " ";
+     }
+     CubitUndo::set_undo_by_command( undo_command );
    }
-   else
-   {
-     GeometryQueryTool::instance()->make_Body( body_sm );
-     body->notify_all_observers( GEOMETRY_MODIFIED );
-     PRINT_INFO("Reversed body %d.\n", body->id());
-     return CUBIT_SUCCESS;
-   }
+
+   return CUBIT_SUCCESS;
 }
 
+//===============================================================================
+// Function   : reverse
+// Member Type: PUBLIC
+// Description: Reverse given surfaces (flip normals)
+// Author     : Steve Storm (CAT)
+// Date       : 4/3/2007
+//===============================================================================
+CubitStatus GeometryModifyTool::reverse( DLIList<RefFace*> &ref_face_list )
+{
+  // Check for virtual geometry
+  DLIList<RefEntity*> ref_ent_list;
+  CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
+  if( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+  {
+    PRINT_ERROR("REVERSING surfaces containing virtual geometry is not\n"
+      "       allowed. Delete virtual geometry on surfaces before\n"
+      "       operation.\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Get the owning bodies of the faces
+  int i;
+  DLIList<Body*> body_list;
+  for( i=ref_face_list.size(); i--; )
+    ref_face_list.get_and_step()->bodies( body_list );
+  body_list.uniquify_unordered();
+
+  // Handle surfaces from different modify engines.  Copy the input list since
+  // we will be pulling RefFaces out of it.
+  DLIList<RefFace*> copied_ref_face_list = ref_face_list;
+
+  // Keep track of overall errors and successes
+  int error_occurred = 0;
+  int successful_case = 0;
+  GeometryModifyEngine *gme_ptr;
+
+  while( copied_ref_face_list.size() )
+  {
+    // Need to send in Surfaces
+    DLIList<Surface*> surface_list;
+    DLIList<RefFace*> common_face_list;
+
+    gme_ptr = pull_common_surfs( copied_ref_face_list, common_face_list,
+                                 surface_list );
+    if( !gme_ptr )
+      return CUBIT_FAILURE;
+
+    if( gme_ptr->flip_normals( surface_list ) == CUBIT_FAILURE )
+      error_occurred = 1;
+    else
+      successful_case = 1;
+  }
+
+  if( error_occurred && !successful_case )
+    return CUBIT_FAILURE;
+
+  // Update the impacted bodies
+  Body *body_ptr;
+  BodySM* body_sm_ptr;
+  DLIList<BodySM*> new_sm_list;
+  for( i=body_list.size(); i--; )
+  {
+    body_ptr = body_list.get_and_step();
+    body_ptr->notify_all_observers( GEOMETRY_MODIFIED );
+    body_sm_ptr = body_ptr->get_body_sm_ptr();
+    new_sm_list.append( body_sm_ptr );
+  }
+
+  DLIList<Body*> new_body_list;
+  return finish_sm_op(body_list, new_sm_list, new_body_list );
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : split a periodic surface.
 //
@@ -5523,15 +8611,44 @@
 
    BodySM* new_sm = 0;
 
-     // Call the default GeometryModifyEngine to create a new Point
+   if (CubitUndo::get_undo_enabled())
+     CubitUndo::save_state_with_cubit_file(b_list);
+
+   DLIList<BodySM*> body_sms;
+   body_sms.append(body_sm);
+
+   do_attribute_setup();
+   push_vg_attributes_before_modify(body_sms);
+
+   // Call the default GeometryModifyEngine to create a new Point
    CubitStatus stat = gme->split_periodic( body_sm, new_sm );
 
+   DLIList<BodySM*> new_bodysm_list;
+   if(new_sm)
+     new_bodysm_list.append(new_sm);
+   DLIList<Body*> old_body_list;
+   old_body_list.append(body_ptr);
+   restore_vg_after_modify(new_bodysm_list, old_body_list, gme);
+   remove_pushed_attributes(new_bodysm_list, old_body_list);
+   do_attribute_cleanup();
+
    update_body(body_ptr);
 
    new_body_ptr = 0;
    if (new_sm)
      new_body_ptr = GeometryQueryTool::instance()->make_Body(new_sm);
 
+   if (new_body_ptr)
+   {
+     if (CubitUndo::get_undo_enabled())
+       CubitUndo::note_result_body(new_body_ptr);
+   }
+   else
+   {
+     if (CubitUndo::get_undo_enabled())
+       CubitUndo::remove_last_undo();
+   }
+
    GeometryQueryTool::instance()->cleanout_deactivated_geometry();
 
    return stat;
@@ -5549,22 +8666,27 @@
                                    DLIList<CubitVector*> &locations,
                                    DLIList<DLIList<CubitVector*>*> &vec_lists,
                                    CubitBoolean preview_flg,
-                                   CubitBoolean create_ref_edges_flg )
+                                   CubitBoolean create_ref_edges_flg,
+                                   CubitBoolean clear_previous_previews )
 {
   // Check for virtual geometry
   DLIList<RefFace*> ref_face_list;
   ref_face_list.append( ref_face_ptr );
 
-  DLIList<RefEntity*> ref_ent_list;
-  CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
-  if( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+  DLIList<Body*> b_list;
+  Body* body = ref_face_ptr->body();
+  if (body)
+	  b_list.append(body);
+  else
   {
-    PRINT_ERROR("SPLITTING surfaces containing virtual geometry is not\n"
-      "       allowed. Delete virtual geometry on surface %d before\n"
-      "       operation.\n", ref_face_ptr->id() );
-    return CUBIT_FAILURE;
+	  PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
+		  "      It cannot be split.\n", ref_face_ptr->id() );
+	  return CUBIT_FAILURE;
   }
 
+  if (!okay_to_modify( b_list, "SPLIT_SURFACE" ))
+    return CUBIT_FAILURE;
+
   int i;
   DLIList<Body*> old_body_list;
   for( i=ref_face_list.size(); i--; )
@@ -5587,12 +8709,131 @@
 
   SplitSurfaceTool sst;
   if( preview_flg == CUBIT_TRUE )
-    return sst.preview( ref_face_ptr, locations, vec_lists, create_ref_edges_flg );
+    return sst.preview( ref_face_ptr, locations, vec_lists, create_ref_edges_flg,
+                        clear_previous_previews );
   else
-   return sst.split_surface( ref_face_ptr, locations, vec_lists );
+    return sst.split_surface( ref_face_ptr, vec_lists );
 }
 
 //===============================================================================
+// Function   : split_surface
+// Member Type: PUBLIC
+// Description: Split multiple surfaces
+// Author     : Greg Schebler (CAT)
+// Date       : 06/08
+//===============================================================================
+
+CubitStatus
+GeometryModifyTool::split_surface( DLIList<RefFace*> &ref_face_list,
+                                  DLIList<CubitVector*> &locations,
+                                  DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
+                                  CubitBoolean preview_flg,
+                                  CubitBoolean create_ref_edges_flg,
+                                  CubitBoolean clear_previous_previews )
+{
+   // Check for virtual geometry
+   DLIList<Body*> b_list;
+   int gg;
+   for( gg = ref_face_list.size() ; gg > 0 ; gg--)
+   {
+      RefFace* ref_face_ptr = ref_face_list.get_and_step();
+      Body* body = ref_face_ptr->body();
+      if (body)
+         b_list.append(body);
+      else
+      {
+         PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
+            "      It cannot be split.\n", ref_face_ptr->id() );
+         return CUBIT_FAILURE;
+      }
+   }
+   if (!okay_to_modify( b_list, "SPLIT_SURFACE" ))
+      return CUBIT_FAILURE;
+
+   int ii;
+
+   for( ii = ref_face_list.size(); ii > 0 ; ii--)
+   {
+      DLIList<Body*> old_body_list;
+      RefFace* ref_face_ptr = ref_face_list.get_and_step();
+
+      DLIList<Body*> body_list;
+      ref_face_ptr->bodies( body_list );
+      old_body_list.merge_unique( body_list );
+
+      if( old_body_list.size() < 1 )
+      {
+         PRINT_ERROR( "Surface %d is not contained within a parent body\n."
+            "      It cannot be split.\n", ref_face_ptr->id() );
+         return CUBIT_FAILURE;
+      }
+   }
+
+   SplitSurfaceTool sst;
+   if( preview_flg == CUBIT_TRUE )
+      return sst.preview( ref_face_list, locations, list_of_vec_lists, create_ref_edges_flg,
+      clear_previous_previews );
+   else
+      return sst.split_surface( ref_face_list, list_of_vec_lists );
+}
+
+//===============================================================================
+// Function   : split_surfaces_extend
+// Member Type: PUBLIC
+// Description: Split surfaces by extending hardline curves on the surface
+// Author     : Steve Storm (CAT)
+// Date       : 10/07
+//===============================================================================
+CubitStatus
+GeometryModifyTool::split_surfaces_extend( DLIList<RefFace*> &ref_face_list,
+                                           DLIList<RefVertex*> &ref_vertex_list,
+                                           CubitBoolean preview_flg,
+                                           CubitBoolean create_ref_edges_flg )
+{
+  int i;
+  RefFace *ref_face_ptr;
+
+  for( i=ref_face_list.size(); i--; )
+  {
+    ref_face_ptr = ref_face_list.get();
+
+    // Check for no body
+    DLIList<Body*> body_list;
+    ref_face_ptr->bodies( body_list );
+    if( body_list.size()==0 )
+    {
+      PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
+        "       It cannot be split.\n", ref_face_ptr->id() );
+      return CUBIT_FAILURE;
+    }
+  }
+
+  // Check for virtual geometry
+  DLIList<RefEntity*> ref_ent_list;
+  CAST_LIST_TO_PARENT(ref_face_list, ref_ent_list);
+  if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+  {
+    PRINT_ERROR("SPLITTING surfaces containing virtual geometry is not\n"
+      "       allowed. Delete virtual geometry on these surfaces\n"
+      "       before operation.\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Make sure all surfaces are from same geometry engine
+  if ( !same_modify_engine(ref_ent_list, CUBIT_TRUE) )
+  {
+    PRINT_ERROR("Performing SPLIT with surfaces containing geometry from\n"
+      "different modeling engines is not allowed.\n"
+      "Delete uncommon geometry on these surfaces before operation.\n\n");
+    return CUBIT_FAILURE;
+  }
+
+  SplitSurfaceTool sst;
+  return sst.split_surfaces_extend( ref_face_list, ref_vertex_list,
+    preview_flg, create_ref_edges_flg );
+}
+
+//===============================================================================
 // Function   : split_surfaces
 // Member Type: PUBLIC
 // Description: Split a chain of surfaces into one or more pieces
@@ -5740,6 +8981,84 @@
       create_ref_edges_flg);
 }
 
+//===============================================================================
+// Function   : auto_mid_surface
+// Member Type: PUBLIC
+// Description: Automatically midsurface a volume
+// Author     : Sam Showman (CAT)
+// Date       : 12/07
+//===============================================================================
+CubitStatus
+GeometryModifyTool::auto_mid_surface(DLIList<Body*> &body_list_in,
+                                     DLIList<Body*> &body_list_out,
+                                     DLIList<Body*> &old_bodies_midsurfaced,
+                                     DLIList<double> &thickness_list,
+                                     double lower_tol,
+                                     double upper_tol,
+                                     CubitBoolean delete_midsurfaced,
+ 
+                                     CubitBoolean preview)
+{
+	// Check for virtual geometry
+	DLIList<RefEntity*> ref_ent_list;
+	CAST_LIST_TO_PARENT(body_list_in, ref_ent_list);
+	if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+	{
+		PRINT_ERROR("Midsurfacing volumes containing virtual geometry is not\n"
+			"       allowed. Delete virtual geometry on these surfaces\n"
+			"       before operation.\n" );
+		return CUBIT_FAILURE;
+	}
+
+	// Make sure all surfaces are from same geometry engine
+	if ( !same_modify_engine(ref_ent_list, CUBIT_TRUE) )
+	{
+		PRINT_ERROR("Performing Midsurface with geometry from\n"
+			"different modeling engines is not allowed.\n");
+		return CUBIT_FAILURE;
+	}
+
+	AutoMidsurfaceTool mid_tool;
+	DLIList<BodySM*> bodysm_list_out;
+
+    if (CubitUndo::get_undo_enabled() && delete_midsurfaced && !preview)
+        CubitUndo::save_state_with_cubit_file(body_list_in);
+
+    CubitStatus result = mid_tool.midsurface(
+        body_list_in,
+        bodysm_list_out,
+        old_bodies_midsurfaced,
+        thickness_list,
+        lower_tol,
+        upper_tol,
+        delete_midsurfaced,
+        preview);
+
+
+	if (result == CUBIT_SUCCESS &&
+		bodysm_list_out.size() > 0 &&
+		!preview)
+	{
+		if(CubitUndo::get_undo_enabled())
+			CubitUndo::save_state();
+
+		for( int i=0; i<bodysm_list_out.size(); i++ )
+		{
+			body_list_out.append(GeometryQueryTool::instance()->make_Body(bodysm_list_out[i]));
+		}
+
+		if( CubitUndo::get_undo_enabled() )
+		{
+			if( body_list_out.size() )
+				CubitUndo::note_result_bodies( body_list_out );
+			else
+				CubitUndo::remove_last_undo();
+		}
+	}
+
+	return result;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : clean RefEntity
 //
@@ -5751,35 +9070,99 @@
 //-------------------------------------------------------------------------
 
 CubitStatus
-GeometryModifyTool::regularize_refentity(RefEntity *old_entity_ptr,
-													               Body *&new_body_ptr)
+GeometryModifyTool::regularize_refentity(RefEntity *old_entity_ptr, Body *&new_body_ptr)
 {
+  BasicTopologyEntity* bte_ptr = dynamic_cast<BasicTopologyEntity*>(old_entity_ptr);
+  if (!bte_ptr)
+  {
+    PRINT_ERROR("Invalid entity passed to regularize_refentity(..)\n");
+    return CUBIT_FAILURE;
+  }
+
+  DLIList<Body*> body_list;
+  bte_ptr->bodies(body_list);
+
+  //ignore free entities
+  if( body_list.size() == 0 )
+  {
+    PRINT_ERROR("%s %d is a free entity.  Cannot regularize it.\n", old_entity_ptr->class_name(), 
+                                                                    old_entity_ptr->id() );
+    new_body_ptr = NULL;
+    return CUBIT_FAILURE;
+  }
+
+  if (!okay_to_modify( body_list, "REGULARIZE" ))
+    return CUBIT_FAILURE;
+
+  DLIList<TopologyBridge*> bridge_list;
+  bte_ptr->bridge_manager()->get_bridge_list(bridge_list);
+  bridge_list.reset();
+
+  DLIList<BodySM*> new_sm_list;
+  DLIList<Body*> new_body_list;
+  CubitStatus stat = CUBIT_SUCCESS;
+
+  do_attribute_setup();
+
+  GeometryModifyEngine *save_gme = NULL;
+  for (int i = bridge_list.size(); i--; )
+  {
+    TopologyBridge* bridge = bridge_list.get_and_step();
+    GeometryEntity* geom_ptr = dynamic_cast<GeometryEntity*>(bridge);
+    GeometryModifyEngine* gme = get_engine(geom_ptr);
+    if(!save_gme)
+      save_gme = gme;
+    if (!gme) continue;
+
+    DLIList<BodySM*> body_sm_list;
+    geom_ptr->bodysms(body_sm_list);
+    push_vg_attributes_before_modify(body_sm_list);
+
+    BodySM *new_body_sm = NULL;
+    if (!gme->regularize_entity( geom_ptr, new_body_sm ))
+      stat = CUBIT_FAILURE;
+
+    if (new_body_sm)
+      new_sm_list.append(new_body_sm);
+  }
+
+  // This is bad in that it assumes all of the gmes will be the
+  // same but I don't know that we truly support the other case
+  // anyway.
+  if(new_sm_list.size())
+  {
+    restore_vg_after_modify(new_sm_list, body_list, save_gme);
+    remove_pushed_attributes(new_sm_list, body_list);
+  }
+
+  if (!finish_sm_op(body_list, new_sm_list, new_body_list))
+    stat = CUBIT_FAILURE;
+
+  do_attribute_cleanup();
+
+  new_body_ptr = new_body_list.size() ? new_body_list.get() : 0;
+  return stat;
+}
+
+CubitStatus GeometryModifyTool::test_regularize_refentity(RefEntity *old_entity_ptr)
+{
    DLIList<RefEntity*> tmp_ref_ent_list(1);
    tmp_ref_ent_list.append( old_entity_ptr );
    if( GeometryQueryTool::instance()->contains_intermediate_geometry(tmp_ref_ent_list) )
    {
-     PRINT_ERROR("%s %d or owning parent(s) is virtual.  Regularizing virtual\n"
-       "       geometry is not allowed. Delete virtual geometry first.\n",
-               old_entity_ptr->class_name(), old_entity_ptr->id() );
      return CUBIT_FAILURE;
    }
 
    BasicTopologyEntity* bte_ptr = dynamic_cast<BasicTopologyEntity*>(old_entity_ptr);
    if (!bte_ptr)
    {
-     PRINT_ERROR("Invalid entity passed to regularize_refentity(..)\n");
      return CUBIT_FAILURE;
    }
 
-   DLIList<Body*> body_list;
-   bte_ptr->bodies(body_list);
-
    DLIList<TopologyBridge*> bridge_list;
    bte_ptr->bridge_manager()->get_bridge_list(bridge_list);
    bridge_list.reset();
 
-   DLIList<BodySM*> new_sm_list;
-   DLIList<Body*> new_body_list;
    CubitStatus stat = CUBIT_SUCCESS;
 
    for (int i = bridge_list.size(); i--; )
@@ -5789,18 +9172,10 @@
      GeometryModifyEngine* gme = get_engine(geom_ptr);
      if (!gme) continue;
 
-     BodySM* new_body_sm = 0;
-     if (!gme->regularize_entity( geom_ptr, new_body_sm ))
+     if (!gme->test_regularize_entity( geom_ptr ))
        stat = CUBIT_FAILURE;
-
-     if (new_body_sm)
-       new_sm_list.append(new_body_sm);
    }
 
-   if (!finish_sm_op(body_list, new_sm_list, new_body_list))
-     stat = CUBIT_FAILURE;
-
-   new_body_ptr = new_body_list.size() ? new_body_list.get() : 0;
    return stat;
 }
 
@@ -5830,6 +9205,11 @@
      return CUBIT_FAILURE;
   }
 
+   do_attribute_setup();
+   DLIList<BodySM*> body_sm_list, new_bodysm_list;
+   body_sm_list.append(body_sm);
+   push_vg_attributes_before_modify(body_sm_list);
+
    CubitStatus stat = gme->regularize_body( body_sm, new_sm );
    if ( new_sm == NULL )
    {
@@ -5837,20 +9217,30 @@
       return CUBIT_FAILURE;
    }
 
+   // remove mesh from modified body
+   body_premodify(body_ptr);
+
+   new_bodysm_list.append(new_sm);
+   restore_vg_after_modify(new_bodysm_list, b_list, gme);
+   remove_pushed_attributes(new_bodysm_list, b_list);
+
    body_sm = body_ptr->get_body_sm_ptr();
    update_body(body_ptr);
 
    new_body = GeometryQueryTool::instance()->make_Body(new_sm);
    GeometryQueryTool::instance()->cleanout_deactivated_geometry();
 
+   do_attribute_cleanup();
+
    return stat;
 }
 
 CubitStatus
-GeometryModifyTool::create_body_from_surfs( DLIList<RefFace*> &ref_face_list,
-                                            Body *&new_body,
+GeometryModifyTool::create_solid_bodies_from_surfs( DLIList<RefFace*> &ref_face_list,
+                                            DLIList<Body*> &new_bodies,
                                             CubitBoolean keep_old,
-                                            CubitBoolean heal ) const
+                                            CubitBoolean heal,
+                                            CubitBoolean sheet ) const
 {
     //First check to make sure the data is all here.
   for ( int ii = ref_face_list.size(); ii > 0; ii-- )
@@ -5894,16 +9284,16 @@
   }
 
   DLIList<ModelEntity*> query_output, query_input(ref_face_list.size());
-  DLIList<Body*> body_list, new_body_list(1);
-  DLIList<BodySM*> body_sm_list(1);
+  DLIList<Body*> body_list;
 
   CAST_LIST_TO_PARENT(ref_face_list, query_input);
   ModelQueryEngine::instance()->
     query_model( query_input, DagType::body_type(), query_output );
   CAST_LIST( query_output, body_list, Body );
-
+  
+  int i;
   DLIList<RefFace*> free_face_list;
-  for (int i = ref_face_list.size(); i--; )
+  for ( i=ref_face_list.size(); i--; )
   {
     RefFace* ref_face = ref_face_list.get_and_step();
     query_output.clean_out();
@@ -5913,14 +9303,47 @@
       free_face_list.append(ref_face);
   }
 
-  BodySM* new_sm = 0;
-  CubitStatus stat = gme->create_body_from_surfs( surface_list, new_sm, keep_old, heal );
-  if (new_sm)
-    body_sm_list.append(new_sm);
+  if (CubitUndo::get_undo_enabled())
+    CubitUndo::save_state_with_cubit_file(ref_face_list);
+  
+  //get all the bodysm's 
+  DLIList<BodySM*> old_body_sm_list;
+  for( i=body_list.size(); i--; )
+  {
+    Body *tmp_body = body_list.get_and_step();
+    TopologyBridge *tb = tmp_body->bridge_manager()->topology_bridge();
+    BodySM *tmp_body_sm = CAST_TO(tb, BodySM);
+    if( tmp_body_sm )
+      old_body_sm_list.append( tmp_body_sm );    
+  }  
 
-  if (!finish_sm_op( body_list, body_sm_list, new_body_list))
+  // TODO: do I need a clear and a flush here? --KGM
+  GeometryModifyTool::instance()->do_attribute_setup();
+  GeometryModifyTool::instance()->push_vg_attributes_before_modify(old_body_sm_list);
+
+  DLIList<BodySM*> new_bodies_sm;
+  CubitStatus stat = gme->create_solid_bodies_from_surfs( surface_list, new_bodies_sm, keep_old, heal, sheet );
+  DLIList<BodySM*> body_sm_list;
+  for ( i=new_bodies_sm.size(); i--; )
+    body_sm_list.append( new_bodies_sm.get_and_step() );
+
+  GeometryModifyTool::instance()->restore_vg_after_modify(new_bodies_sm, body_list, gme);
+  GeometryModifyTool::instance()->remove_pushed_attributes(new_bodies_sm, body_list);
+
+  if (!finish_sm_op( body_list, body_sm_list, new_bodies))
+  {
     stat = CUBIT_FAILURE;
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::remove_last_undo();
+  }
+  else
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::note_result_bodies(new_bodies);
+  }
 
+  GeometryModifyTool::instance()->do_attribute_cleanup();
+
   DLIList<int> id_list (free_face_list.size());
   while (free_face_list.size())
   {
@@ -5932,11 +9355,12 @@
         destroy_dead_entity( ref_face );
     }
   }
+
   GeometryQueryTool::instance()->cleanout_deactivated_geometry();
   if (id_list.size())
     CubitUtil::list_entity_ids( "Destroyed surface(s) ", id_list );
 
-  new_body = new_body_list.size() ? new_body_list.get() : 0;
+  //new_body = new_body_list.size() ? new_body_list.get() : 0;
   return stat;
 }
 
@@ -6080,6 +9504,8 @@
     complete_entity_list.clean_out();
     complete_entity_list.merge_unique(temp);
   }
+  else
+    complete_entity_list = ref_entity_list;
 
   //Now make sure all the RefEntitys are from the same geometry engine
   DLIList<TopologyEntity*> te_list;
@@ -6101,13 +9527,28 @@
   if (!gme_ptr || !curve)
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefEdge*> tmp_ents(1);
+    tmp_ents.append( trim_curve );
+    CubitUndo::save_state_with_cubit_file( tmp_ents );
+  }
+
   new_curve = gme_ptr->trim_curve( curve, trim_vector, keep_vector );
   if (!new_curve)
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
   GeometryQueryTool::instance()->destroy_dead_entity( trim_curve );
 
   RefEdge* new_edge = GeometryQueryTool::instance()->make_free_RefEdge(new_curve);
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_entity( new_edge );
+
   PRINT_INFO("Created curve %d\n", new_edge->id());
 
   return CUBIT_SUCCESS;
@@ -6140,10 +9581,14 @@
   double resabs = gqe->get_sme_resabs_tolerance();
 
   DLIList<Curve*> curve_list;
-  if( gme->surface_intersection( surf0, surf1, curve_list, resabs ) ==
-    CUBIT_FAILURE )
+  CubitStatus status = gme->surface_intersection( surf0, surf1, curve_list, resabs );
+
+  if( status == CUBIT_FAILURE )
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && curve_list.size() )
+    CubitUndo::save_state();
+
   int i;
   Curve *curve_ptr;
   RefEdge *ref_edge_ptr;
@@ -6154,13 +9599,19 @@
     ref_edge_ptr = GeometryQueryTool::instance()->
       make_free_RefEdge( curve_ptr );
     if( ref_edge_ptr )
-    {
       ref_edge_list.append( ref_edge_ptr );
-    }
     else
       delete curve_ptr;
   }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefEntity*> tmp_list;
+    for( i=ref_edge_list.size(); i--; )
+      tmp_list.append( ref_edge_list.get_and_step() );
+    CubitUndo::note_result_entities( tmp_list );
+  }
+
   return CUBIT_SUCCESS;
 }
 
@@ -6183,9 +9634,11 @@
   }
 
   //if we can reuse vertices, we decide here
+  bool need_new_start_point = false;
+  bool need_new_end_point = false;
   if( full )
   {
-    bool need_new_start_point = ref_vertex1->get_parents() > 0;
+    need_new_start_point = ref_vertex1->get_parents() > 0;
     if (need_new_start_point)
     {
       bridge_list.reset();
@@ -6195,8 +9648,8 @@
   }
   else
   {
-    bool need_new_start_point = ref_vertex1->get_parents() > 0;
-    bool need_new_end_point = ref_vertex3->get_parents() > 0;
+    need_new_start_point = ref_vertex1->get_parents() > 0;
+    need_new_end_point = ref_vertex3->get_parents() > 0;
 
     if (need_new_start_point)
     {
@@ -6213,16 +9666,38 @@
     }
   }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefVertex*> vertices_to_save;
+    if( !need_new_start_point )
+      vertices_to_save.append( ref_vertex1 );
+    if( !need_new_end_point )
+      vertices_to_save.append( ref_vertex3 );
+
+    if( vertices_to_save.size() )
+      CubitUndo::save_state_with_cubit_file( vertices_to_save, true );
+    else
+      CubitUndo::save_state();
+  }
+
   bridge_list.reset();
   Point* point0 = dynamic_cast<Point*>(bridge_list.next(0));
   Point* point1 = dynamic_cast<Point*>(bridge_list.next(1));
   Point* point2 = dynamic_cast<Point*>(bridge_list.next(2));
   Curve* curve = gme->create_arc_three( point0, point1, point2, full );
   if (!curve)
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
     return 0;
+  }
 
   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
   PRINT_INFO("Created curve %d\n", result->id());
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_entity( result );
+
   return result;
 }
 
@@ -6252,7 +9727,14 @@
   if (!curve)
     return 0;
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_entity( result );
+
   PRINT_INFO("Created curve %d\n", result->id());
   return result;
 }
@@ -6278,20 +9760,22 @@
   }
 
   //if we can reuse vertices, we decide here
+  bool need_new_start_point, need_new_end_point;
   if( full )
   {
-    bool need_new_start_point = ref_vertex3->get_parents() > 0;
+    need_new_start_point = ref_vertex2->get_parents() > 0;
     if (need_new_start_point)
     {
       bridge_list.reset();
-      Point *start_point = gme->make_Point( ref_vertex3->coordinates() );
+      bridge_list.step(1);
+      Point *start_point = gme->make_Point( ref_vertex2->coordinates() );
       bridge_list.change_to( start_point );
     }
   }
   else
   {
-    bool need_new_start_point = ref_vertex2->get_parents() > 0;
-    bool need_new_end_point = ref_vertex3->get_parents() > 0;
+    need_new_start_point = ref_vertex2->get_parents() > 0;
+    need_new_end_point = ref_vertex3->get_parents() > 0;
 
     if (need_new_start_point)
     {
@@ -6308,7 +9792,20 @@
     }
   }
 
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefVertex*> vertices_to_save;
+    if( !need_new_start_point )
+      vertices_to_save.append( ref_vertex2 );
+    if( !need_new_end_point )
+      vertices_to_save.append( ref_vertex3 );
 
+    if( vertices_to_save.size() )
+      CubitUndo::save_state_with_cubit_file( vertices_to_save, true );
+    else
+      CubitUndo::save_state();
+  }
+
   bridge_list.reset();
   Point* point0 = dynamic_cast<Point*>(bridge_list.next(0));
   Point* point1 = dynamic_cast<Point*>(bridge_list.next(1));
@@ -6316,10 +9813,18 @@
   Curve* curve = gme->create_arc_center_edge( point0, point1, point2,
                                               normal, radius, full );
   if (!curve)
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
     return 0;
+  }
 
   RefEdge* result = GeometryQueryTool::instance()->make_free_RefEdge(curve);
   PRINT_INFO("Created curve %d\n", result->id());
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::note_result_entity( result );
+
   return result;
 }
 
@@ -6350,6 +9855,9 @@
   DLIList<Curve*> curve_list(count);
   CAST_LIST( bridge_list, curve_list, Curve );
   result = gme->create_curve_combine(curve_list, new_curve_ptr);
+  if (new_curve_ptr)
+      new_ref_edge_ptr = CAST_TO(new_curve_ptr->topology_entity(), RefEdge);
+  
 
   return result;
 }
@@ -6366,50 +9874,86 @@
 GeometryModifyEngine*
 GeometryModifyTool::common_modify_engine( DLIList<TopologyEntity*>& topology_list,
                                           DLIList<TopologyBridge*>& engine_bridges,
-                                          CubitBoolean /*allow_virtual_engine*/ ) const
+                                          CubitBoolean allow_composites ) const
 {
-  topology_list.reset();
-
-  TopologyEntity* topo_ptr = topology_list.get_and_step();
-  if (!topo_ptr)
-     return (GeometryModifyEngine*)NULL;
-  DLIList<TopologyBridge*> first_bridge_list;
-  topo_ptr->bridge_manager()->get_bridge_list( first_bridge_list );
-
-  first_bridge_list.reset();
   GeometryModifyEngine* gme_ptr = 0;
-  for( int i = first_bridge_list.size(); i > 0; i-- )
+  if(allow_composites)
   {
-    TopologyBridge* bridge_ptr = first_bridge_list.get_and_step();
+    int i;
     engine_bridges.clean_out();
-    engine_bridges.append( bridge_ptr );
-    gme_ptr = get_engine(bridge_ptr);
+    for(i=topology_list.size(); i--;)
+    {
+      TopologyEntity* topo_ptr = topology_list.get_and_step();
+      if (!topo_ptr)
+        return (GeometryModifyEngine*)NULL;
+      TopologyBridge *first_bridge = topo_ptr->bridge_manager()->topology_bridge();
+      GeometryQueryEngine *gqe = first_bridge->get_geometry_query_engine();
+      DLIList<TopologyBridge*> underlying_bridge_list;
+      gqe->get_underlying_bridges(first_bridge, underlying_bridge_list);
+      if(underlying_bridge_list.size() == 0)
+        underlying_bridge_list.append(first_bridge);
+      int k;
+      for(k=underlying_bridge_list.size(); k--;)
+      {
+        TopologyBridge *bridge_ptr = underlying_bridge_list.get_and_step();
+        engine_bridges.append( bridge_ptr );
+        GeometryModifyEngine *cur_gme = get_engine(bridge_ptr);
+        if(!gme_ptr)
+          gme_ptr = cur_gme;
+        else
+        {
+          if(gme_ptr != cur_gme)
+          {
+            gme_ptr = NULL;
+            k=0;
+            i=0;
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    topology_list.reset();
 
-    if( !gme_ptr )
-     return (GeometryModifyEngine*)NULL;
+    TopologyEntity* topo_ptr = topology_list.get_and_step();
+    if (!topo_ptr)
+      return (GeometryModifyEngine*)NULL;
+    DLIList<TopologyBridge*> first_bridge_list;
+    topo_ptr->bridge_manager()->get_bridge_list( first_bridge_list );
 
-    topology_list.reset();
-    topology_list.step(); //skip first entry
-    for( int j = topology_list.size(); j > 1; j-- )
+    first_bridge_list.reset();
+    for( int i = first_bridge_list.size(); i > 0; i-- )
     {
-      topo_ptr = topology_list.get_and_step();
-      bridge_ptr = topo_ptr->bridge_manager()->topology_bridge(gme_ptr->get_gqe());
-      if( bridge_ptr ) engine_bridges.append( bridge_ptr );
-      else break;
-    }
+      TopologyBridge* bridge_ptr = first_bridge_list.get_and_step();
+      engine_bridges.clean_out();
+      engine_bridges.append( bridge_ptr );
+      gme_ptr = get_engine(bridge_ptr);
 
-    if( engine_bridges.size() == topology_list.size() )
-      break;
+      if( !gme_ptr )
+      return (GeometryModifyEngine*)NULL;
 
-    gme_ptr = 0;
+      topology_list.reset();
+      topology_list.step(); //skip first entry
+      for( int j = topology_list.size(); j > 1; j-- )
+      {
+        topo_ptr = topology_list.get_and_step();
+        bridge_ptr = topo_ptr->bridge_manager()->topology_bridge(gme_ptr->get_gqe());
+        if( bridge_ptr ) engine_bridges.append( bridge_ptr );
+        else break;
+      }
+
+      if( engine_bridges.size() == topology_list.size() )
+        break;
+
+      gme_ptr = 0;
+    }
   }
-
   if( !gme_ptr )
   {
     engine_bridges.clean_out();
     PRINT_ERROR("Entities do not belong to the same geometry engine.\n");
   }
-
   return gme_ptr;
 }
 
@@ -6424,7 +9968,7 @@
 //-------------------------------------------------------------------------
 GeometryModifyEngine*
 GeometryModifyTool::common_modify_engine( DLIList<Body*>& input,
-                                          DLIList<BodySM*>& output ) const
+                                          DLIList<BodySM*>& output) const
 {
   input.reset();
   Body* body_ptr = input.get();
@@ -6467,7 +10011,8 @@
 GeometryModifyTool::common_modify_engine( DLIList<RefFace*>& face_list,
                                           DLIList<RefEdge*>& edge_list,
                                           DLIList<Surface*>& surf_list,
-                                          DLIList<Curve*>& curv_list ) const
+                                          DLIList<Curve*>& curv_list,
+                                          CubitBoolean allow_composites) const
 {
   int i;
   const int count = face_list.size() + edge_list.size();
@@ -6481,17 +10026,27 @@
   for (i = edge_list.size(); i--; )
     entity_list.append(edge_list.get_and_step());
 
-  GeometryModifyEngine* engine = common_modify_engine(entity_list, bridge_list);
+  GeometryModifyEngine* engine = common_modify_engine(entity_list, bridge_list, allow_composites);
   if (!engine)
     return 0;
 
   entity_list.reset();
   CAST_LIST(bridge_list, surf_list, Surface);
   CAST_LIST(bridge_list, curv_list, Curve  );
-  if (surf_list.size() != face_list.size() || curv_list.size() != edge_list.size())
-    return 0;
-
-  return engine;
+  if(allow_composites)
+  {
+    if(surf_list.size() >= face_list.size() && curv_list.size() >= edge_list.size())
+      return engine;
+    else
+      return 0;
+  }
+  else
+  {
+    if (surf_list.size() != face_list.size() || curv_list.size() != edge_list.size())
+      return 0;
+    else
+      return engine;
+  }
 }
 
 //-------------------------------------------------------------------------
@@ -6505,7 +10060,8 @@
 //-------------------------------------------------------------------------
 GeometryModifyEngine*
 GeometryModifyTool::common_modify_engine( DLIList<RefFace*>& face_list,
-                                          DLIList<Surface*>& surf_list ) const
+                                          DLIList<Surface*>& surf_list,
+                                          CubitBoolean allow_composites) const
 {
   const int size = face_list.size();
   DLIList<TopologyEntity*> topo_list(size);
@@ -6513,7 +10069,7 @@
   GeometryModifyEngine* result;
 
   CAST_LIST_TO_PARENT( face_list, topo_list );
-  result = common_modify_engine( topo_list, geom_list );
+  result = common_modify_engine( topo_list, geom_list, allow_composites );
 
   CAST_LIST( geom_list, surf_list, Surface );
   return result;
@@ -6530,7 +10086,8 @@
 //-------------------------------------------------------------------------
 GeometryModifyEngine* GeometryModifyTool::common_modify_engine(
                                       DLIList<RefEdge*>& edge_list,
-                                      DLIList<Curve*>& curve_list ) const
+                                      DLIList<Curve*>& curve_list,
+                                      CubitBoolean allow_composites) const
 {
   const int size = edge_list.size();
   DLIList<TopologyEntity*> topo_list(size);
@@ -6538,7 +10095,7 @@
   GeometryModifyEngine* result;
 
   CAST_LIST_TO_PARENT( edge_list, topo_list );
-  result = common_modify_engine( topo_list, geom_list );
+  result = common_modify_engine( topo_list, geom_list, allow_composites );
 
   CAST_LIST( geom_list, curve_list, Curve );
   return result;
@@ -6555,7 +10112,8 @@
 //-------------------------------------------------------------------------
 GeometryModifyEngine*
 GeometryModifyTool::common_modify_engine( DLIList<RefVertex*>& vertex_list,
-                                          DLIList<Point*>& point_list ) const
+                                          DLIList<Point*>& point_list,
+                                          CubitBoolean allow_composites) const
 {
   const int size = vertex_list.size();
   DLIList<TopologyEntity*> topo_list(size);
@@ -6563,12 +10121,78 @@
   GeometryModifyEngine* result;
 
   CAST_LIST_TO_PARENT( vertex_list, topo_list );
-  result = common_modify_engine( topo_list, geom_list );
+  result = common_modify_engine( topo_list, geom_list, allow_composites );
 
   CAST_LIST( geom_list, point_list, Point );
   return result;
 }
 
+//-------------------------------------------------------------------------
+// Purpose       : Pull RefFaces with a common GeometryModifyEngine out of
+//                 the input ref_face_list.  Place their surfaces in the
+//                 output surf_list, and return the common modify engine.
+//
+// Special Notes : the function returns a NULL pointer if a RefFace without
+//                 a modify engine is found in the input list.
+//
+// Creator       : Steve Storm
+//
+// Creation Date : 03/02/08
+//-------------------------------------------------------------------------
+GeometryModifyEngine*
+GeometryModifyTool::pull_common_surfs( DLIList<RefFace*> &ref_face_list,
+                                       DLIList<RefFace*> &common_face_list,
+                                       DLIList<Surface*> &common_surf_list )
+{
+  int i;
+  RefFace *ref_face_ptr;
+  Surface *surf_ptr;
+
+  GeometryModifyEngine *gme1 = 0, *gme2 = 0;
+
+  ref_face_list.reset();
+  for( i=0; i<ref_face_list.size(); i++ )
+  {
+    ref_face_ptr = ref_face_list.get();
+    surf_ptr = ref_face_ptr->get_surface_ptr();
+
+    if( i==0 )
+    {
+      common_face_list.append( ref_face_ptr );
+      common_surf_list.append( surf_ptr );
+      gme1 = get_engine( surf_ptr );
+      if (!gme1)
+      {
+        PRINT_ERROR("Surface %d does not have a modify engine.\n", ref_face_ptr->id());
+        return 0;
+      }
+      ref_face_list.change_to( NULL );
+      ref_face_list.step();
+      continue;
+    }
+
+    gme2 = get_engine( surf_ptr );
+    if (!gme2)
+    {
+      PRINT_ERROR("Surface %d does not have a modify engine.\n", ref_face_ptr->id());
+      return 0;
+    }
+
+    if( gme2 == gme1 )
+    {
+      common_face_list.append( ref_face_ptr );
+      common_surf_list.append( surf_ptr );
+      ref_face_list.change_to( NULL );
+    }
+
+    ref_face_list.step();
+  }
+
+  ref_face_list.remove_all_with_value( NULL );
+
+  return gme1;
+}
+
 // Separates the list of bodies so that there is one body per volume
 // after a webcut.  Checks the sepAfterWebcut flag.
 CubitStatus GeometryModifyTool::separate_body_after_webcut( DLIList<Body*> &input_list,
@@ -6585,7 +10209,16 @@
   {
     Body *body_ptr = input_list.get_and_step();
     temp_body_list.clean_out();
+
+    bool undo_setting = CubitUndo::get_undo_enabled();
+    if( undo_setting == true )
+      CubitUndo::set_undo_enabled( false );
+
     split_body(body_ptr, temp_body_list);
+
+    if( undo_setting == true )
+      CubitUndo::set_undo_enabled( true );
+
     output_list += temp_body_list;
   }
   return CUBIT_SUCCESS;
@@ -6786,7 +10419,7 @@
   if( ref_face1 == ref_face2 )
   {
     PRINT_ERROR("Cannot create midplane between the same surface.\n",
-                "       Surface %d was entered twice\n",  ref_face1->id() ); 
+                "       Surface %d was entered twice\n",  ref_face1->id() );
     return CUBIT_FAILURE;
   }
 
@@ -7053,7 +10686,7 @@
   if( ref_face1 == ref_face2 )
   {
     PRINT_ERROR("Cannot create midplane between the same surface.\n",
-                "       Surface %d was entered twice\n",  ref_face1->id() ); 
+                "       Surface %d was entered twice\n",  ref_face1->id() );
     return CUBIT_FAILURE;
   }
 
@@ -7142,23 +10775,37 @@
 
   if ( midsurface_body_sm )
   {
-    Body *midsurface_body;
+    if(CubitUndo::get_undo_enabled())
+      CubitUndo::save_state();
 
-    midsurface_body = GeometryQueryTool::instance()->make_Body(midsurface_body_sm);
-
-    DLIList<RefFace*> ref_faces;
-    midsurface_body->ref_faces( ref_faces );
-
+    DLIList<Surface*> mid_surfaces;
+    DLIList<Body*> new_bodies;
+    midsurface_body_sm->surfaces( mid_surfaces);
     //make each surface of the body into its own body
     int i;
-    for( i=0; i<ref_faces.size(); i++ )
+    for( i=0; i<mid_surfaces.size(); i++ )
     {
-      RefEntity *new_entity_ptr;
-      new_entity_ptr = GeometryModifyTool::instance()->copy_refentity(ref_faces.get_and_step());
-      RefFace *ref_face_ptr = CAST_TO(new_entity_ptr, RefFace);
+      Surface *tmp_surface = mid_surfaces.get_and_step();
+      bool extended_from = false;
+      Surface* new_surface_ptr = gme1_ptr->make_Surface( tmp_surface, extended_from );
+
+      Body *new_Body = make_Body(new_surface_ptr);
+      new_bodies.append( new_Body );
+      DLIList<RefFace*> ref_faces;
+      new_Body->ref_faces(ref_faces);
+      RefFace *ref_face_ptr = ref_faces.get();
       mid_surface_surfs.append( ref_face_ptr );
     }
-    GeometryQueryTool::instance()->delete_Body( midsurface_body );
+    gme1_ptr->get_gqe()->delete_solid_model_entities( midsurface_body_sm );
+
+    if( CubitUndo::get_undo_enabled() )
+    {
+      if( new_bodies.size() )
+        CubitUndo::note_result_bodies( new_bodies );
+      else
+        CubitUndo::remove_last_undo();
+    }
+
     return ret;
   }
   else
@@ -7197,7 +10844,8 @@
 GeometryModifyTool::tweak_setup( DLIList<RefFace*> &input_faces,
                                  const char* name,
                                  DLIList<Body*> &output_bodies,
-                                 DLIList<Surface*> &output_surfaces )
+                                 DLIList<Surface*> &output_surfaces,
+                                 CubitBoolean allow_composites)
 {
   if( input_faces.size() == 0 )
   {
@@ -7229,19 +10877,26 @@
     ->query_model( query_input, DagType::body_type(), query_output );
   CAST_LIST(query_output, output_bodies, Body);
 
-  // Check for virtual geometry
-  if ( contains_intermediate_geom(output_bodies))
+  if(allow_composites)
   {
-    PRINT_ERROR("%s surfaces on volumes containing virtual geometry\n"
-      "       is not allowed.\n"
-      "       Delete virtual geometry on these volumes before operation.\n",
-      name);
-    return 0;
+    if (!okay_to_modify( output_bodies, "TWEAK" ))
+      return 0;
   }
+  else
+  {
+    if ( contains_intermediate_geom(output_bodies))
+    {
+      PRINT_ERROR("%s surfaces on volumes containing virtual geometry\n"
+        "       is not allowed.\n"
+        "       Delete virtual geometry on these volumes before operation.\n",
+        name);
+      return 0;
+    }
+  }
 
   // Get engine and corresponding geom entities
   GeometryModifyEngine* gme_ptr;
-  gme_ptr = common_modify_engine( input_faces, output_surfaces );
+  gme_ptr = common_modify_engine( input_faces, output_surfaces, allow_composites );
   if (!gme_ptr)
   {
     PRINT_ERROR("%s surfaces on volumes containing surfaces from different\n"
@@ -7348,9 +11003,6 @@
   if( input_vertices.size() == 0 )
     return 0;
 
-
-
-
   // Get parent bodies
   DLIList<ModelEntity*> query_input(input_vertices.size()), query_output;
   CAST_LIST_TO_PARENT(input_vertices, query_input);
@@ -7381,10 +11033,1416 @@
 }
 
 //=============================================================================
-// 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.
+// Description: The user selects a surface they would like to idealize and also selects a radius
+//				size for fillets.  The user also specifies whether to consider internal and/or external fillets.
+//              The program will identify fillets which meet the users criteria and tweak remove them automatically.
+//              There is also a preview and exclude curve capability.
+// Author     : Jonathan Bugman
+// Date       : 10/23/2008
+//=============================================================================
+CubitStatus GeometryModifyTool::idealize_fillet_geometry(DLIList<RefEntity*> idealize_entity,
+                                                         DLIList<RefEntity*> exclude_entity,
+                                                         double fillet_rad,
+                                                         CubitBoolean internal_flg,
+                                                         CubitBoolean external_flg,
+													     CubitBoolean preview)
+{
+    //cast the DLIList<RefEntity> to a DLIList<RefFace>
+    DLIList<RefFace*> face_to_idealize;
+    CAST_LIST(idealize_entity, face_to_idealize, RefFace);
+
+    //grabbing geometry tolerance
+    double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance(),temp_fillet_radius;
+
+    //grabbing all the curve loops ONLY from surfaces which are a sheet body
+    int y, i, j, z;
+    DLIList<RefFace*> sheet_body_idealize_face;
+    
+    for(i=0; i<face_to_idealize.size(); i++)
+    {
+        RefFace* target_face = face_to_idealize.get_and_step();
+        DLIList<Shell*> shell_list;
+        target_face->shells(shell_list);
+        for(j=0; j<shell_list.size(); j++)
+        {
+            Shell* target_shell = shell_list.get_and_step();
+            if(target_face->is_nonmanifold( (GroupingEntity*)target_shell ) )
+            {         
+                sheet_body_idealize_face.append(face_to_idealize[i]);
+            }
+        }
+    }
+
+    face_to_idealize.clean_out();
+
+    //this section is going to remove all excluded curves loopsm from the 'master' loopsm list
+    DLIList<Curve*> exclude_cuves;
+    DLIList <Body*> old_body_list;
+    if(exclude_entity.size()>0)
+    {
+        //cast the exclude DLIList<RefEntity> to DLIList<RefEdge>
+        DLIList<RefEdge*> exclude_edge;
+        CAST_LIST(exclude_entity, exclude_edge, RefEdge);
+
+        //switching the DLIList<RefEdge> to DLIList<Curve>
+        GeometryModifyEngine* gme_ptr1;
+        gme_ptr1 = tweak_setup(exclude_edge,"idealize",old_body_list,exclude_cuves);
+        exclude_edge.clean_out();
+    }
+
+    //switching the DLIList<RefFace> to DLIList<Surface>
+    GeometryModifyEngine* gme_ptr;
+    DLIList<Surface*> sheet_body_idealize_surface;
+    gme_ptr = tweak_setup(sheet_body_idealize_face,"idealize",old_body_list,sheet_body_idealize_surface);
+    sheet_body_idealize_face.clean_out();
+
+    //grab all the loops from each sheet body surface
+    DLIList <LoopSM*> idealize_loopSM_list;
+    for(y=0;y<sheet_body_idealize_surface.size();y++)
+    {
+        sheet_body_idealize_surface[y]->loopsms(idealize_loopSM_list);
+    }
+    sheet_body_idealize_surface.clean_out();
+
+    //search through possible fillet curves filtering only for curves of type arc
+    //if it is an arc, does it have a straight line on both sides of it, if so'
+    //check the radius of the arc and if it passes test add it to the list of curves to be tweaked removed
+    DLIList <Curve*> master_curve_remove_list,possible_fillet_arcs,potential_fillet,internal_fillet, external_fillet, attached_curves;
+    CubitVector fillet_center_point, intersection_pt,arc_mid,test_point;
+    DLIList <Point*> arc_vertices;
+    for(y=0;y<idealize_loopSM_list.size();y++)
+    {
+        idealize_loopSM_list[y]->curves(possible_fillet_arcs);
+        //doing this as a performance boost, it'll keep the code out of the next couple of for loops for situations
+        //where there is no fillet possible, for instance, a hole with 2 curves will never be a fillet
+        if(possible_fillet_arcs.size()>3)
+        {
+            for(i=0;i<possible_fillet_arcs.size();i++)
+            {
+                if(possible_fillet_arcs[i]->geometry_type() == ARC_CURVE_TYPE &&
+                    exclude_cuves.is_in_list(possible_fillet_arcs[i])==CUBIT_FALSE)
+                {
+                    possible_fillet_arcs[i]->points(arc_vertices);
+                    //don't need to check for one point as in a hole because I have a check that there needs to be
+                    //at least 3 curves in the loop
+
+                    //this is to check that there is only one curve attached to the arc
+                    for(z=0;z<arc_vertices.size();z++)
+                    {
+                        arc_vertices[z]->curves(attached_curves);
+                        if(attached_curves.size()!=2)
+                        {
+                            //I dont' think this break point is going to kick me far enough out of the for loop
+                            break;
+                        }
+                    }
+
+                    possible_fillet_arcs[i]->mid_point(arc_mid);
+                    possible_fillet_arcs[i]->get_center_radius(fillet_center_point,temp_fillet_radius);
+                    test_point = arc_mid + geo_tol * (fillet_center_point-arc_mid);
+                    DLIList<Surface*> test_surf;
+                    idealize_loopSM_list[y]->surfaces(test_surf);
+
+                    //this may be dangerous but I'm assuming that a loop is on only one surface
+                    CubitPointContainment cpc = test_surf[0]->point_containment(test_point);
+                    if(temp_fillet_radius <= fillet_rad && cpc==CUBIT_PNT_INSIDE)
+                    {
+                        external_fillet.append(possible_fillet_arcs[i]);
+                    }
+                    else if(temp_fillet_radius <= fillet_rad && cpc==CUBIT_PNT_OUTSIDE)
+                    {
+                        internal_fillet.append(possible_fillet_arcs[i]);
+                    }
+                }
+            }
+        }
+        possible_fillet_arcs.clean_out();
+    }
+
+    if(internal_flg==CUBIT_TRUE)
+    {
+        master_curve_remove_list+=internal_fillet;
+    }
+    if(external_flg==CUBIT_TRUE)
+    {
+        master_curve_remove_list+=external_fillet;
+    }
+
+    //if no arcs are found to be removed, warn the user.
+    if(master_curve_remove_list.size()==0)
+    {
+        PRINT_INFO( "Failed to find any fillets which met users requirements\n\n" );
+        //I'm returning success here even though no curves were found
+        return CUBIT_SUCCESS;
+    }
+    else if(preview == CUBIT_TRUE)
+    {
+        DLIList<BodySM*> new_bodysm_list;
+        bool old_error_flag = GET_ERROR_FLAG();
+        SET_ERROR_FLAG(false); // don't throw any tweak_remove errors
+
+        CubitStatus stat = gme_ptr->tweak_remove(master_curve_remove_list, new_bodysm_list,CUBIT_FALSE, CUBIT_TRUE );
+
+        SET_ERROR_FLAG(old_error_flag); // turn errors back on 
+        if(stat==CUBIT_FAILURE)
+        {
+            PRINT_WARNING("At least one of the fillets which met your requirements \n"
+                "           can't be preview due to the curve's geometry\n");
+        }
+
+        //output the number of holes or slots which were found
+        PRINT_INFO("Found %d fillets which met idealization parameters\n\n", master_curve_remove_list.size());
+        return CUBIT_SUCCESS;
+    }
+    else
+    {
+        DLIList<BodySM*> new_bodysm_list;
+        bool old_error_flag = GET_ERROR_FLAG();
+        SET_ERROR_FLAG(false); // don't throw any tweak_remove errors
+
+        //pass master_curve_remove_list to the tweak_remove command
+        CubitStatus stat = gme_ptr->tweak_remove(master_curve_remove_list, new_bodysm_list,CUBIT_FALSE, CUBIT_FALSE );
+        if(stat==CUBIT_FAILURE)
+        {
+            PRINT_WARNING("At least one of the fillets which met your requirements \n"
+                "           can't be tweaked due to the curve's geometry\n");
+        }
+        SET_ERROR_FLAG(old_error_flag); // turn errors back on 
+
+        //update DAG
+        DLIList<Body*> new_body_list;
+        stat = finish_sm_op( old_body_list, new_bodysm_list ,new_body_list );
+        //output the number of holes or slots which were found
+        PRINT_INFO("Found %d fillets which met idealization parameters\n\n", master_curve_remove_list.size());
+        return CUBIT_SUCCESS;
+    }
+}
+
+//=============================================================================
+// Description: The user selects a surface they would like to idealize and also selects a radius
+//				size for holes and or selects a radius and length for slots.  The program will identify
+//              'holes' and 'slots' which meet the users criteria and tweak remove them automatically.
+//              There is also a preview and exclude curve capability.
+// Author     : Jonathan Bugman
+// Date       : 10/23/2008
+//=============================================================================
+CubitStatus GeometryModifyTool::idealize_hole_slot_geometry(DLIList<RefEntity*> idealize_entity,
+                                                            DLIList<RefEntity*> exclude_entity,
+                                                            double arc_radius,
+                                                            double slot_arc_radius,
+                                                            double slot_length,
+													        CubitBoolean preview)
+{
+    //cast the DLIList<RefEntity> to a DLIList<RefFace>
+    DLIList<RefFace*> face_to_idealize;
+    CAST_LIST(idealize_entity, face_to_idealize, RefFace);
+
+    //grabbing geometry tolerance
+    double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance();
+
+    //grabbing all the curve loops ONLY from surfaces which are a sheet body
+    int y=0, i=0, j=0;
+    DLIList<RefFace*> sheet_body_idealize_face;
+
+    for(i=0; i<face_to_idealize.size(); i++)
+    {
+        RefFace* target_face = face_to_idealize.get_and_step();
+        DLIList<Shell*> shell_list;
+        target_face->shells(shell_list);
+        for(j=0; j<shell_list.size(); j++)
+        {
+            Shell* target_shell = shell_list.get_and_step();
+            if(target_face->is_nonmanifold( (GroupingEntity*)target_shell ) )
+            {         
+                sheet_body_idealize_face.append(face_to_idealize[i]);
+            }
+        }
+    }
+
+    //if no faces to idealize that pass requirements, error out a warning message
+    if(sheet_body_idealize_face.size()==0)
+    {
+        //I'm returning success here even though no surfaces found that meet shell requirements set above
+        {
+            PRINT_INFO( "Failed to find any feature(s) which met user requirements\n\n" );
+        }
+        return CUBIT_SUCCESS;
+    }
+
+    //temp_body_ptr = face_to_idealize[y]->body();
+    //if(temp_body_ptr->is_sheet_body())
+    //{
+    //    sheet_body_idealize_face.append(face_to_idealize[y]);
+    //}
+
+    face_to_idealize.clean_out();
+
+    //switching the DLIList<RefFace> to DLIList<Surface>
+    GeometryModifyEngine* gme_ptr;
+    DLIList <Body*> old_body_list;
+    DLIList<Surface*> sheet_body_idealize_surface;
+    gme_ptr = tweak_setup(sheet_body_idealize_face,"idealize",old_body_list,sheet_body_idealize_surface);
+    sheet_body_idealize_face.clean_out();
+
+    //grab all the loops from each sheet body surface
+    DLIList <LoopSM*> idealize_loopSM_list;
+    for(y=0;y<sheet_body_idealize_surface.size();y++)
+    {
+            sheet_body_idealize_surface[y]->loopsms(idealize_loopSM_list);
+    }
+    sheet_body_idealize_surface.clean_out();
+
+    //this section is going to remove all excluded curves loopsm from the 'master' loopsm list
+    if(exclude_entity.size()>0)
+    {
+        //cast the exclude DLIList<RefEntity> to DLIList<RefEdge>
+        DLIList<RefEdge*> exclude_edge;
+        CAST_LIST(exclude_entity, exclude_edge, RefEdge);
+        
+        //switching the DLIList<RefEdge> to DLIList<Curve>
+        DLIList<Curve*> exclude_cuves;
+        GeometryModifyEngine* gme_ptr1;
+        gme_ptr1 = tweak_setup(exclude_edge,"idealize",old_body_list,exclude_cuves);
+        exclude_edge.clean_out();
+
+        //grabbing all the curve loops from the given excluded curves
+        DLIList <LoopSM*> exclude_loops;
+        for(y=0;y<exclude_cuves.size();y++)
+        {
+            exclude_cuves[y]->loopsms(exclude_loops);
+        }
+        exclude_cuves.clean_out();
+
+        //remove the excluded loops from the list of sheet body loopsms
+        idealize_loopSM_list -= exclude_loops;
+    }
+
+    //removing all the external loops from the list as they will not be tweak removed
+    DLIList <LoopSM*> possible_internal_LoopSM_list;
+    for(y=0;y<idealize_loopSM_list.size();y++)
+    {
+        if(idealize_loopSM_list[y]->loop_type() == LOOP_TYPE_HOLE)
+        {
+            possible_internal_LoopSM_list.append(idealize_loopSM_list[y]);
+        }
+    }
+    idealize_loopSM_list.clean_out();
+    DLIList <Curve*> hole_curves_to_remove;          //hole_curves_to_remove is the curves selected for removal out of the 'hole' search algorithm
+    DLIList <Curve*> master_curve_remove_list;
+    DLIList <LoopSM*> arc_LoopSM_list;
+    DLIList <Surface*> temp_list;
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    //this begins the hole search algorithm
+    //if no arc radius given, skip hole search algorithm
+    if(arc_radius!=CUBIT_DBL_MAX)
+    {
+        DLIList <LoopSM*> not_hole_loop;        //loops which don't meet the all curves are arc type filter
+        DLIList <Curve*> possible_internal_arcs;
+
+        //search through possible internal curves filtering only for curves of type arc
+        //if one of the curves in a loop is not an arc, add that loop to the not_hole_loop list
+        for(y=0;y<possible_internal_LoopSM_list.size();y++)
+        {
+            possible_internal_arcs.clean_out();
+            possible_internal_LoopSM_list[y]->curves(possible_internal_arcs);
+            for(i=0;i<possible_internal_arcs.size();i++)
+            {
+                temp_list.clean_out();
+                possible_internal_arcs[i]->surfaces(temp_list);
+                //check whether or not curve is of arc type and whether it is attached to more than one surface
+                if( possible_internal_arcs[i]->geometry_type() != ARC_CURVE_TYPE || temp_list.size() != 1)
+                {               
+                    not_hole_loop.append(possible_internal_LoopSM_list[y]);
+                    break;
+                }
+            }
+        }
+
+        //change name of possible_internal_LoopSM_list to arc_LoopSM_list
+        arc_LoopSM_list = possible_internal_LoopSM_list;
+        //subtract from the possible loops the loops which don't have curves which are all arcs or are attached to more than two surfaces
+        arc_LoopSM_list-=not_hole_loop;
+        not_hole_loop.clean_out();
+
+        //this next filter checks to make sure that all arcs of the same loop share the same
+        //radius center within the geometry tolerance
+        CubitVector arc_center_point, arc_center_point1;
+        DLIList <LoopSM*> not_center_arc_loop;
+        double rad_distance, temp_arc_radius , temp_arc_radius1;
+
+        //this for loop is going to check that each loops arc curves have the same center radius point
+        //if not you can remove that loop as a possibility for being added to the tweak_remove command
+        for(y=0;y<arc_LoopSM_list.size();y++)
+        {
+            //clean out curve list before grabbing a new loop
+            hole_curves_to_remove.clean_out();
+            arc_LoopSM_list[y]->curves(hole_curves_to_remove);
+            //iterate across the hole_curves_to_remove size
+            for (i=0;i<hole_curves_to_remove.size();i++)
+            {
+                //if you are on the first index, we need to set a baseline radius point
+                if(i==0)
+                {
+                    hole_curves_to_remove[i]->get_center_radius(arc_center_point,temp_arc_radius);
+                    //if this is the only arc in the loop go ahead and check if it meets specified arc parameter
+                    //if it doesn't meet the users parameter add the loop to the not_center_arc_loop list
+                    if(temp_arc_radius >= arc_radius && hole_curves_to_remove.size()==1)
+                    {
+                        not_center_arc_loop.append(arc_LoopSM_list[y]);
+                        break;
+                    }
+                }
+                //now compare the other arc center points to the baseline, if it ever fails the users parameter
+                //add the loop to the not_center_arc_loop list
+                else
+                {
+                    hole_curves_to_remove[i]->get_center_radius(arc_center_point1,temp_arc_radius1);
+                    rad_distance = arc_center_point.distance_between_squared(arc_center_point1);
+                    if(rad_distance > geo_tol || temp_arc_radius >= arc_radius)
+                    {
+                        not_center_arc_loop.append(arc_LoopSM_list[y]);
+                        break;
+                    }
+                }
+            }
+        }
+
+        //remove loops which didn't have perfect circular holes from the arc_loopsm_list
+        arc_LoopSM_list -= not_center_arc_loop;
+        for(y=0;y<arc_LoopSM_list.size();y++)
+        {
+            arc_LoopSM_list[y]->curves(hole_curves_to_remove);
+        }
+        master_curve_remove_list+=hole_curves_to_remove;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    //this begins the slot search algorithm
+    DLIList<LoopSM*> removable_slot_loop;
+    if(slot_arc_radius!=CUBIT_DBL_MAX || slot_length!=CUBIT_DBL_MAX)
+    {
+        DLIList<LoopSM*> four_curve_possible_slot;
+        DLIList<LoopSM*> possible_slot;
+        DLIList<Curve*> internal_curves_in_loop;
+
+        //checks to make sure the loop has only four curves - may want to expand this in the future
+        for(y=0;y<possible_internal_LoopSM_list.size();y++)
+        {
+            possible_internal_LoopSM_list[y]->curves(internal_curves_in_loop);
+            if(internal_curves_in_loop.size()==4)
+            {
+                four_curve_possible_slot.append(possible_internal_LoopSM_list[y]);
+            }
+            internal_curves_in_loop.clean_out();
+        }
+
+
+        //check to make sure it alternates straight line, arc, etc...
+        for(y=0;y<four_curve_possible_slot.size();y++)
+        {
+            four_curve_possible_slot[y]->curves(internal_curves_in_loop);
+
+            if(internal_curves_in_loop[0]->geometry_type() == ARC_CURVE_TYPE &&
+                internal_curves_in_loop[1]->geometry_type() == STRAIGHT_CURVE_TYPE &&
+                internal_curves_in_loop[2]->geometry_type() == ARC_CURVE_TYPE &&
+                internal_curves_in_loop[3]->geometry_type() == STRAIGHT_CURVE_TYPE)
+            {
+                int num_of_surfs=0;
+                for(i=0;i<internal_curves_in_loop.size();i++)
+                {
+                    temp_list.clean_out();
+                    internal_curves_in_loop[i]->surfaces(temp_list);
+                    num_of_surfs=num_of_surfs + temp_list.size();
+                }
+                if(num_of_surfs==4)
+                {
+                    possible_slot.append(four_curve_possible_slot[y]);
+                }
+            }
+            else if(internal_curves_in_loop[0]->geometry_type() == STRAIGHT_CURVE_TYPE &&
+                internal_curves_in_loop[1]->geometry_type() == ARC_CURVE_TYPE &&
+                internal_curves_in_loop[2]->geometry_type() == STRAIGHT_CURVE_TYPE &&
+                internal_curves_in_loop[3]->geometry_type() == ARC_CURVE_TYPE)
+            {
+                int num_of_surfs=0;
+                for(i=0;i<internal_curves_in_loop.size();i++)
+                {
+                    temp_list.clean_out();
+                    internal_curves_in_loop[i]->surfaces(temp_list);
+                    num_of_surfs=num_of_surfs + temp_list.size();
+                }
+                if(num_of_surfs==4)
+                {
+                    possible_slot.append(four_curve_possible_slot[y]);
+                }
+            }
+            internal_curves_in_loop.clean_out();
+        }
+
+        CubitVector arc_center_point;
+        double temp_arc_radius = CUBIT_DBL_MAX, curve_length = CUBIT_DBL_MAX;
+
+        //check to make sure that the rad and/or length meet users parameters
+        for(y=0;y<possible_slot.size();y++)
+        {
+            possible_slot[y]->curves(internal_curves_in_loop);
+            //if user specified rad, then passed rad_counter should = 2 after for loop completes
+            //if length specified, length_counter should =2 after for loop completes
+            int rad_counter = 0, length_counter = 0;
+            for(i=0;i<internal_curves_in_loop.size();i++)
+            {
+                //if curve is an arc and user specified a radius enter if statement
+                if( internal_curves_in_loop[i]->geometry_type() == ARC_CURVE_TYPE && slot_arc_radius!=CUBIT_DBL_MAX )
+                {
+                    //check the radius against the user inputed value
+                    internal_curves_in_loop[i]->get_center_radius(arc_center_point,temp_arc_radius);
+                    if(temp_arc_radius <= slot_arc_radius)
+                    {
+                        //if it passes rad test, add to rad_counter
+                        rad_counter++;
+                    }
+                }
+                else if(internal_curves_in_loop[i]->geometry_type() == STRAIGHT_CURVE_TYPE && slot_length!=CUBIT_DBL_MAX )
+                {
+                    //check the length against the user inputed value
+                    curve_length = internal_curves_in_loop[i]->get_arc_length();
+                    if(curve_length <= slot_length)
+                    {
+                        //if it passes rad test, add to length_counter
+                        length_counter++;
+                    }
+                }
+            }
+
+            //checks that if user specified length and radius constraint that its parameter passes for all four curves
+            if(slot_length!=CUBIT_DBL_MAX && slot_arc_radius!=CUBIT_DBL_MAX  && rad_counter==2 && length_counter==2)
+            {
+                removable_slot_loop.append(possible_slot[y]);
+            }
+
+            //if user only specified one length or arc parameter, it only needs to meet 2 criteria
+            else if((slot_length!=CUBIT_DBL_MAX  && length_counter==2) || (slot_arc_radius!=CUBIT_DBL_MAX  && rad_counter==2))
+            {
+                removable_slot_loop.append(possible_slot[y]);
+            }
+            internal_curves_in_loop.clean_out();
+        }
+        //add removable loops curves to the master_curve_remove_list list
+        for(y=0;y<removable_slot_loop.size();y++)
+        {
+            removable_slot_loop[y]->curves(master_curve_remove_list);
+        }
+    }
+
+    //if no arcs are found to be removed, warn the user.
+    if(master_curve_remove_list.size()==0)
+    {
+        //I'm returning success here even though no curves were found
+        {
+            PRINT_INFO( "Failed to find any feature(s) which met user requirements\n\n" );
+        }
+        return CUBIT_SUCCESS;
+    }
+    else if(preview == CUBIT_TRUE)
+    {
+        GfxPreview::clear();
+
+        for(i=0; i<master_curve_remove_list.size();i++)
+        {
+            CubitStatus result;
+            GMem g_mem;
+
+            // get the graphics
+            result = master_curve_remove_list[i]->get_geometry_query_engine()->
+                get_graphics( master_curve_remove_list[i], &g_mem );
+
+            if (result==CUBIT_FAILURE || g_mem.pointListCount == 0)
+            {
+                PRINT_WARNING("Unable to preview a curve\n" );
+                double len = master_curve_remove_list[i]->
+                    length_from_u(master_curve_remove_list[i]->start_param(),master_curve_remove_list[i]->end_param());
+
+                PRINT_WARNING("Curve len: %f\n",len);
+            }
+
+            // Draw the polyline
+            GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, CUBIT_BLUE );
+
+        }
+
+        //output the number of holes or slots which were found
+        PRINT_INFO("Found %d holes and %d slots which met idealization parameters\n\n", arc_LoopSM_list.size(),removable_slot_loop.size());
+        GfxPreview::flush();
+        return CUBIT_SUCCESS;
+    }
+    else
+    {
+        DLIList<BodySM*> new_bodysm_list;
+        //pass master_curve_remove_list to the tweak_remove command
+        CubitStatus stat = gme_ptr->tweak_remove(master_curve_remove_list, new_bodysm_list,CUBIT_FALSE, CUBIT_FALSE );
+
+        //update DAG
+        DLIList<Body*> new_body_list;
+        stat = finish_sm_op( old_body_list, new_bodysm_list ,new_body_list );
+        //output the number of holes or slots which were found
+        PRINT_INFO("Found %d holes, and %d slots which met idealization parameters\n\n", arc_LoopSM_list.size(), removable_slot_loop.size());
+        return CUBIT_SUCCESS;
+    }
+}
+
+//=============================================================================
+// Description: Create drop down surfaces from the external edges of a surface to another surface with options
+//	        Use it primarially when you have a doubler plate situation and you need
+//		to connect them together with surfaces to represent a weld
+// Author     : Jonathan Bugman
+// Date       : 02/07/2008
+//=============================================================================
+CubitStatus GeometryModifyTool::create_surface_doubler(DLIList<RefEntity*> doubler_entity,
+                                                       DLIList<RefEntity*> target_entity,
+                                                       DLIList<Body*> &body_list_out,
+                                                       CubitBoolean internal_flg,
+                                                       CubitBoolean extend_flg,
+                                                       CubitPlane *limit_plane,
+                                                       CubitVector sweep_direction,
+                                                       CubitBoolean preview)
+{
+	//need to switch the DLIList<RefEntity> to a DLIList<RefFace>
+	DLIList<RefFace*> doubler_face;
+	DLIList<RefFace*> target_face;
+	CAST_LIST( doubler_entity, doubler_face, RefFace);
+	CAST_LIST( target_entity, target_face, RefFace);
+
+	DLIList <Surface*> doubler_surface;
+	DLIList <Surface*> target_surface;
+	DLIList <Body*> old_body_list;
+	DLIList<RefFace*> tweak_face;
+	DLIList<Surface*> tweak_surface;
+	tweak_face+=doubler_face;
+	tweak_face+=target_face;
+	GeometryModifyEngine* gme_ptr;
+    int ii=0, i=0;
+
+	gme_ptr = tweak_setup(tweak_face,"doubler",old_body_list,tweak_surface);
+    int z;
+	for(z=0;z<doubler_face.size();z++)
+	{
+		doubler_surface.append(tweak_surface[z]);
+	}
+	for(z;z<tweak_face.size();z++)
+    {
+        target_surface.append(tweak_surface[z]);
+    }
+
+    DLIList<BodySM*> all_kept_bodies;
+    DLIList<BodySM*> body_convert;
+    DLIList<Surface*> copied_doubler_surface;
+    DLIList <BodySM*> tweak_target_bodySM;
+
+    for(z=0;z<doubler_surface.size();z++)
+    {
+        copied_doubler_surface.append(gme_ptr->make_Surface(doubler_surface[z]));
+        body_convert.append(copied_doubler_surface[z]->bodysm());
+    }
+
+    //each workflow is dependent on whether or not a sweep_direction is specified
+    if(sweep_direction == CubitVector(0,0,0))
+    {
+		DLIList<BodySM*> united_bodies;
+		DLIList<BodySM*> separate_bodies;
+		//this section takes all the doublers, unites them, and then splits them.  If only one body
+		//then skip the aforementioned two steps.
+		if(doubler_surface.size()==1)
+		{
+			separate_bodies=body_convert;
+		}
+		else
+		{
+			if(gme_ptr->unite(body_convert,united_bodies) == CUBIT_FAILURE || united_bodies.size()==0 )
+			{
+				PRINT_ERROR( "Command failed at unite command\n" );
+				return CUBIT_FAILURE;
+			}
+
+			if(gme_ptr->split_body(united_bodies[0],separate_bodies) == CUBIT_FAILURE || separate_bodies.size()==0)
+			{
+				PRINT_ERROR( "Command failed at separate command\n" );
+				return CUBIT_FAILURE;
+			}
+		}
+		for(z=0; z<separate_bodies.size();z++)
+		{
+			DLIList<Surface*> body_surface;
+			separate_bodies[z]->surfaces(body_surface);
+
+			DLIList<CubitVector> doubler_surface_center_points;
+			int d=0;
+			for(d=0;d<body_surface.size();d++)
+			{
+				doubler_surface_center_points.append(body_surface[d]->bounding_box().center());
+			}
+			CubitVector doubler_normal,doubler_center_pt,doubler_to_target_vector,target_center_pt;
+			double extrude_distance = 0.0;
+
+			//make sure that the normal of the surface is pointing towards the target surface
+			//the thicken command thickens in the direction of the surface normal, normals are checked using dot product check
+			CubitVector center_pt = body_surface[0]->bounding_box().center();
+			body_surface[0]->closest_point(center_pt,&doubler_center_pt,&doubler_normal);
+            //adding this for loop because of l bracket doublers may have the first target surface perpendicular to an opposite side doubler surface
+            //resulting in the code erroneously failing
+            double dot=0.0;
+            int mm;
+            for(mm=0; mm<target_surface.size();mm++)
+            {
+                target_surface[mm]->closest_point_trimmed(doubler_center_pt, target_center_pt);
+                doubler_to_target_vector = target_center_pt - doubler_center_pt;
+                dot = doubler_to_target_vector.x()*doubler_normal.x()+doubler_to_target_vector.y()*doubler_normal.y()+doubler_to_target_vector.z()*doubler_normal.z();
+                if(fabs(dot)>1E-6)
+                {
+                    mm=target_surface.size();
+                }
+            }
+            if(fabs(dot)<1E-6)
+            {
+                PRINT_ERROR( "Doubler and target surface are touching or are perpendicular to each other\n" );
+                for(ii =0;ii<separate_bodies.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = separate_bodies[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(separate_bodies[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+            else if(dot < 0)
+            {
+                if(gme_ptr->reverse_body(separate_bodies[z])==CUBIT_FAILURE)
+                {
+                    PRINT_ERROR( "Command failed at reverse body command.\n" );
+                    for(ii =0;ii<separate_bodies.size();ii++)
+                    {
+                        GeometryQueryEngine* gqe = separate_bodies[ii]->get_geometry_query_engine();
+                        gqe->delete_solid_model_entities(separate_bodies[ii]);
+                    }
+                    return CUBIT_FAILURE;
+                }
+                extrude_distance = 0.0001;
+            }
+            else
+			{
+				extrude_distance = 0.0001;
+			}
+
+			DLIList<BodySM*> thickened_doubler_bodySM;
+			DLIList<BodySM*> current_body;
+			current_body.append(separate_bodies[z]);
+
+            if(gme_ptr->thicken(current_body,thickened_doubler_bodySM,extrude_distance,CUBIT_FALSE) == CUBIT_FAILURE || thickened_doubler_bodySM.size()==0)
+            {
+                PRINT_ERROR( "Command failed at thicken command, this may be due to using a non-ACIS geometry engine\n" );
+                for(ii =0;ii<separate_bodies.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = separate_bodies[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(separate_bodies[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+
+			//need to grab the newly created surface opposite the user selected one from the thicken function to carry it through for the tweak target
+			DLIList<Surface*> thicken_surfaces;
+			thickened_doubler_bodySM[0]->surfaces(thicken_surfaces);
+			DLIList <Surface*> post_thicken_doublers;
+
+			int y=0;
+			for(y=0;y<doubler_surface_center_points.size();y++)
+			{
+				doubler_center_pt = doubler_surface_center_points[y];
+				int r=0;
+				for(r=0;r<thicken_surfaces.size();r++)
+				{
+					CubitVector test_center_pt = thicken_surfaces[r]->bounding_box().center();
+					if((test_center_pt-doubler_center_pt).length()<=.000001)
+					{
+						post_thicken_doublers.append(thicken_surfaces[r]);
+					}
+				}
+			}
+
+			DLIList <LoopSM*> doubler_loopSM_list;
+			DLIList <Curve*> doubler_external_curves;
+			Curve* test_external_curves1;
+			Curve* test_external_curves2;
+
+			//need to do this in order to grab all curves, not just external IMPORTANT:THIS HAS TO BE DONE BEFORE THE tweak? COMMAND!
+			for(y=0;y<post_thicken_doublers.size();y++)
+			{
+				post_thicken_doublers[y]->loopsms(doubler_loopSM_list);
+			}
+			for(i=0;i<doubler_loopSM_list.size();i++)
+			{
+				doubler_loopSM_list[i]->curves(doubler_external_curves);
+			}
+
+			doubler_loopSM_list.clean_out();
+            tweak_target_bodySM.clean_out();
+			DLIList <LoopSM*> test_loopSM_list;
+			DLIList <Curve*> thicken_external_curves;
+			DLIList <Surface*> tweak_target_surface = thicken_surfaces;
+
+            //stepping through the surfaces from the thicken body
+            for(i=0; i < thicken_surfaces.size(); i++)
+            {
+                thicken_surfaces[i]->loopsms(test_loopSM_list);
+                //grabbing the external curves from the current thicken_surface
+                test_loopSM_list[0]->curves(thicken_external_curves);
+                test_loopSM_list.clean_out();
+                int j=0;
+                for(j=0;j<thicken_external_curves.size();j++)
+                {
+                    //step through the first curve
+                    test_external_curves1 = thicken_external_curves[j];
+                    int k=0;
+                    for(k=0; k<doubler_external_curves.size();k++)
+                    {
+                        //while stepping through the doubler plate curves, compare them to the test_test_surface curves
+                        test_external_curves2 = doubler_external_curves[k];
+
+						//if the two are equal, they are touching the doulber and therefore are either the side surfaces or the doubler
+						if(test_external_curves2 == test_external_curves1)
+						{
+							//remove the surface from the tweak_target_surface list
+							tweak_target_surface.remove_all_with_value(thicken_surfaces[i]);
+							break;
+						}
+					}
+					if(test_external_curves2 == test_external_curves1)
+					{
+						break;
+					}
+
+				}
+				thicken_external_curves.clean_out();
+            }
+
+            //pass the found opposite surface into the tweak_target routine
+            if(gme_ptr->tweak_target(tweak_target_surface,target_surface,tweak_target_bodySM,extend_flg,limit_plane) == CUBIT_FAILURE || tweak_target_bodySM.size()==0)
+            {
+                PRINT_ERROR( "Command failed at Tweak_Target routine\n" );
+                for(ii =0;ii<thickened_doubler_bodySM.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = thickened_doubler_bodySM[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(thickened_doubler_bodySM[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+
+			//fill out a tweak_body_surface list from tweak_target routine
+			DLIList<Surface*> tweak_body_surfaces;
+			tweak_target_bodySM[0]->surfaces(tweak_body_surfaces);
+			DLIList <Curve*> tweak_external_curves;
+			doubler_external_curves.clean_out();
+			
+			//refilling DLIList's as needed based on internal_flg
+			//if we are not keeping internal surfaces we do not want it's curves in the doubler_external_curves list
+			//otherwise if we are, we do want the curves in the list for the following sections for loop
+            if(internal_flg==CUBIT_FALSE)
+            {
+                int j=0;
+                for(i=0;i<post_thicken_doublers.size();i++)
+                {
+                    post_thicken_doublers[i]->loopsms(doubler_loopSM_list);
+                    for(j=0;j<doubler_loopSM_list.size();j++)
+                    {
+                      LoopType loop_type = doubler_loopSM_list[j]->loop_type();
+                      if(loop_type == LOOP_TYPE_EXTERNAL ||
+                         loop_type == LOOP_TYPE_U_PERIODIC ||
+                         loop_type == LOOP_TYPE_V_PERIODIC)
+                      {
+                          doubler_loopSM_list[j]->curves(doubler_external_curves);
+                          break;
+                      }
+                    }
+                    doubler_loopSM_list.clean_out();
+                }
+            }
+			else
+			{
+				for(i=0;i<post_thicken_doublers.size();i++)
+				{
+					post_thicken_doublers[i]->loopsms(doubler_loopSM_list);
+				}
+				for(i=0;i<doubler_loopSM_list.size();i++)
+				{
+					doubler_loopSM_list[i]->curves(doubler_external_curves);
+				}
+
+			}
+
+            DLIList <Surface*> surfaces_to_keep;
+            for(i=0;i<tweak_body_surfaces.size();i++)
+            {
+                tweak_body_surfaces[i]->loopsms(test_loopSM_list);
+
+                if(test_loopSM_list.size()==0)
+                {
+                    PRINT_ERROR( "Command failed to find any doubler drop down curves\n" );
+                    for(ii =0;ii<thickened_doubler_bodySM.size();ii++)
+                    {
+                        GeometryQueryEngine* gqe = thickened_doubler_bodySM[ii]->get_geometry_query_engine();
+                        gqe->delete_solid_model_entities(thickened_doubler_bodySM[ii]);
+                    }
+                    return CUBIT_FAILURE;
+                }
+
+                test_loopSM_list[0]->curves(tweak_external_curves);
+                test_loopSM_list.clean_out();
+
+				int j=0;
+				for(j=0;j<tweak_external_curves.size();j++)
+				{
+					test_external_curves1 = tweak_external_curves[j];
+
+					int k=0;
+					for(k=0; k<doubler_external_curves.size();k++)
+					{
+						//while stepping through the doubler plate curves, compare them to the test_loop_list
+						test_external_curves2 = doubler_external_curves[k];
+
+						if(test_external_curves2 == test_external_curves1)
+						{
+							surfaces_to_keep.append(tweak_body_surfaces[i]);
+							break;
+						}
+					}
+					if(test_external_curves2 == test_external_curves1)
+					{
+						break;
+					}
+				}
+				tweak_external_curves.clean_out();
+			}
+
+            if(surfaces_to_keep.size()==0)
+            {
+                PRINT_ERROR( "Failed to find and keep surfaces\n" );
+                for(ii =0;ii<tweak_target_bodySM.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+
+			//do this to remove the copied_doubler_surface since we no longer need the surface anymore
+			int c=0;
+			for(c=0;c<post_thicken_doublers.size();c++)
+			{
+				surfaces_to_keep.remove_all_with_value(post_thicken_doublers[c]);
+			}
+
+			DLIList <Surface*> surfaces_to_remove = tweak_body_surfaces;
+			surfaces_to_remove -= surfaces_to_keep;
+			DLIList<BodySM*> resulting_bodies;
+
+			//remove all surfaces in the surfaces_to_remove list
+            if(gme_ptr->tweak_remove(surfaces_to_remove,resulting_bodies,CUBIT_FALSE) == CUBIT_FAILURE || resulting_bodies.size()==0)
+            {
+                PRINT_ERROR( "Command failed at Tweak_Remove routine\n" );
+                for(ii =0;ii<tweak_target_bodySM.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+            all_kept_bodies+=resulting_bodies;
+        }
+    }	
+	else
+	{
+		DLIList<BodySM*> swept_bodies;
+		DLIList<BodySM*> swept_doubler_bodySM;
+
+		//take the copied_doubler_surface and extrude it along the sweep_direction to create a body
+		for(z=0;z<copied_doubler_surface.size();z++)
+		{
+			DLIList<GeometryEntity*> DLIList_copied_doubler_surface;
+            DLIList_copied_doubler_surface.append(copied_doubler_surface[z]);
+            if(gme_ptr->sweep_translational(DLIList_copied_doubler_surface,swept_doubler_bodySM,sweep_direction*0.0001,0.0,0,CUBIT_FALSE,CUBIT_FALSE) == CUBIT_FAILURE || swept_doubler_bodySM.size()==0)
+            {
+                PRINT_ERROR( "Command failed at sweep->extrude command\n" );
+                for(ii =0;ii<body_convert.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = body_convert[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(body_convert[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+			swept_bodies+=swept_doubler_bodySM;
+			swept_doubler_bodySM.clean_out();
+		}
+
+		DLIList<BodySM*> united_bodies;
+		DLIList<BodySM*> separate_bodies;
+		//if more than one body, unite and split the newly created bodies, if only one body skip this step
+		//as the unite will fail
+		if(swept_bodies.size()==1)
+		{
+			separate_bodies=swept_bodies;
+		}
+		else
+		{
+			if(gme_ptr->unite(swept_bodies,united_bodies) == CUBIT_FAILURE || united_bodies.size()==0 )
+			{
+				PRINT_ERROR( "Command failed at unite command\n" );
+				return CUBIT_FAILURE;
+			}
+
+			if(gme_ptr->split_body(united_bodies[0],separate_bodies) == CUBIT_FAILURE || separate_bodies.size()==0)
+			{
+				PRINT_ERROR( "Command failed at separate command\n" );
+				return CUBIT_FAILURE;
+			}
+		}
+
+		//create another copy of copied_doubler_surface since copied_doubler_surface is going to be manipulated
+		DLIList<Surface*> temp_copied_doubler_surface=copied_doubler_surface;
+		for(z=0;z<separate_bodies.size();z++)
+		{
+			//need to grab the newly created surface opposite the user selected one from the thicken function to carry it through for the tweak target
+			//this will need to be changed to a for loop to account for multiple thickened bodies if we impliment multiple doubler surfaces
+			DLIList<Surface*> thicken_surfaces;
+			separate_bodies[z]->surfaces(thicken_surfaces);
+
+			//initializing a lot of variables to be used in the next few steps
+			DLIList<Surface*> master_surface_remove_list;
+			DLIList <Curve*> thicken_external_curves;
+			DLIList<Surface*> tweak_target_surface;
+			DLIList<Surface*> surfaces_to_remove;
+
+			//using a centerpoint of the surfaces, I want to find out which surface from the recently swept bodies corresponds to the surface of the body closest the target
+			//this has to be done because sweep_translational moves the source surface.  Thicken on the otherhand does and doesn't based on number of surfaces being thickened.
+			int y=0;
+			for(y=0;y<temp_copied_doubler_surface.size();y++)
+			{
+				CubitVector doubler_center_pt = temp_copied_doubler_surface[y]->bounding_box().center();
+				int r=0;
+				for(r=0;r<thicken_surfaces.size();r++)
+				{
+					CubitVector test_center_pt = thicken_surfaces[r]->bounding_box().center();
+					if((test_center_pt-doubler_center_pt).length()<=.000001)
+					{
+						tweak_target_surface.append(thicken_surfaces[r]);
+						surfaces_to_remove.append(temp_copied_doubler_surface[y]);
+					}
+				}
+			}
+			//remove the manipulated surfaces from the temp_copied_doubler_surface list
+			temp_copied_doubler_surface-=surfaces_to_remove;
+			surfaces_to_remove.clean_out();
+
+			//grab all the curves of the doubler
+			DLIList <Curve*> doubler_external_curves;
+			DLIList <LoopSM*> doubler_loopSM_list;
+			for(y=0;y<tweak_target_surface.size();y++)
+			{
+				tweak_target_surface[y]->loopsms(doubler_loopSM_list);
+			}
+
+			for(i=0;i<doubler_loopSM_list.size();i++)
+			{
+				doubler_loopSM_list[i]->curves(doubler_external_curves);
+			}
+
+			Surface* temp_test_surface;
+			DLIList <Surface*> doubler_surface_for_this_body = thicken_surfaces;
+			Curve* test_external_curves1;
+			Curve* test_external_curves2;
+			DLIList <LoopSM*> test_loopSM_list;
+
+			for(i=0; i < thicken_surfaces.size(); i++)
+			{
+				//step through the thickened bodies surfaces
+				thicken_surfaces[i]->loopsms(test_loopSM_list);
+				temp_test_surface = thicken_surfaces[i];
+				//grabbing the external curve loop from the face and making it a DLIList <RefEdge*>
+				test_loopSM_list[0]->curves(thicken_external_curves);
+
+				int j=0;
+				for(j=0;j<thicken_external_curves.size();j++)
+				{
+					//step through the loop list
+					test_external_curves1 = thicken_external_curves[j];
+
+					int k=0;
+					for(k=0; k<doubler_external_curves.size();k++)
+					{
+						//while stepping through the doubler plate curves, compare them to the test_loop_list
+						test_external_curves2 = doubler_external_curves[k];
+
+						if(test_external_curves2 == test_external_curves1)
+						{
+							doubler_surface_for_this_body.remove_all_with_value(thicken_surfaces[i]);
+							break;
+						}
+					}
+					if(test_external_curves2 == test_external_curves1)
+					{
+						break;
+					}
+				}
+
+				thicken_external_curves.clean_out();
+				thicken_external_curves.reset();
+                test_loopSM_list.clean_out();
+            }
+
+            //DLIList <BodySM*> tweak_target_bodySM
+            tweak_target_bodySM.clean_out();
+            if(gme_ptr->tweak_target(tweak_target_surface,target_surface,tweak_target_bodySM,extend_flg,limit_plane) == CUBIT_FAILURE || tweak_target_bodySM.size()==0)
+            {
+                PRINT_ERROR( "Command failed at Tweak_Target routine\n" );
+                for(ii =0;ii<body_convert.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = body_convert[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(body_convert[ii]);
+                }
+                return CUBIT_FAILURE;
+            }
+
+			//make note of the doubler_surface and add it to the delete list
+			master_surface_remove_list+=doubler_surface_for_this_body;
+
+			//clean out these DLIList's as they will be used later on
+			doubler_loopSM_list.clean_out();
+			doubler_external_curves.clean_out();
+
+			//refilling DLIList's as needed based on internal_flg
+			//basically if surfaces share a curve, that surface will be kept so if you don't want the internal surfaces
+			//create the list without the internal curves and they'll be removed
+            if(internal_flg==CUBIT_FALSE)
+            {
+                int j=0;
+                for(i=0;i<doubler_surface_for_this_body.size();i++)
+                {
+                    doubler_surface_for_this_body[i]->loopsms(doubler_loopSM_list);
+                    for(j=0;j<doubler_loopSM_list.size();j++)
+                    {
+                      LoopType loop_type = doubler_loopSM_list[j]->loop_type();
+                      if(loop_type == LOOP_TYPE_EXTERNAL ||
+                         loop_type == LOOP_TYPE_U_PERIODIC ||
+                         loop_type == LOOP_TYPE_V_PERIODIC)
+                      {
+                          doubler_loopSM_list[j]->curves(doubler_external_curves);
+                          break;
+                      }
+
+                    }
+                    doubler_loopSM_list.clean_out();
+                }
+            }
+            else
+			{
+				for(i=0;i<doubler_surface_for_this_body.size();i++)
+				{
+					doubler_surface_for_this_body[i]->loopsms(doubler_loopSM_list);
+				}
+				for(i=0;i<doubler_loopSM_list.size();i++)
+				{
+					doubler_loopSM_list[i]->curves(doubler_external_curves);
+				}
+			}
+
+			//recreate the thicken_surfaces list based now on the bodies after the tweak_target command
+			thicken_surfaces.clean_out();
+			tweak_target_bodySM[0]->surfaces(thicken_surfaces);
+
+			DLIList <Surface*> surfaces_to_keep;
+			surfaces_to_remove = thicken_surfaces;
+			DLIList <Curve*> tweak_external_curves;
+			
+			for(i=0;i<thicken_surfaces.size();i++)
+			{
+				thicken_surfaces[i]->loopsms(test_loopSM_list);
+				//grabs the external curves from face
+				test_loopSM_list[0]->curves(tweak_external_curves);
+
+				int j=0;
+				for(j=0;j<tweak_external_curves.size();j++)
+				{
+					//step through the loop list
+					test_external_curves1 = tweak_external_curves[j];
+
+					int k=0;
+					for(k=0; k<doubler_external_curves.size();k++)
+					{
+						//while stepping through the doubler plate curves, compare them to the test_loop_list
+						test_external_curves2 = doubler_external_curves[k];
+
+						if(test_external_curves2 == test_external_curves1)
+						{
+							surfaces_to_keep.append(thicken_surfaces[i]);
+							break;
+						}
+					}
+					if(test_external_curves2 == test_external_curves1)
+					{
+						break;
+					}
+				}
+				test_loopSM_list.clean_out();
+				tweak_external_curves.clean_out();
+			}
+
+			if(surfaces_to_keep.size()==0)
+			{
+				PRINT_ERROR( "Failed to find and keep tweak_target surfaces\n" );
+                for(ii =0;ii<tweak_target_bodySM.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
+                }
+				return CUBIT_FAILURE;
+			}
+
+			//subtract surfaces
+			surfaces_to_remove -= surfaces_to_keep;
+			master_surface_remove_list+=surfaces_to_remove;
+
+			DLIList<BodySM*> resulting_bodies;
+
+			if(gme_ptr->tweak_remove(master_surface_remove_list,resulting_bodies,CUBIT_FALSE) == CUBIT_FAILURE || resulting_bodies.size()==0)
+			{
+				PRINT_ERROR( "Command failed at Tweak_Remove routine\n" );
+                for(ii =0;ii<tweak_target_bodySM.size();ii++)
+                {
+                    GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
+                    gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
+                }
+				return CUBIT_FAILURE;
+			}
+
+			//all_kept_bodies is a list of bodies that will eventually be passed into finish_sm_op at the end
+			all_kept_bodies+=resulting_bodies;
+		}
+    }
+
+    if(preview==CUBIT_FALSE)
+    {
+        DLIList<BodySM*> bodies_to_unite;
+        //check to see if their is only one body.  If only one body skip over the unite and split because
+        //the unite command will fail (there is a check at the beginning to return cubit_failure)
+        //append the original doubler surfaces to the resulting body list
+
+        for(i=0;i<doubler_surface.size();i++)
+        {
+            all_kept_bodies.insert_first(doubler_surface[i]->bodysm());
+        }
+        if(all_kept_bodies.size()!=1)
+        {
+            if(gme_ptr->unite(all_kept_bodies,bodies_to_unite) == CUBIT_FAILURE || bodies_to_unite.size()==0 )
+            {
+                PRINT_ERROR( "Command failed at unite command\n" );
+                return CUBIT_FAILURE;
+            }
+            all_kept_bodies.clean_out();
+            if(gme_ptr->split_body(bodies_to_unite[0],all_kept_bodies) == CUBIT_FAILURE || all_kept_bodies.size()==0)
+            {
+                PRINT_ERROR( "Command failed at separate command\n" );
+                return CUBIT_FAILURE;
+            }
+        }
+        else
+        {
+                PRINT_WARNING( "Command may have failed at finding doubler surface(s) and appending them to the drop-down surfaces\n" );
+                return CUBIT_FAILURE;
+        }
+        
+        //update DAG
+		CubitStatus stat;
+		stat = finish_sm_op( old_body_list, all_kept_bodies ,body_list_out );
+		return CUBIT_SUCCESS;
+	}
+	else
+	{
+		DLIList<Curve*> kept_curves;
+		for(i =0;i<all_kept_bodies.size();i++)
+		{
+			all_kept_bodies[i]->curves(kept_curves);
+		}
+
+        GfxPreview::clear();
+
+        for(i=0; i<kept_curves.size();i++)
+        {
+            CubitStatus result;
+            GMem g_mem;
+
+            // get the graphics
+            result = kept_curves[i]->get_geometry_query_engine()->
+                get_graphics( kept_curves[i], &g_mem );
+
+            if (result==CUBIT_FAILURE || g_mem.pointListCount == 0)
+            {
+                PRINT_WARNING("Unable to preview a curve\n" );;
+                double len = kept_curves[i]->
+                    length_from_u(kept_curves[i]->start_param(),kept_curves[i]->end_param());
+
+                PRINT_WARNING("Curve len: %f\n",len);
+            }
+
+            // Draw the polyline
+            GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, CUBIT_BLUE );
+        }
+        GfxPreview::flush();
+        for(ii =0;ii<tweak_target_bodySM.size();ii++)
+        {
+            GeometryQueryEngine* gqe = tweak_target_bodySM[ii]->get_geometry_query_engine();
+            gqe->delete_solid_model_entities(tweak_target_bodySM[ii]);
+        }
+        return CUBIT_SUCCESS;
+    }
+}
+
+//=============================================================================
+// 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 GeometryModifyTool::tweak_bend( DLIList<Body*> &bend_bodies,
+                                            DLIList<Body*> &new_body_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 )
+{
+    if (CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE)
+	{
+		if (keep_old_body)
+			CubitUndo::save_state();
+		else
+			CubitUndo::save_state_with_cubit_file( bend_bodies );
+    }
+    
+    DLIList<BodySM*> new_body_sm_list;
+    DLIList<BodySM*> bend_bodies_sm;
+    GeometryModifyEngine* engine;
+    engine = common_modify_engine(bend_bodies, bend_bodies_sm);
+    
+    if (!preview)
+    {
+        //do_attribute_setup();
+        //push_vg_attributes_before_modify(bend_bodies_sm);
+    }
+
+    CubitStatus result = engine->tweak_bend(
+            bend_bodies_sm,
+            new_body_sm_list,
+            neutral_root,
+            bend_axis,
+            bend_direction,
+            radius,
+            angle,
+            bend_regions,
+            width,
+            center_bend,
+            num_points,
+            keep_old_body,
+            preview);
+
+    if (result == CUBIT_FAILURE)
+    {
+        if (!preview)
+        {
+            //remove_pushed_attributes(bend_bodies_sm, bend_bodies);
+            //do_attribute_cleanup();
+        }
+        if (CubitUndo::get_undo_enabled())
+            CubitUndo::remove_last_undo();
+        return CUBIT_FAILURE;
+    }
+
+    if (preview == CUBIT_FALSE)
+    {
+        //restore_vg_after_modify(new_body_sm_list, bend_bodies, engine);
+        //remove_pushed_attributes(new_body_sm_list, bend_bodies);
+
+        // Update DAG
+        CubitStatus stat = finish_sm_op( bend_bodies, new_body_sm_list, new_body_list );
+        if (CubitUndo::get_undo_enabled())
+        {
+            if (stat == CUBIT_SUCCESS)
+                CubitUndo::note_result_bodies( new_body_list );
+            else
+                CubitUndo::remove_last_undo();
+        }
+
+        //do_attribute_cleanup();
+
+        // Update graphics
+        /*
+        bend_bodies.reset();
+        int i = 0;
+        for (i = 0; i < bend_bodies.size(); i++)
+        {
+            Body* body_ptr = bend_bodies.get_and_step();
+            body_ptr->notify_all_observers( GEOMETRY_MODIFIED );
+        }//*/
+        
+        // get list of entities to update
+        DLIList<RefEntity*> entities_to_update;
+        int i;
+        for(i=0; i < new_body_sm_list.size(); i++)
+        {
+            BodySM* bodysm = new_body_sm_list.get_and_step();
+            DLIList<TopologyBridge*> to_check;
+            DLIList<TopologyBridge*> tmp;
+            DLIList<Surface*> surfs;
+            bodysm->surfaces(surfs);
+            DLIList<Curve*> curves;
+            bodysm->curves(curves);
+            DLIList<Point*> points;
+            bodysm->points(points);
+            to_check.append(bodysm);
+            to_check.append(bodysm->lump());
+            CAST_LIST_TO_PARENT(surfs, tmp);
+            to_check += tmp;
+            CAST_LIST_TO_PARENT(curves, tmp);
+            to_check += tmp;
+            CAST_LIST_TO_PARENT(points, tmp);
+            to_check += tmp;
+
+            int k;
+            for(k=0; k<to_check.size(); k++)
+                if(BridgeManager* m = to_check.get_and_step()->bridge_manager())
+                    if(TopologyEntity* t = m->topology_entity())
+                        entities_to_update.append(CAST_TO(t, RefEntity));
+
+        }
+        // Update graphics
+        while (entities_to_update.size())
+            entities_to_update.pop()->notify_all_observers(GEOMETRY_MODIFIED);
+
+        return stat;
+    }
+
+    return CUBIT_SUCCESS;
+}
+
+
+
+//=============================================================================
+// Description: Chamfer curves on solid and 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.
 // Author     : Steve Storm
 // Date       : 03/25/05
 //=============================================================================
@@ -7395,30 +12453,6 @@
                                                CubitBoolean keep_old_body,
                                                CubitBoolean preview )
 {
-  // Make sure curves are not part of a sheet body
-  // Get unique volumes that the curves are attached to
-  DLIList<RefVolume*> ref_volume_list;
-  int i;
-  RefEdge *ref_edge_ptr;
-  for( i=ref_edge_list.size(); i--; )
-  {
-    ref_edge_ptr = ref_edge_list.get_and_step();
-    DLIList<RefVolume*> tmp_ref_volume_list;
-    ref_edge_ptr->ref_volumes( tmp_ref_volume_list );
-    ref_volume_list.merge_unique( tmp_ref_volume_list );
-  }
-
-  RefVolume *ref_volume_ptr;
-  for( i=ref_volume_list.size(); i--; )
-  {
-    ref_volume_ptr = ref_volume_list.get_and_step();
-    if( ref_volume_ptr->is_sheet() )
-    {
-      PRINT_ERROR( "Cannot chamfer curves on sheet bodies\n" );
-      return CUBIT_FAILURE;
-    }
-  }
-
   DLIList<Curve*> curve_list(ref_edge_list.size());
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
@@ -7427,6 +12461,14 @@
   if( !gme_ptr )
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do chamfering
   DLIList<BodySM*> new_bodysm_list;
   if( gme_ptr->tweak_chamfer( curve_list, left_offset, new_bodysm_list,
@@ -7436,13 +12478,414 @@
   if( preview == CUBIT_FALSE )
   {
     // Update DAG
-    if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-      return CUBIT_FAILURE;
+    CubitStatus stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled() )
+    {
+      if( stat == CUBIT_SUCCESS )
+        CubitUndo::note_result_bodies( new_body_list );
+      else
+        CubitUndo::remove_last_undo();
+    }
+
+    return stat;
   }
-
   return CUBIT_SUCCESS;
 }
 
+void GeometryModifyTool::propagate_from_small_edge(RefEdge *edge,
+                                                 DLIList<RefEdge*> &small_edges,
+                                                 DLIList<RefFace*> &narrow_faces,
+                                                 DLIList<RefFace*> &processed_faces,
+                                                 double small_edge_length)
+{
+  int i, j;
+  // First find any small edges connected to this edge.
+  DLIList<RefVertex*> edge_verts;
+  edge->ref_vertices(edge_verts);
+  for(i=edge_verts.size(); i--;)
+  {
+    RefVertex *vert = edge_verts.get_and_step();
+    DLIList<RefEdge*> vert_edges;
+    vert->ref_edges(vert_edges);
+    for(j=vert_edges.size(); j--;)
+    {
+      RefEdge *cur_edge = vert_edges.get_and_step();
+      if(cur_edge != edge && !cur_edge->marked())
+      {
+        // Mark of > 0 means it has been processed.
+        cur_edge->marked(1);
+        if(cur_edge->get_arc_length() < small_edge_length)
+        {
+          small_edges.append(cur_edge);
+          // Mark of 2 means it is a small edge.
+          cur_edge->marked(2);
+          propagate_from_small_edge(cur_edge, small_edges, narrow_faces,
+            processed_faces, small_edge_length);
+        }
+      }
+    }
+  }
+  // Now look at adjacent narrow faces and recursively process them.
+  DLIList<RefFace*> edge_faces;
+  edge->ref_faces(edge_faces);
+  for(i=edge_faces.size(); i--;)
+  {
+    RefFace *cur_face = edge_faces.get_and_step();
+    if(!cur_face->marked())
+    {
+      cur_face->marked(1);
+      if(GeomMeasureTool::narrow_region_exists(cur_face, small_edge_length))
+      {
+        DLIList<CubitVector> split_pos1_list;
+        DLIList<CubitVector> split_pos2_list;
+        GeomMeasureTool::find_split_points_for_narrow_regions(cur_face,
+          small_edge_length, split_pos1_list, split_pos2_list);
+        if(split_pos1_list.size() == 0)
+        {
+          narrow_faces.append_unique(cur_face);
+          propagate_over_narrow_face(cur_face, edge, processed_faces,
+            small_edges, narrow_faces, small_edge_length);
+        }
+      }
+    }
+  }
+}
+
+void GeometryModifyTool::propagate_over_narrow_face(RefFace *narrow_face,
+                                                  RefEdge *edge,
+                                                  DLIList<RefFace*> &processed_faces,
+                                                  DLIList<RefEdge*> &small_edges,
+                                                  DLIList<RefFace*> &narrow_faces,
+                                                  double small_edge_length)
+{
+  int i, j;
+  processed_faces.append(narrow_face);
+  DLIList<RefEdge*> face_edges;
+  narrow_face->ref_edges(face_edges);
+  for(i=face_edges.size(); i--;)
+  {
+    RefEdge *cur_edge = face_edges.get_and_step();
+    if(cur_edge != edge && !cur_edge->marked())
+    {
+      cur_edge->marked(1);
+      if(cur_edge->get_arc_length() < small_edge_length)
+      {
+        cur_edge->marked(2);
+        small_edges.append(cur_edge);
+        propagate_from_small_edge(cur_edge, small_edges,
+                narrow_faces, processed_faces, small_edge_length);
+      }
+      else
+      {
+        DLIList<RefFace*> edge_faces;
+        cur_edge->ref_faces(edge_faces);
+        for(j=edge_faces.size(); j--;)
+        {
+          RefFace *cur_face = edge_faces.get_and_step();
+          if(cur_face != narrow_face)
+          {
+            if(!cur_face->marked())
+            {
+              cur_face->marked(1);
+              if(GeomMeasureTool::narrow_region_exists(cur_face, small_edge_length))
+              {
+                DLIList<CubitVector> split_pos1_list;
+                DLIList<CubitVector> split_pos2_list;
+                GeomMeasureTool::find_split_points_for_narrow_regions(cur_face,
+                  small_edge_length, split_pos1_list, split_pos2_list);
+                if(split_pos1_list.size() == 0)
+                {
+                  narrow_faces.append_unique(cur_face);
+                  propagate_over_narrow_face(cur_face, edge, processed_faces,
+                    small_edges, narrow_faces, small_edge_length);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+CubitStatus GeometryModifyTool::remove_topology( DLIList<RefEdge*> &ref_edge_list,
+                                                  DLIList<RefFace*> &ref_face_list,
+                                                  double backoff_distance,
+                                                  double small_curve_size,
+                                                  DLIList<Body*> &new_body_list,
+                                                  CubitBoolean propagate,
+                                                  CubitBoolean preview)
+{
+  int i, j;
+  CubitStatus ret = CUBIT_SUCCESS;
+  DLIList<Surface*> surf_list;
+  DLIList<Curve*> curve_list;
+  DLIList<Body*> old_body_list;
+  GeometryModifyEngine *gme_ptr1=NULL, *gme_ptr2=NULL, *gme_ptr=NULL;
+  Body *b1=NULL, *b2=NULL, *b=NULL;
+
+  if(ref_edge_list.size())
+    b1 = ref_edge_list.get()->body();
+  if(ref_face_list.size())
+    b2 = ref_face_list.get()->body();
+
+  if(b1 && b2)
+  {
+    if(b1 == b2)
+      b = b1;
+  }
+  else if(b1)
+    b = b1;
+  else if(b2)
+    b = b2;
+
+  if(b)
+    old_body_list.append(b);
+  else
+  {
+    PRINT_ERROR("Failed to find an owning body for the topology being removed.\n");
+    ret = CUBIT_FAILURE;
+  }
+
+  if(ret == CUBIT_SUCCESS)
+  {
+    if (!okay_to_modify( old_body_list, "REMOVE_TOPOLOGY" ))
+      ret = CUBIT_FAILURE;
+    else
+    {
+      // Remove any edges from the list that aren't small enough.
+      DLIList<RefEdge*> edges_to_remove;
+      for(i=ref_edge_list.size(); i--;)
+      {
+        RefEdge* re = ref_edge_list.get_and_step();
+        if(re->get_arc_length() > small_curve_size)
+        {
+          edges_to_remove.append(re);
+          PRINT_INFO("Ignoring curve %d as it is not a small curve based on the input. "
+            "Try a larger small_curve_size value.\n", re->id());
+        }
+      }
+      ref_edge_list -= edges_to_remove;
+
+      // Remove any faces from the list that don't have at least one small edge.
+      DLIList<RefFace*> faces_to_remove;
+      for(i=ref_face_list.size(); i--;)
+      {
+        DLIList<RefEdge*> face_edges;
+        RefFace* rf = ref_face_list.get_and_step();
+        rf->ref_edges(face_edges);
+        int face_ok = 0;
+        for(j=face_edges.size(); j && !face_ok; j--)
+        {
+          RefEdge* cur_edge = face_edges.get_and_step();
+          if(cur_edge->get_arc_length() <= small_curve_size)
+            face_ok = 1;
+        }
+        if(!face_ok)
+        {
+          faces_to_remove.append(rf);
+          PRINT_INFO("Ignoring surface %d as it does not have at least one small curve in it based on the input. "
+            "Try a larger small_curve_size value.\n", rf->id());
+        }
+      }
+      ref_face_list -= faces_to_remove;
+    }
+
+    if(ref_face_list.size() > 0 || ref_edge_list.size() > 0)
+    {
+      // If told to do so propagate the topology to be removed to include
+      // other narrow surfaces and small edges.
+      if(propagate)
+      {
+        // Get all of the small edges into a single list.
+        DLIList<RefEdge*> small_edges = ref_edge_list;
+        for(i=ref_face_list.size(); i--;)
+        {
+          RefFace *face = ref_face_list.get_and_step();
+          DLIList<RefEdge*> edges;
+          face->ref_edges(edges);
+          for(j=edges.size(); j--;)
+          {
+            RefEdge *edge = edges.get_and_step();
+            if(edge->get_arc_length() < small_curve_size)
+              small_edges.append(edge);
+          }
+        }
+        small_edges.uniquify_ordered();
+
+        DLIList<RefFace*> processed_faces;
+        DLIList<RefEdge*> copy_of_small_edges = small_edges;
+        DLIList<RefFace*> narrow_faces;
+
+        DLIList<RefFace*> all_faces;
+        DLIList<RefEdge*> all_edges;
+
+        // Set all of the marked flags to 0.
+        b->ref_faces(all_faces);
+        for(i=all_faces.size(); i>0; i--)
+          all_faces.get_and_step()->marked(0);
+
+        b->ref_edges(all_edges);
+        for(i=all_edges.size(); i>0; i--)
+          all_edges.get_and_step()->marked(0);
+
+        // Mark of >0 means it has been processed.
+        // Mark of 2 means it is a small edge.
+        for(i=small_edges.size(); i>0; i--)
+          small_edges.get_and_step()->marked(2);
+
+        // First look at all of the edges connected to small edges
+        // to see if there are other small edges.
+        while(copy_of_small_edges.size())
+        {
+          RefEdge *edge = copy_of_small_edges.extract();
+          propagate_from_small_edge(edge, small_edges,
+                  narrow_faces, processed_faces, small_curve_size);
+        }
+
+        ref_face_list += narrow_faces;
+        ref_face_list.uniquify_ordered();
+
+        ref_edge_list = small_edges;
+        ref_edge_list.uniquify_ordered();
+        // Append to face list here so we don't lose the ones that were passed in.
+      }
+    }
+    else
+    {
+      PRINT_WARNING("No entities to remove.\n");
+      ret = CUBIT_FAILURE;
+    }
+  }
+
+  if(ret == CUBIT_SUCCESS)
+  {
+    if(ref_edge_list.size())
+    {
+      for(i=ref_edge_list.size(); i--;)
+      {
+        RefEdge *re = ref_edge_list.get_and_step();
+        Curve *cur = re->get_curve_ptr();
+        DLIList<TopologyBridge*> tmp_curve_list;
+        GeometryQueryEngine *gqe = cur->get_geometry_query_engine();
+        gqe->get_underlying_curves(cur, tmp_curve_list);
+        if(tmp_curve_list.size() == 0)
+          tmp_curve_list.append(cur);
+        for(int p=tmp_curve_list.size(); p--;)
+        {
+          Curve *crv = dynamic_cast<Curve*>(tmp_curve_list.get_and_step());
+          if(!gme_ptr1)
+            gme_ptr1 = get_engine(crv);
+          curve_list.append(crv);
+        }
+      }
+    }
+    if(ref_face_list.size())
+    {
+      for(i=ref_face_list.size(); i--;)
+      {
+        RefFace *rf = ref_face_list.get_and_step();
+        Surface *sur = rf->get_surface_ptr();
+        DLIList<TopologyBridge*> tmp_surf_list;
+        GeometryQueryEngine *gqe = sur->get_geometry_query_engine();
+        gqe->get_underlying_surfaces(sur, tmp_surf_list);
+        if(tmp_surf_list.size() == 0)
+          tmp_surf_list.append(sur);
+        for(int p=tmp_surf_list.size(); p--;)
+        {
+          Surface *srf = dynamic_cast<Surface*>(tmp_surf_list.get_and_step());
+          if(!gme_ptr2)
+            gme_ptr2 = get_engine(srf);
+          surf_list.append(srf);
+        }
+      }
+    }
+    if(gme_ptr1 && gme_ptr2)
+    {
+      if(gme_ptr1 == gme_ptr2)
+        gme_ptr = gme_ptr1;
+    }
+    else if(gme_ptr1)
+      gme_ptr = gme_ptr1;
+    else if(gme_ptr2)
+      gme_ptr = gme_ptr2;
+
+    if(!gme_ptr)
+    {
+      PRINT_ERROR("Failed to find a geometry modify engine.\n");
+      ret = CUBIT_FAILURE;
+    }
+  }
+
+  if(ret == CUBIT_SUCCESS)
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    {
+      DLIList<Body*> bodies;
+      int i;
+      for( i=ref_face_list.size(); i--; )
+      {
+        RefFace* ref_face = ref_face_list.get_and_step();
+        bodies.append( ref_face->body() );
+      }
+      for( i=ref_edge_list.size(); i--; )
+      {
+        RefEdge* ref_edge = ref_edge_list.get_and_step();
+        bodies.append( ref_edge->body() );
+      }
+      bodies.uniquify_unordered();
+      CubitUndo::save_state_with_cubit_file( bodies );
+    }
+
+    if(preview == CUBIT_FALSE)
+      do_attribute_setup();
+
+    DLIList<BodySM*> body_sm_list(old_body_list.size());
+    GeometryModifyEngine* gme = common_modify_engine(old_body_list, body_sm_list);
+
+    if(preview == CUBIT_FALSE)
+      push_vg_attributes_before_modify(body_sm_list);
+
+    DLIList<BodySM*> new_bodysm_list;
+    if(gme_ptr->remove_topology(curve_list, surf_list, backoff_distance, small_curve_size,
+        new_bodysm_list, preview) == CUBIT_FAILURE)
+    {
+      if( CubitUndo::get_undo_enabled() )
+        CubitUndo::remove_last_undo();
+
+      if(!preview)
+        remove_pushed_attributes(new_bodysm_list, old_body_list);
+
+      ret = CUBIT_FAILURE;
+    }
+    else
+    {
+      if( preview == CUBIT_FALSE )
+      {
+        restore_vg_after_modify(new_bodysm_list, old_body_list, gme);
+        remove_pushed_attributes(new_bodysm_list, old_body_list);
+
+        // Update DAG
+        ret = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+        if( CubitUndo::get_undo_enabled() )
+        {
+          if( ret == CUBIT_FAILURE)
+            CubitUndo::remove_last_undo();
+          else
+            CubitUndo::note_result_bodies( new_body_list );
+        }
+      }
+    }
+
+    if(preview == CUBIT_FALSE)
+      do_attribute_cleanup();
+  }
+
+  return ret;
+}
+
 //=============================================================================
 // 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.
@@ -7576,6 +13019,14 @@
     curve3 = dynamic_cast<Curve*>(bridge);
   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_vertex_list );
+  }
+
   // Do chamfering
   DLIList<BodySM*> new_bodysm_list;
   if( gme_ptr->tweak_chamfer( point_list, offset1, new_bodysm_list, curve1, offset2,
@@ -7585,8 +13036,16 @@
   if( preview == CUBIT_FALSE )
   {
     // Update DAG
-    if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-      return CUBIT_FAILURE;
+    CubitStatus stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+    return stat;
   }
 
   return CUBIT_SUCCESS;
@@ -7594,7 +13053,7 @@
 
 //=============================================================================
 // Description: Create a round fillet (or blend) at the given curves on solid
-//              bodies.
+//              or sheet bodies.
 // Author     : Steve Storm
 // Date       : 03/25/05
 //=============================================================================
@@ -7604,30 +13063,6 @@
                                               CubitBoolean keep_old_body,
                                               CubitBoolean preview )
 {
-  // Make sure curves are not part of a sheet body
-  // Get unique volumes that the curves are attached to
-  DLIList<RefVolume*> ref_volume_list;
-  int i;
-  RefEdge *ref_edge_ptr;
-  for( i=ref_edge_list.size(); i--; )
-  {
-    ref_edge_ptr = ref_edge_list.get_and_step();
-    DLIList<RefVolume*> tmp_ref_volume_list;
-    ref_edge_ptr->ref_volumes( tmp_ref_volume_list );
-    ref_volume_list.merge_unique( tmp_ref_volume_list );
-  }
-
-  RefVolume *ref_volume_ptr;
-  for( i=ref_volume_list.size(); i--; )
-  {
-    ref_volume_ptr = ref_volume_list.get_and_step();
-    if( ref_volume_ptr->is_sheet() )
-    {
-      PRINT_ERROR( "Cannot fillet curves on sheet bodies\n" );
-      return CUBIT_FAILURE;
-    }
-  }
-
   DLIList<Curve*> curve_list(ref_edge_list.size());
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
@@ -7636,6 +13071,14 @@
   if( !gme_ptr )
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do filleting
   DLIList<BodySM*> new_bodysm_list;
   if( gme_ptr->tweak_fillet(curve_list, radius, new_bodysm_list, keep_old_body,
@@ -7645,17 +13088,25 @@
   if( preview == CUBIT_FALSE )
   {
     // Update DAG
-    if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-      return CUBIT_FAILURE;
+    CubitStatus stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled() )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+
+    return stat;
   }
-
   return CUBIT_SUCCESS;
 }
 
 //=============================================================================
 // 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.
+//              or sheet body.  The fillet has a variable radius from the start
+//              to the end of the curve.
 // Author     : Steve Storm
 // Date       : 03/25/05
 //=============================================================================
@@ -7666,23 +13117,6 @@
                                               CubitBoolean keep_old_body,
                                               CubitBoolean preview )
 {
-  // Make sure curve is not part of a sheet body
-  // Get unique volumes that the curves are attached to
-  DLIList<RefVolume*> ref_volume_list;
-  ref_edge_ptr->ref_volumes( ref_volume_list );
-
-  int i;
-  RefVolume *ref_volume_ptr;
-  for( i=ref_volume_list.size(); i--; )
-  {
-    ref_volume_ptr = ref_volume_list.get_and_step();
-    if( ref_volume_ptr->is_sheet() )
-    {
-      PRINT_ERROR( "Cannot fillet curves on sheet bodies\n" );
-      return CUBIT_FAILURE;
-    }
-  }
-
   DLIList<Curve*> curve_list(1);
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
@@ -7694,26 +13128,52 @@
   if( !gme_ptr )
     return CUBIT_FAILURE;
 
-  Curve *curve_ptr = curve_list.get();
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+    {
+      DLIList<RefEdge*> edges(1);
+      edges.append( ref_edge_ptr );
+      CubitUndo::save_state_with_cubit_file( edges );
+    }
+  }
 
   // Do filleting
   BodySM *new_bodysm_ptr;
-  if( gme_ptr->tweak_fillet( curve_ptr, start_radius, end_radius, new_bodysm_ptr,
-    keep_old_body, preview ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
+  Curve *curve_ptr = curve_list.get();
+  CubitStatus stat = gme_ptr->tweak_fillet( curve_ptr, start_radius,
+                                            end_radius, new_bodysm_ptr,
+                                            keep_old_body, preview );
 
+  if( CubitUndo::get_undo_enabled() )
+    if( stat == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE )
+    return stat;
+
   if( preview == CUBIT_FALSE )
   {
     // Update DAG
     DLIList<BodySM*> new_bodysm_list;
     new_bodysm_list.append( new_bodysm_ptr );
     DLIList<Body*> new_body_list;
-    if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-      return CUBIT_FAILURE;
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
 
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+
     new_body_ptr = new_body_list.get();
+
+    return stat;
   }
-
   return CUBIT_SUCCESS;
 }
 
@@ -7738,19 +13198,42 @@
   if( !gme_ptr )
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_vertex_list );
+  }
+
   // Do filleting
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_fillet( point_list, radius, new_bodysm_list, keep_old_body,
-    preview ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
+  CubitStatus stat = gme_ptr->tweak_fillet( point_list, radius,
+                                            new_bodysm_list, keep_old_body,
+                                            preview );
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    if( stat == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE )
+    return stat;
+
   if( preview == CUBIT_FALSE )
   {
     // Update DAG
-    if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-      return CUBIT_FAILURE;
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+
+    return stat;
   }
-
   return CUBIT_SUCCESS;
 }
 
@@ -7769,20 +13252,72 @@
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
 
-  gme_ptr = tweak_setup( ref_face_list, "Moving", old_body_list, surface_list );
+  gme_ptr = tweak_setup( ref_face_list, "Moving", old_body_list, surface_list, CUBIT_TRUE );
   if (!gme_ptr)
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+    {
+      int i;
+      DLIList<RefEdge*> ref_edges;
+      for( i=ref_face_list.size(); i--; )
+        ref_face_list.get_and_step()->ref_edges( ref_edges );
+      ref_edges.uniquify_unordered();
+      CubitUndo::save_state_with_cubit_file( ref_edges );
+    }
+  }
+
+  int i;
+  DLIList<BodySM*> body_sms;
+  for(i=old_body_list.size(); i--;)
+  {
+    BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
+    if(bsm)
+      body_sms.append_unique(bsm);
+  }
+
+  if(!preview)
+  {
+    do_attribute_setup();
+    push_vg_attributes_before_modify(body_sms);
+  }
+
   // Do move
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_move( surface_list, delta, new_bodysm_list, keep_old_body,
-    preview ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
+  CubitStatus stat = gme_ptr->tweak_move( surface_list, delta,
+                                          new_bodysm_list, keep_old_body,
+                                          preview );
 
+
+  if( CubitUndo::get_undo_enabled() )
+    if( stat == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if(!preview)
+    {
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+      do_attribute_cleanup();
+    }
+    return stat;
+  }
+  else
+  {
+    if(!preview)
+    {
+      restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+    }
+  }
+
   // loop body sm list and find surfaces that need updating.
   // this is to account for some cases where the topology doesn't change, but the geometry does.
   DLIList<RefEntity*> entities_to_update;
-  int i;
   for(i=0; i<new_bodysm_list.size(); i++)
   {
     BodySM* bodysm = new_bodysm_list.get_and_step();
@@ -7831,15 +13366,114 @@
     }
   }
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
+  if( preview == CUBIT_FALSE )
+  {
+    // Update DAG
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
 
-  // Update graphics
-  while (entities_to_update.size())
-    entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
 
-  return CUBIT_SUCCESS;
+    // Update graphics
+    while (entities_to_update.size())
+      entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
+
+    do_attribute_cleanup();
+  }
+
+
+  //collect all the new faces
+  DLIList<RefFace*> new_faces;
+  for( i=new_body_list.size(); i--; )
+  {
+    Body *new_body = new_body_list.get_and_step();
+    DLIList<RefFace*> tmp_faces;
+    new_body->ref_faces( tmp_faces );
+    new_faces += tmp_faces;
+  }
+
+  //unmerge any merged adjacent surfaces or
+  //merged curves in unmerged adjacent surfaces
+  DLIList<RefFace*> adjacent_faces_to_unmerge;
+  DLIList<RefEdge*> adjacent_edges_to_unmerge;
+  for(i=ref_face_list.size(); i--;)
+  {
+    RefFace *tweaked_face = ref_face_list.get_and_step();
+    if( !new_faces.move_to( tweaked_face ) )
+      continue;
+
+    //get all the edges of the face you tweaked
+    DLIList<RefEdge*> tweaked_face_edges;
+    tweaked_face->ref_edges( tweaked_face_edges );
+    adjacent_edges_to_unmerge += tweaked_face_edges;
+
+    //get all the adjacent faces to this edge
+    int j;
+    for( j=tweaked_face_edges.size(); j--; )
+    {
+      RefEdge *tmp_edge = tweaked_face_edges.get_and_step();
+      DLIList<RefFace*> tmp_faces;
+      tmp_edge->ref_faces( tmp_faces );
+      tmp_faces.remove( tweaked_face );
+      adjacent_faces_to_unmerge += tmp_faces;
+    }
+
+    //get all edges not in the surface,
+    //sharing vertices with the surface
+    DLIList<RefVertex*> ref_vertices;
+    tweaked_face->ref_vertices( ref_vertices );
+    for( j=ref_vertices.size(); j--; )
+    {
+      RefVertex *tmp_vert = ref_vertices.get_and_step();
+      DLIList<RefEdge*>  ref_edges;
+      tmp_vert->ref_edges( ref_edges );
+
+      int k;
+      for( k=ref_edges.size(); k--; )
+      {
+        RefEdge *tmp_edge = ref_edges.get_and_step();
+        if( !tweaked_face_edges.move_to( tmp_edge ) )
+          adjacent_edges_to_unmerge.append( tmp_edge );
+      }
+    }
+  }
+
+  //unmerge any adjacent faces
+  adjacent_faces_to_unmerge.uniquify_unordered();
+  for( i=adjacent_faces_to_unmerge.size(); i--; )
+  {
+    RefFace *ref_face = adjacent_faces_to_unmerge.get_and_step();
+
+    DLIList<TopologyBridge*> bridge_list;
+    ref_face->bridge_manager()->get_bridge_list(bridge_list);
+    if (bridge_list.size() > 1)
+    {
+      if( MergeTool::instance()->unmerge( ref_face ) )
+        PRINT_WARNING("Unmerging Surface %d\n", ref_face->id() );
+    }
+  }
+
+  //unmerge any adjacent edges
+  adjacent_edges_to_unmerge.uniquify_unordered();
+  for( i=adjacent_edges_to_unmerge.size(); i--; )
+  {
+    RefEdge *ref_edge = adjacent_edges_to_unmerge.get_and_step();
+    DLIList<TopologyBridge*> bridge_list;
+    ref_edge->bridge_manager()->get_bridge_list(bridge_list);
+    if (bridge_list.size() > 1)
+    {
+      if( MergeTool::instance()->unmerge( ref_edge) )
+        PRINT_WARNING("Unmerging Curve %d\n", ref_edge->id() );
+    }
+  }
+
+
+  return stat;
 }
 
 //=============================================================================
@@ -7861,24 +13495,48 @@
   if (!gme_ptr)
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do move
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_move( curve_list, delta, new_bodysm_list, keep_old_body,
-    preview )
-    == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
+  CubitStatus stat = gme_ptr->tweak_move( curve_list, delta,
+                                          new_bodysm_list, keep_old_body,
+                                          preview );
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
+  if( CubitUndo::get_undo_enabled() )
+    if( stat == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
 
+  if( stat == CUBIT_FAILURE )
+    return stat;
+
+  if( preview == CUBIT_FALSE )
+  {
+    // Update DAG
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+  }
+
   // Update graphics
   DLIList<Body*> moved_bodies(new_body_list);
   moved_bodies.intersect(old_body_list);
   while (moved_bodies.size())
     moved_bodies.pop()->notify_sub_all_observers( GEOMETRY_MODIFIED );
 
-  return CUBIT_SUCCESS;
+  return stat;
 }
 
 //=============================================================================
@@ -7887,30 +13545,153 @@
 // Author     : Steve Storm
 // Date       : 03/25/05
 //=============================================================================
-CubitStatus GeometryModifyTool::tweak_offset( DLIList<RefFace*>& ref_face_list,
+CubitStatus GeometryModifyTool::tweak_offset( DLIList<RefFace*> &ref_face_list,
                                               double offset_distance,
-                                              DLIList<Body*>& new_body_list,
+                                              DLIList<RefFace*> *add_ref_face_list_ptr,
+                                              DLIList<double> *add_offset_list_ptr,
+                                              DLIList<Body*> &new_body_list,
                                               CubitBoolean keep_old_body,
                                               CubitBoolean preview )
 {
+  DLIList<RefFace*> all_ref_face_list(ref_face_list.size());
+  all_ref_face_list = ref_face_list;
+  if( add_ref_face_list_ptr->size() )
+    all_ref_face_list += *add_ref_face_list_ptr;
+
   DLIList<Surface*> surface_list(ref_face_list.size());
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
 
-  gme_ptr = tweak_setup( ref_face_list, "Offsetting", old_body_list, surface_list );
+  gme_ptr = tweak_setup( ref_face_list, "Offsetting", old_body_list, surface_list, CUBIT_TRUE );
   if (!gme_ptr)
     return CUBIT_FAILURE;
 
+  DLIList<Surface*> add_surface_list;
+  if( add_ref_face_list_ptr && add_ref_face_list_ptr->size() )
+  {
+    DLIList<Body*> old_body_list2;
+    GeometryModifyEngine* gme_ptr2 = tweak_setup( *add_ref_face_list_ptr, "Offsetting", 
+      old_body_list2, add_surface_list, CUBIT_TRUE );
+    if (!gme_ptr2)
+      return CUBIT_FAILURE;
+    if( gme_ptr != gme_ptr2 )
+    {
+      PRINT_ERROR("Offsetting surfaces on volumes containing surfaces from different\n"
+        "       geometry engines is not allowed.\n");
+      return CUBIT_FAILURE;
+    }
+    old_body_list.merge_unique( old_body_list2 );
+  }
+
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+    {
+      int i;
+      DLIList<RefEdge*> ref_edges;
+      for( i=ref_face_list.size(); i--; )
+        all_ref_face_list.get_and_step()->ref_edges( ref_edges );
+      ref_edges.uniquify_unordered();
+      CubitUndo::save_state_with_cubit_file( ref_edges );
+    }
+  }
+
+  int i;
+  if(!preview)
+  {
+    DLIList<BodySM*> body_sms;
+    for(i=old_body_list.size(); i--;)
+    {
+      BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
+      if(bsm)
+        body_sms.append_unique(bsm);
+    }
+
+    do_attribute_setup();
+    push_vg_attributes_before_modify(body_sms);
+  }
+
   // Do offset
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_offset( surface_list, offset_distance, new_bodysm_list,
-    keep_old_body, preview ) == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
+  CubitStatus stat;
+  if( add_surface_list.size() )
+    stat = gme_ptr->tweak_offset( surface_list, offset_distance, 
+                                  &add_surface_list, add_offset_list_ptr,
+                                  new_bodysm_list, keep_old_body, preview );
+  else
+    stat = gme_ptr->tweak_offset( surface_list, offset_distance, NULL, NULL,
+                                  new_bodysm_list, keep_old_body, preview );
 
+  if( CubitUndo::get_undo_enabled() )
+    if( stat == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if(!preview)
+    {
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+      do_attribute_cleanup();
+    }
+    return stat;
+  }
+  else
+  {
+    if(!preview)
+    {
+      restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+    }
+  }
+
+  // Collect all of the old faces to be compared later with the new faces...DJQ
+  DLIList<RefFace*> old_faces;
+  for (i = 0; i < old_body_list.size(); i++)
+  {
+      Body *old_body = old_body_list.get_and_step();
+      DLIList<RefFace*> tmp_faces;
+      old_body->ref_faces(tmp_faces);
+      old_faces +=tmp_faces;
+  }
+
+  if( preview == CUBIT_FALSE )
+  {
+    // Update DAG
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+    do_attribute_cleanup();
+  }
+
+  //collect all the new faces
+  DLIList<RefFace*> new_faces;
+  for( i=new_body_list.size(); i--; )
+  {
+    Body *new_body = new_body_list.get_and_step();
+    DLIList<RefFace*> tmp_faces;
+    new_body->ref_faces( tmp_faces );
+    new_faces += tmp_faces;
+  }
+
+  // Compare the new_faces list with the old_faces list to determine which faces are created
+  // Add these faces to the all_ref_face_list to check for its neighbors...DJQ
+  DLIList<RefFace*> difference = new_faces;
+  difference -= old_faces;
+  all_ref_face_list += difference;
+
   // loop body sm list and find surfaces that need updating.
-  // this is to account for some cases where the topology doesn't change, but the geometry does.
+  // this is to account for some cases where the topology
+  //doesn't change, but the geometry does.
+
   DLIList<RefEntity*> entities_to_update;
-  int i;
   for(i=0; i<new_bodysm_list.size(); i++)
   {
     BodySM* bodysm = new_bodysm_list.get_and_step();
@@ -7924,7 +13705,7 @@
       if(man)
       {
         RefFace* ref_face = CAST_TO(man->topology_entity(), RefFace);
-        if(ref_face && ref_face_list.is_in_list(ref_face))
+        if(ref_face && all_ref_face_list.is_in_list(ref_face))
         {
           // get neighbors
           DLIList<Point*> neighbor_points;
@@ -7959,15 +13740,87 @@
     }
   }
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
 
+  //unmerge any merged adjacent surfaces or
+  //merged curves in unmerged adjacent surfaces
+  DLIList<RefFace*> adjacent_faces_to_unmerge;
+  DLIList<RefEdge*> adjacent_edges_to_unmerge;
+  for(i=ref_face_list.size(); i--;)
+  {
+    RefFace *tweaked_face = ref_face_list.get_and_step();
+    if( !new_faces.move_to( tweaked_face ) )
+      continue;
+
+    //get all the edges of the face you tweaked
+    DLIList<RefEdge*> tweaked_face_edges;
+    tweaked_face->ref_edges( tweaked_face_edges );
+    adjacent_edges_to_unmerge += tweaked_face_edges;
+
+    //get all the adjacent faces to this edge
+    int j;
+    for( j=tweaked_face_edges.size(); j--; )
+    {
+      RefEdge *tmp_edge = tweaked_face_edges.get_and_step();
+      DLIList<RefFace*> tmp_faces;
+      tmp_edge->ref_faces( tmp_faces );
+      tmp_faces.remove( tweaked_face );
+      adjacent_faces_to_unmerge += tmp_faces;
+    }
+
+    //get all edges not in the surface,
+    //sharing vertices with the surface
+    DLIList<RefVertex*> ref_vertices;
+    tweaked_face->ref_vertices( ref_vertices );
+    for( j=ref_vertices.size(); j--; )
+    {
+      RefVertex *tmp_vert = ref_vertices.get_and_step();
+      DLIList<RefEdge*>  ref_edges;
+      tmp_vert->ref_edges( ref_edges );
+
+      int k;
+      for( k=ref_edges.size(); k--; )
+      {
+        RefEdge *tmp_edge = ref_edges.get_and_step();
+        if( !tweaked_face_edges.move_to( tmp_edge ) )
+          adjacent_edges_to_unmerge.append( tmp_edge );
+      }
+    }
+  }
+
+  //unmerge any adjacent faces
+  adjacent_faces_to_unmerge.uniquify_unordered();
+  for( i=adjacent_faces_to_unmerge.size(); i--; )
+  {
+    RefFace *ref_face = adjacent_faces_to_unmerge.get_and_step();
+
+    DLIList<TopologyBridge*> bridge_list;
+    ref_face->bridge_manager()->get_bridge_list(bridge_list);
+    if (bridge_list.size() > 1)
+    {
+      if( MergeTool::instance()->unmerge( ref_face ) )
+        PRINT_WARNING("Unmerging Surface %d\n", ref_face->id() );
+    }
+  }
+
+  //unmerge any adjacent edges
+  adjacent_edges_to_unmerge.uniquify_unordered();
+  for( i=adjacent_edges_to_unmerge.size(); i--; )
+  {
+    RefEdge *ref_edge = adjacent_edges_to_unmerge.get_and_step();
+    DLIList<TopologyBridge*> bridge_list;
+    ref_edge->bridge_manager()->get_bridge_list(bridge_list);
+    if (bridge_list.size() > 1)
+    {
+      if( MergeTool::instance()->unmerge( ref_edge) )
+        PRINT_WARNING("Unmerging Curve %d\n", ref_edge->id() );
+    }
+  }
+
   // Update graphics
   while (entities_to_update.size())
     entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
 
-  return CUBIT_SUCCESS;
+  return stat;
 }
 
 //=============================================================================
@@ -7976,12 +13829,19 @@
 // Author     : Steve Storm
 // Date       : 03/25/05
 //=============================================================================
-CubitStatus GeometryModifyTool::tweak_offset( DLIList<RefEdge*>& ref_edge_list,
+CubitStatus GeometryModifyTool::tweak_offset( DLIList<RefEdge*> &ref_edge_list,
                                               double offset_distance,
-                                              DLIList<Body*>& new_body_list,
+                                              DLIList<RefEdge*> *add_ref_edge_list_ptr,
+                                              DLIList<double> *add_offset_list_ptr,
+                                              DLIList<Body*> &new_body_list,
                                               CubitBoolean keep_old_body,
                                               CubitBoolean preview )
 {
+  DLIList<RefEdge*> all_ref_edge_list(ref_edge_list.size());
+  all_ref_edge_list = ref_edge_list;
+  if( add_ref_edge_list_ptr )
+    all_ref_edge_list += *add_ref_edge_list_ptr;
+
   DLIList<Curve*> curve_list(ref_edge_list.size());
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
@@ -7990,119 +13850,250 @@
   if (!gme_ptr)
     return CUBIT_FAILURE;
 
+  DLIList<Curve*> add_curve_list;
+  if( add_ref_edge_list_ptr && add_ref_edge_list_ptr->size() )
+  {
+    DLIList<Body*> old_body_list2;
+    GeometryModifyEngine* gme_ptr2 = tweak_setup( *add_ref_edge_list_ptr, "Offsetting", 
+      old_body_list2, add_curve_list );
+    if (!gme_ptr2)
+      return CUBIT_FAILURE;
+    if( gme_ptr != gme_ptr2 )
+    {
+      PRINT_ERROR("Offsetting curves on entities containing surfaces from different\n"
+      "       geometry engines is not allowed.\n");
+      return CUBIT_FAILURE;
+    }
+    old_body_list.merge_unique( old_body_list2 );
+  }
+
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( all_ref_edge_list );
+  }
+
   // Do offset
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_offset( curve_list, offset_distance, new_bodysm_list,
-    keep_old_body, preview ) == CUBIT_FAILURE )
+  CubitStatus stat;
+  if( add_curve_list.size() )
+    stat = gme_ptr->tweak_offset( curve_list, offset_distance, &add_curve_list,
+    add_offset_list_ptr, new_bodysm_list, keep_old_body, preview );
+  else
+    stat = gme_ptr->tweak_offset( curve_list, offset_distance, NULL, NULL,
+    new_bodysm_list, keep_old_body, preview );
+
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    if( stat == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE )
     return CUBIT_FAILURE;
 
   // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
+  if( preview == CUBIT_FALSE )
+  {
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
 
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+  }
+
   // Update graphics
   DLIList<Body*> moved_bodies(new_body_list);
   moved_bodies.intersect(old_body_list);
   while (moved_bodies.size())
     moved_bodies.pop()->notify_sub_all_observers( GEOMETRY_MODIFIED );
 
-  return CUBIT_SUCCESS;
+  return stat;
 }
 
-//=============================================================================
-// 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/25/05
-//=============================================================================
-CubitStatus GeometryModifyTool::tweak_remove( DLIList<RefFace*> &ref_face_list,
+
+CubitStatus GeometryModifyTool::tweak_remove_individually(
+                                              DLIList<RefFace*> &ref_face_list,
                                               DLIList<Body*> &new_body_list,
-                                              CubitBoolean extend_adjoining,
                                               CubitBoolean keep_surface,
                                               CubitBoolean keep_old_body,
-                                              CubitBoolean individual,
                                               CubitBoolean preview )
 {
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_face_list );
+  }
+
   // Split things up if individual
-  if (individual && extend_adjoining )
+  //build a surfae to volume map
+  std::map<RefFace*, RefVolume*> surface_to_volume_map;
+
+  int i;
+  for (i = ref_face_list.size(); i--; )
   {
-    //build a surfae to volume map
-    std::map<RefFace*, RefVolume*> surface_to_volume_map;
+    RefFace *tmp_face = ref_face_list.get_and_step();
+    RefVolume *tmp_vol = tmp_face->ref_volume();
+    surface_to_volume_map.insert( std::map<RefFace*, RefVolume*>::value_type( tmp_face, tmp_vol));
+  }
 
-    int i;
-    for (i = ref_face_list.size(); i--; )
-    {
-      RefFace *tmp_face = ref_face_list.get_and_step();
-      RefVolume *tmp_vol = tmp_face->ref_volume();
-      surface_to_volume_map.insert( std::map<RefFace*, RefVolume*>::value_type( tmp_face, tmp_vol));
-    }
+  DLIList<RefFace*> one_ref_face;
+  DLIList<Body*> tmp_new_body_list;
+  CubitStatus total_rv = CUBIT_FAILURE;
+  bool extend = true;
 
-    DLIList<RefFace*> one_ref_face;
-    CubitStatus total_rv = CUBIT_FAILURE;
+  // Succeed if any one surface succeeds.
+  for (i = ref_face_list.size(); i--; )
+  {
+    //make sure that the surface to remove is still in the body...
+    //that it hasn't been removed from a previous tweak operation
+    RefFace *tmp_face = ref_face_list.get_and_step();
+    std::map<RefFace*, RefVolume*>::iterator tmp_iter;
+    tmp_iter = surface_to_volume_map.find( tmp_face );
+    RefVolume *tmp_vol = tmp_iter->second;
+    DLIList<RefFace*> ref_face_list;
+    tmp_vol->ref_faces( ref_face_list );
+    if( !ref_face_list.move_to( tmp_face ) )
+      continue;
 
-    // Succeed if any one surface succeeds.
-    for (i = ref_face_list.size(); i--; )
+    one_ref_face.clean_out();
+    one_ref_face.append( tmp_face );
+    int id = one_ref_face.get()->id();
+
+    //See if the owning body of the face is a multi-volume body
+    Body *owning_body = one_ref_face.get()->body();
+    int number_volumes_before = owning_body->num_ref_volumes();
+
+    tmp_new_body_list.clean_out();
+
+    CubitStatus rv = this->tweak_remove(one_ref_face, tmp_new_body_list,
+      extend, keep_surface, keep_old_body, preview );
+    if (rv)
     {
-      //make sure that the surface to remove is still in the body...
-      //that it hasn't been removed from a previous tweak operation
-      RefFace *tmp_face = ref_face_list.get_and_step();
-      std::map<RefFace*, RefVolume*>::iterator tmp_iter;
-      tmp_iter = surface_to_volume_map.find( tmp_face ); 
-      RefVolume *tmp_vol = tmp_iter->second;
-      DLIList<RefFace*> ref_face_list;
-      tmp_vol->ref_faces( ref_face_list );
-      if( !ref_face_list.move_to( tmp_face ) )
-        continue;
+      total_rv = CUBIT_SUCCESS;
+      if( !preview )
+        PRINT_INFO("Successfully removed Surface %d\n\n", id);
+      else
+        PRINT_INFO("Successfully removed Surface %d in preview\n\n", id);
 
-      one_ref_face.clean_out();
-      one_ref_face.append( tmp_face );
-      int id = one_ref_face.get()->id();
-      CubitStatus rv = this->tweak_remove(one_ref_face, new_body_list,
-        extend_adjoining, keep_surface, keep_old_body, false, preview );
-      if (rv)
+      //see if we have a multi-volume body or multiple bodies
+      //if so, we know the original volume was destroyed, so we
+      //cannot remove any more surfaces because the check above is
+      //highly likely to crash
+      bool volume_destroyed = false;
+      int number_volumes_after = tmp_new_body_list.get()->num_ref_volumes();
+      if( number_volumes_after > number_volumes_before  )
+        volume_destroyed = true;
+
+      new_body_list += tmp_new_body_list;
+
+      if( volume_destroyed == true )
       {
-        new_body_list.uniquify_unordered();
-        total_rv = CUBIT_SUCCESS;
-        if( !preview )
-          PRINT_INFO("Successfully removed Surface %d\n\n", id);
-        else
-          PRINT_INFO("Successfully removed Surface %d in preview\n\n", id);
-        
-        //see if we have a multi-volume body or multiple bodies
-        //if so, we know the original volume was destroyed, so we 
-        //cannot remove any more surfaces because the check above is 
-        //highly likely to crash
-        bool volume_destroyed = false;
-        if( new_body_list.size() > 1 ) 
-          volume_destroyed = true;
-        else if( new_body_list.size() )
+        PRINT_WARNING("Unable to remove more surfaces because multiple bodies\n"
+                      "       have been produced from removing surfaces individually\n" );
+        if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
         {
-          if( new_body_list.get()->num_ref_volumes() > 1 )
-            volume_destroyed = true;
+          if( total_rv == CUBIT_FAILURE )  //didn't remove any surfaces
+            CubitUndo::remove_last_undo();
+          else
+            CubitUndo::note_result_bodies( new_body_list );
         }
 
-        if( volume_destroyed == true  && i )
-        {
-          PRINT_WARNING("Unable to remove more surfaces because multiple bodies\n"
-                        "       have been produced from removing surfaces individually\n" );
-          return total_rv; 
-        }
+        return total_rv;
       }
+    }
+    else
+    {
+      if( !preview )
+        PRINT_INFO("Unable to remove Surface %d\n\n", id);
       else
-      {
-        if( !preview )
-          PRINT_INFO("Unable to remove Surface %d\n\n", id);
-        else
-          PRINT_INFO("Unable to remove Surface %d in preview\n\n", id);
-      }
+        PRINT_INFO("Unable to remove Surface %d in preview\n\n", id);
     }
-    return total_rv;
   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( total_rv == CUBIT_FAILURE)
+      CubitUndo::remove_last_undo();
+    else if( keep_old_body || keep_surface )
+      CubitUndo::note_result_bodies( new_body_list );
+  }
+
+  return total_rv;
+}
+
+
+//=============================================================================
+// 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/25/05
+//=============================================================================
+CubitStatus GeometryModifyTool::tweak_remove_together(
+                                              DLIList<RefFace*> &ref_face_list,
+                                              DLIList<Body*> &new_body_list,
+                                              CubitBoolean extend_adjoining,
+                                              CubitBoolean keep_surface,
+                                              CubitBoolean keep_old_body,
+                                              CubitBoolean preview )
+{
+
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_face_list );
+  }
+
+  CubitStatus stat = tweak_remove( ref_face_list, new_body_list,
+                                   extend_adjoining, keep_surface,
+                                   keep_old_body, preview );
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
+
+    return CUBIT_FAILURE;
+  }
+
+
+  if( preview == CUBIT_FALSE )
+  {
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body || keep_surface )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+//private funcion...should not be called from outside this class
+CubitStatus GeometryModifyTool::tweak_remove( DLIList<RefFace*> &ref_face_list,
+                                              DLIList<Body*> &new_body_list,
+                                              CubitBoolean extend_adjoining,
+                                              CubitBoolean keep_surface,
+                                              CubitBoolean keep_old_body,
+                                              CubitBoolean preview )
+{
    DLIList<Surface*> surface_list(ref_face_list.size());
    DLIList<Body*> old_body_list;
    GeometryModifyEngine* gme_ptr;
 
+   // clear any preview previews
+   GfxPreview::clear();
+
    //collect all neighboring surfaces to those in the list
    int i,j;
    DLIList<RefFace*> neighboring_surfaces;
@@ -8119,15 +14110,70 @@
   neighboring_surfaces.uniquify_unordered();
   neighboring_surfaces += ref_face_list;
 
-   gme_ptr = tweak_setup( ref_face_list, "Removing", old_body_list, surface_list );
+   gme_ptr = tweak_setup( ref_face_list, "Removing", old_body_list, surface_list, CUBIT_TRUE );
    if (!gme_ptr)
      return CUBIT_FAILURE;
 
+   DLIList<Surface*> kept_surface_list;
+   if( keep_surface )
+   {
+     int kk;
+     for( kk=surface_list.size(); kk--; )
+     {
+       Surface *new_surf = gme_ptr->make_Surface( surface_list.get_and_step() );
+       kept_surface_list.append( new_surf );
+     }
+   }
+
+   DLIList<BodySM*> body_sms;
+   for(i=old_body_list.size(); i--;)
+   {
+     BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
+     if(bsm)
+       body_sms.append_unique(bsm);
+   }
+
+   if(!preview)
+   {
+    do_attribute_setup();
+    push_vg_attributes_before_modify(body_sms);
+   }
+
    // Do remove
    DLIList<BodySM*> new_bodysm_list;
-   if( gme_ptr->tweak_remove( surface_list, new_bodysm_list, extend_adjoining,
-     keep_surface, keep_old_body, preview ) == CUBIT_FAILURE )
+   CubitStatus removal_status =
+       gme_ptr->tweak_remove( surface_list,
+                              new_bodysm_list,
+                              extend_adjoining,
+                              keep_old_body,
+                              preview );
+
+
+   if( removal_status == CUBIT_FAILURE )
+   {
+     if(!preview)
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+     if( keep_surface )
+     {
+       int kk;
+       for( kk=kept_surface_list.size(); kk--; )
+       {
+         Surface *surf = kept_surface_list.get_and_step();
+         gme_ptr->get_gqe()->delete_solid_model_entities( surf );
+       }
+     }
+     if(!preview)
+      do_attribute_cleanup();
      return CUBIT_FAILURE;
+   }
+   else
+   {
+     if(!preview)
+     {
+        restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
+        remove_pushed_attributes(new_bodysm_list, old_body_list);
+     }
+   }
 
   // loop body sm list and find surfaces that need updating.
   // this is to account for some cases where the topology doesn't change, but the geometry does.
@@ -8188,17 +14234,38 @@
   }
 
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
+  DLIList<Body*> kept_surface_bodies;
+  if( preview == CUBIT_FALSE && keep_surface )
+  {
+    int kk;
+    for( kk=kept_surface_list.size(); kk--; )
+    {
+      Surface *surf = kept_surface_list.get_and_step();
+      Body *new_body = make_Body( surf );
+      kept_surface_bodies.append( new_body );
+    }
+  }
 
-  // Update graphics
+    // Update DAG
+  CubitStatus stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+  if(!preview)
+    do_attribute_cleanup();
+
+  if( keep_surface )
+    new_body_list += kept_surface_bodies;
+
+  if( stat == CUBIT_FAILURE)
+      return CUBIT_FAILURE;
+
+    // Update graphics
   while (entities_to_update.size())
     entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
 
-   return CUBIT_SUCCESS;
+  return CUBIT_SUCCESS;
 }
 
+
 //=============================================================================
 // Description: Function to remove curves from a sheet body and then extend the
 //              remaining curves or fill the gap or hole.
@@ -8214,23 +14281,128 @@
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
 
+  // clear any preview previews
+  GfxPreview::clear();
+
   gme_ptr = tweak_setup( ref_edge_list, "Removing", old_body_list, curve_list );
   if( !gme_ptr )
     return CUBIT_FAILURE;
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do remove
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_remove( curve_list, new_bodysm_list, keep_old_body, preview )
-    == CUBIT_FAILURE )
-    return CUBIT_FAILURE;
+  CubitStatus stat = gme_ptr->tweak_remove( curve_list, new_bodysm_list,
+                                            keep_old_body, preview );
+  //collect all neighboring curves to those in the list
+   int i, j;
+   DLIList<RefEdge*> neighboring_curves;
+   for( i=ref_edge_list.size(); i--; )
+   {
+     RefEdge *tmp_edge = ref_edge_list.get_and_step();
+     DLIList<RefVertex*> tmp_ref_vertex_list;
+     tmp_edge->ref_vertices( tmp_ref_vertex_list );
+     for( j=tmp_ref_vertex_list.size(); j--; )
+       tmp_ref_vertex_list.get_and_step()->ref_edges( neighboring_curves );
+   }
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
+  //uniquify and add other curves
+  neighboring_curves.uniquify_unordered();
+  //neighboring_curves += ref_edge_list;
 
-  return CUBIT_SUCCESS;
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    if( stat == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE)
+    return stat;
+
+  // loop body sm list and find curves that need updating.
+  // this is to account for some cases where the topology doesn't change, but the geometry does.
+  DLIList<RefEntity*> entities_to_update;
+  for(i=0; i<new_bodysm_list.size(); i++)
+  {
+    BodySM* bodysm = new_bodysm_list.get_and_step();
+    DLIList<Curve*> curves;
+    bodysm->curves(curves);
+    int j;
+    // find a surface that is also found in our input list
+    for(j=0; j<curves.size(); j++, curves.step())
+    {
+      BridgeManager* man = curves.get()->bridge_manager();
+      if(man)
+      {
+        RefEdge* ref_edge = CAST_TO(man->topology_entity(), RefEdge);
+        if( ref_edge && neighboring_curves.is_in_list(ref_edge) )
+        {
+          // get neighbors
+          DLIList<Point*> neighbor_points;
+          curves.get()->points(neighbor_points);
+          DLIList<Curve*> neighbor_curves;
+          DLIList<Surface*> neighbor_surfaces;
+          DLIList<TopologyBridge*> neighbors;
+          DLIList<TopologyBridge*> tmp;
+          int k;
+          for(k=0; k<neighbor_points.size(); k++)
+            neighbor_points.get_and_step()->surfaces(neighbor_surfaces);
+          for(k=0; k<neighbor_points.size(); k++)
+            neighbor_points.get_and_step()->curves(neighbor_curves);
+
+          CAST_LIST_TO_PARENT(neighbor_points, tmp);
+          neighbors += tmp;
+          neighbor_curves.uniquify_unordered();
+          CAST_LIST_TO_PARENT(neighbor_curves, tmp);
+          neighbors += tmp;
+          neighbor_surfaces.uniquify_unordered();
+          CAST_LIST_TO_PARENT(neighbor_surfaces, tmp);
+          neighbors += tmp;
+          //neighbors.append(curves.get()->lump());
+          //neighbors.append(curves.get()->bodysm());
+
+          for(k=0; k<neighbors.size(); k++)
+          {
+            if(BridgeManager* m = neighbors.get_and_step()->bridge_manager())
+            {
+              if(TopologyEntity* t = m->topology_entity())
+              {
+                entities_to_update.append(CAST_TO(t, RefEntity));
+                RefEntity *ref_ent = CAST_TO(t, RefEntity );
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if(preview == CUBIT_FALSE )
+  {
+    // Update DAG
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    // Update graphics
+    while (entities_to_update.size())
+      entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
+
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old_body )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+  }
+
+  return stat;
 }
 
+
 //=============================================================================
 // Description: Tweak specified faces of a volume or volumes up to a target
 //              surface or set of connected target surfaces.
@@ -8240,6 +14412,8 @@
 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefFace*> &ref_face_list,
                                               DLIList<RefFace*> &target_face_list,
                                               DLIList<Body*> &new_body_list,
+                                              CubitBoolean extend_flg,
+                                              CubitPlane *limit_plane,
                                               CubitBoolean reverse_flg,
                                               CubitBoolean keep_old_body,
                                               CubitBoolean preview )
@@ -8249,12 +14423,12 @@
   DLIList<Body*> old_body_list;
   GeometryModifyEngine *gme_ptr1, *gme_ptr2;
 
-  gme_ptr1 = tweak_setup( ref_face_list, "Tweaking", old_body_list, surface_list );
+  gme_ptr1 = tweak_setup( ref_face_list, "Tweaking", old_body_list, surface_list, CUBIT_TRUE );
   if (!gme_ptr1)
     return CUBIT_FAILURE;
 
   DLIList<Body*> old_body_list2;
-  gme_ptr2 = tweak_setup( target_face_list, "Tweaking", old_body_list2, target_surf_list );
+  gme_ptr2 = tweak_setup( target_face_list, "Tweaking", old_body_list2, target_surf_list, CUBIT_TRUE );
   if (!gme_ptr2)
     return CUBIT_FAILURE;
 
@@ -8264,16 +14438,101 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old_body )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_face_list );
+  }
+
+  int i;
+  DLIList<Body*> all_bodies = old_body_list;
+  all_bodies += old_body_list2;
+  DLIList<BodySM*> body_sms;
+  for(i=all_bodies.size(); i--;)
+  {
+    BodySM* bsm = all_bodies.get_and_step()->get_body_sm_ptr();
+    if(bsm)
+      body_sms.append_unique(bsm);
+  }
+
+  if(!preview)
+  {
+    do_attribute_setup();
+    push_vg_attributes_before_modify(body_sms);
+  }
+
   // Do tweak to target
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr1->tweak_target( surface_list, target_surf_list, new_bodysm_list,
-    reverse_flg, keep_old_body, preview ) == CUBIT_FAILURE )
+  CubitStatus stat = gme_ptr1->tweak_target( surface_list, target_surf_list,
+                                             new_bodysm_list, extend_flg,
+                                             limit_plane, reverse_flg, 
+                                             keep_old_body, preview );
+
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if(!preview)
+      remove_pushed_attributes(new_bodysm_list, all_bodies);
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
+    if(!preview)
+      do_attribute_cleanup();
     return CUBIT_FAILURE;
+  }
+  else
+  {
+    if(!preview)
+    {
+      restore_vg_after_modify(new_bodysm_list, all_bodies, gme_ptr1);
+      remove_pushed_attributes(new_bodysm_list, all_bodies);
+    }
+  }
 
+  // Collect all the old_faces to be compared against new_faces later...DJQ
+  DLIList<RefFace*> old_faces;
+  for (i = 0; i < old_body_list.size(); i++)
+  {
+      Body *old_body = old_body_list.get_and_step();
+      DLIList<RefFace*> tmp_faces;
+      old_body->ref_faces(tmp_faces);
+      old_faces +=tmp_faces;
+  }
+  
+  // Update DAG
+  stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+  if(!preview)
+    do_attribute_cleanup();
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
+    return CUBIT_FAILURE;
+  }
+
+  //collect all the new faces
+  DLIList<RefFace*> new_faces;
+  for( i=new_body_list.size(); i--; )
+  {
+    Body *new_body = new_body_list.get_and_step();
+    DLIList<RefFace*> tmp_faces;
+    new_body->ref_faces( tmp_faces );
+    new_faces += tmp_faces;
+  }
+
+  // Compare the new_faces list with the old_faces list to determine which faces are created
+  // Add these faces to the all_ref_face_list to check for its neighbors...DJQ
+  DLIList<RefFace*> difference = new_faces;
+  difference -= old_faces;
+  ref_face_list += difference;
+
+
   // loop body sm list and find surfaces that need updating.
   // this is to account for some cases where the topology doesn't change, but the geometry does.
   DLIList<RefEntity*> entities_to_update;
-  int i;
   for(i=0; i<new_bodysm_list.size(); i++)
   {
     BodySM* bodysm = new_bodysm_list.get_and_step();
@@ -8304,6 +14563,11 @@
           for(k=0; k<neighbor_points.size(); k++)
             neighbor_points.get_and_step()->curves(neighbor_curves);
 
+          for (int i = 0; i < neighbor_points.size(); i++)
+          {
+              int id = neighbor_points.get_and_step()->get_saved_id();
+              int temp = id;
+          }
           CAST_LIST_TO_PARENT(neighbor_points, tmp);
           neighbors += tmp;
           neighbor_curves.uniquify_unordered();
@@ -8324,14 +14588,89 @@
     }
   }
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
-    return CUBIT_FAILURE;
+  //unmerge any merged adjacent surfaces or
+  //merged curves in unmerged adjacent surfaces
+  DLIList<RefFace*> adjacent_faces_to_unmerge;
+  DLIList<RefEdge*> adjacent_edges_to_unmerge;
+  for(i=ref_face_list.size(); i--;)
+  {
+    RefFace *tweaked_face = ref_face_list.get_and_step();
+    if( !new_faces.move_to( tweaked_face ) )
+      continue;
 
+    //get all the edges of the face you tweaked
+    DLIList<RefEdge*> tweaked_face_edges;
+    tweaked_face->ref_edges( tweaked_face_edges );
+    adjacent_edges_to_unmerge += tweaked_face_edges;
+
+    //get all the adjacent faces to this edge
+    int j;
+    for( j=tweaked_face_edges.size(); j--; )
+    {
+      RefEdge *tmp_edge = tweaked_face_edges.get_and_step();
+      DLIList<RefFace*> tmp_faces;
+      tmp_edge->ref_faces( tmp_faces );
+      tmp_faces.remove( tweaked_face );
+      adjacent_faces_to_unmerge += tmp_faces;
+    }
+
+    //get all edges not in the surface,
+    //sharing vertices with the surface
+    DLIList<RefVertex*> ref_vertices;
+    tweaked_face->ref_vertices( ref_vertices );
+    for( j=ref_vertices.size(); j--; )
+    {
+      RefVertex *tmp_vert = ref_vertices.get_and_step();
+      DLIList<RefEdge*>  ref_edges;
+      tmp_vert->ref_edges( ref_edges );
+
+      int k;
+      for( k=ref_edges.size(); k--; )
+      {
+        RefEdge *tmp_edge = ref_edges.get_and_step();
+        if( !tweaked_face_edges.move_to( tmp_edge ) )
+          adjacent_edges_to_unmerge.append( tmp_edge );
+      }
+    }
+  }
+
+  //unmerge any adjacent faces
+  adjacent_faces_to_unmerge.uniquify_unordered();
+  for( i=adjacent_faces_to_unmerge.size(); i--; )
+  {
+    RefFace *ref_face = adjacent_faces_to_unmerge.get_and_step();
+
+    DLIList<TopologyBridge*> bridge_list;
+    ref_face->bridge_manager()->get_bridge_list(bridge_list);
+    if (bridge_list.size() > 1)
+    {
+      if( MergeTool::instance()->unmerge( ref_face ) )
+        PRINT_WARNING("Unmerging Surface %d\n", ref_face->id() );
+    }
+  }
+
+  //unmerge any adjacent edges
+  adjacent_edges_to_unmerge.uniquify_unordered();
+  for( i=adjacent_edges_to_unmerge.size(); i--; )
+  {
+    RefEdge *ref_edge = adjacent_edges_to_unmerge.get_and_step();
+    DLIList<TopologyBridge*> bridge_list;
+    ref_edge->bridge_manager()->get_bridge_list(bridge_list);
+    if (bridge_list.size() > 1)
+    {
+      if( MergeTool::instance()->unmerge( ref_edge) )
+        PRINT_WARNING("Unmerging Curve %d\n", ref_edge->id() );
+    }
+  }
+
+  if( CubitUndo::get_undo_enabled() && keep_old_body )
+    CubitUndo::note_result_bodies( new_body_list );
+
   // Update graphics
   while (entities_to_update.size())
     entities_to_update.pop()->notify_all_observers( GEOMETRY_MODIFIED );
 
+
   return CUBIT_SUCCESS;
 }
 
@@ -8352,7 +14691,7 @@
   DLIList<Body*> old_body_list;
   GeometryModifyEngine* gme_ptr;
 
-  gme_ptr = tweak_setup( ref_face_list, "Tweaking", old_body_list, surface_list );
+  gme_ptr = tweak_setup( ref_face_list, "Tweaking", old_body_list, surface_list, CUBIT_TRUE );
   if (!gme_ptr)
     return CUBIT_FAILURE;
 
@@ -8385,18 +14724,63 @@
     return CUBIT_FAILURE;
   }
 
+  int i;
+  DLIList<BodySM*> body_sms;
+  for(i=old_body_list.size(); i--;)
+  {
+    BodySM* bsm = old_body_list.get_and_step()->get_body_sm_ptr();
+    if(bsm)
+      body_sms.append_unique(bsm);
+  }
+
+  if(!preview)
+  {
+    do_attribute_setup();
+    push_vg_attributes_before_modify(body_sms);
+  }
+
   // Do tweak to target
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_target( surface_list, target_surf_list, new_bodysm_list,
-    reverse_flg, keep_old_body, preview ) == CUBIT_FAILURE )
+  CubitStatus stat = gme_ptr->tweak_target( surface_list, target_surf_list,
+                                            new_bodysm_list, CUBIT_TRUE,
+                                            NULL, reverse_flg, keep_old_body,
+                                            preview );
+
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if(!preview)
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
+    if(!preview)
+      do_attribute_cleanup();
     return CUBIT_FAILURE;
+  }
+  else
+  {
+    if(!preview)
+    {
+      restore_vg_after_modify(new_bodysm_list, old_body_list, gme_ptr);
+      remove_pushed_attributes(new_bodysm_list, old_body_list);
+    }
+  }
 
   // Delete temporary sheet body
   bodysm_ptr->get_geometry_query_engine()->delete_solid_model_entities( bodysm_ptr );
 
   // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
+  stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+  if(!preview)
+    do_attribute_cleanup();
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
   // Update graphics
   DLIList<Body*> moved_bodies(new_body_list);
@@ -8416,9 +14800,12 @@
 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefEdge*> &ref_edge_list,
                                               DLIList<RefFace*> &target_face_list,
                                               DLIList<Body*> &new_body_list,
+                                              CubitBoolean extend_flg,
+                                              CubitPlane *limit_plane,
                                               CubitBoolean reverse_flg,
                                               CubitBoolean keep_old,
-                                              CubitBoolean preview )
+                                              CubitBoolean preview,
+                                              double max_area_increase /*= 0%*/ )
 {
   DLIList<Curve*> curve_list(ref_edge_list.size());
   DLIList<Surface*> target_surf_list(target_face_list.size());
@@ -8440,16 +14827,45 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do tweak to target
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr1->tweak_target( curve_list, target_surf_list, new_bodysm_list,
-    reverse_flg, keep_old, preview ) == CUBIT_FAILURE )
+  CubitStatus stat = gme_ptr1->tweak_target( curve_list, target_surf_list,
+                                             new_bodysm_list, extend_flg,
+                                             limit_plane, reverse_flg,
+                                             keep_old, preview, max_area_increase );
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
   // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
+  stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old )
+      CubitUndo::note_result_bodies( new_body_list );
+  }
+
   // Update graphics
   DLIList<Body*> moved_bodies(new_body_list);
   moved_bodies.intersect(old_body_list);
@@ -8509,19 +14925,44 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do tweak to target
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr->tweak_target( curve_list, target_surf_list, new_bodysm_list,
-    reverse_flg, keep_old, preview ) == CUBIT_FAILURE )
+  CubitStatus stat = gme_ptr->tweak_target( curve_list, target_surf_list,
+                                            new_bodysm_list, CUBIT_TRUE,
+                                            NULL, reverse_flg, keep_old,
+                                            preview );
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
   // Delete temporary sheet body
   bodysm_ptr->get_geometry_query_engine()->delete_solid_model_entities( bodysm_ptr );
 
   // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
+  stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+  if( stat == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
+  if( CubitUndo::get_undo_enabled() && keep_old )
+    CubitUndo::note_result_bodies( new_body_list );
+
   // Update graphics
   DLIList<Body*> moved_bodies(new_body_list);
   moved_bodies.intersect(old_body_list);
@@ -8541,9 +14982,12 @@
 CubitStatus GeometryModifyTool::tweak_target( DLIList<RefEdge*> &ref_edge_list,
                                               DLIList<RefEdge*> &target_edge_list,
                                               DLIList<Body*> &new_body_list,
+                                              CubitBoolean extend_flg,
+                                              CubitPlane *limit_plane,
                                               CubitBoolean reverse_flg,
                                               CubitBoolean keep_old,
-                                              CubitBoolean preview )
+                                              CubitBoolean preview,
+                                              double max_area_increase /*= 0*/ )
 {
   DLIList<Curve*> curve_list(ref_edge_list.size());
   DLIList<Curve*> target_curve_list(target_edge_list.size());
@@ -8565,26 +15009,245 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  }
+
   // Do tweak to target
   DLIList<BodySM*> new_bodysm_list;
-  if( gme_ptr1->tweak_target( curve_list, target_curve_list, new_bodysm_list,
-    reverse_flg, keep_old, preview ) == CUBIT_FAILURE )
+  CubitStatus stat = gme_ptr1->tweak_target( curve_list, target_curve_list,
+                                             new_bodysm_list, extend_flg,
+                                             limit_plane, reverse_flg,
+                                             keep_old, preview, max_area_increase );
+
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    if( stat == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE)
+    return stat;
+
+  if( preview == CUBIT_FALSE )
+  {
+    // Update DAG
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled()  )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+  }
+
+  // Update graphics
+  DLIList<Body*> moved_bodies(new_body_list);
+  moved_bodies.intersect(old_body_list);
+  while (moved_bodies.size())
+    moved_bodies.pop()->notify_sub_all_observers( GEOMETRY_MODIFIED );
+
+  return stat;
+}
+
+//=============================================================================
+// Description: 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 given location will be
+//              projected to be on the planar surface(s) before being used.
+// Author     : Steve Storm
+// Date       : 09/09/08
+//=============================================================================
+CubitStatus
+GeometryModifyTool::tweak_target( RefVertex *ref_vertex_ptr,
+                                  DLIList<RefFace*> &modify_ref_face_list,
+                                  CubitVector &target_loc,
+                                  Body *&new_Body_ptr,
+                                  CubitBoolean keep_old,
+                                  CubitBoolean preview )
+{
+  if( modify_ref_face_list.size() == 0 )
+  {
+    PRINT_ERROR( "No surfaces found to modify\n" );
     return CUBIT_FAILURE;
+  }
 
-  // Update DAG
-  if (!finish_sm_op( old_body_list, new_bodysm_list, new_body_list ))
+  int i;
+  RefFace *ref_face_ptr;
+
+  // Check to make sure vertex is part of all given surfaces
+  modify_ref_face_list.reset();
+  for( i=modify_ref_face_list.size(); i--; )
+  {
+    ref_face_ptr = modify_ref_face_list.get_and_step();
+
+    if( !ref_face_ptr->is_directly_related( ref_vertex_ptr ) )
+    {
+      PRINT_ERROR( "Vertex %d is not part of 'modify' Surface %d\n", 
+        ref_vertex_ptr->id(), ref_face_ptr->id() );
+      return CUBIT_FAILURE;
+    }
+  }
+  
+  GeometryModifyEngine *gme_ptr;
+  DLIList<RefVertex*> ref_vertex_list(1);
+  ref_vertex_list.append( ref_vertex_ptr );
+  DLIList<Body*> old_body_list;
+  DLIList<Point*> point_list(1);
+  gme_ptr = tweak_setup( ref_vertex_list, "Tweaking", old_body_list, point_list );
+  if( !gme_ptr )
     return CUBIT_FAILURE;
 
+  // We already made sure the vertex is part of all of the modify faces, so
+  // just use the common_modify_engine function to get the surface_list
+  DLIList<Surface*> surface_list;
+  if( !common_modify_engine( modify_ref_face_list, surface_list ) )
+    return CUBIT_FAILURE;
+
+  // Make sure part of a sheet body, not a solid body
+  Body *body_ptr = ref_vertex_ptr->body();
+  if( !body_ptr->is_sheet_body() )
+  {
+    PRINT_ERROR( "Vertex %d is not in a sheet body - Body %d is solid.\n"
+      "       Tweaking a vertex to a target currently not possible on solid bodies.\n",
+      ref_vertex_ptr->id(), body_ptr->id() );
+    return CUBIT_FAILURE;
+  }
+
+  // Make sure all the given surfaces are planar
+  modify_ref_face_list.reset();
+  for( i=modify_ref_face_list.size(); i--; )
+  {
+    ref_face_ptr = modify_ref_face_list.get_and_step();
+
+    if( !ref_face_ptr->is_planar() )
+    {
+      PRINT_ERROR( "Surfaces to modify must be planar - Surface %d is not planar\n", ref_face_ptr->id() );
+      return CUBIT_FAILURE;
+    }
+  }
+
+  // Make sure all curves (on modify surfaces) attached to the given vertex are linear
+  // Get all attached curves
+  int j;
+  DLIList<RefEdge*> ref_edge_list;
+  ref_vertex_ptr->ref_edges( ref_edge_list );
+  RefEdge *ref_edge_ptr;
+  for( i=ref_edge_list.size(); i--; )
+  {
+    ref_edge_ptr = ref_edge_list.get_and_step();
+
+    // Check to see if this edge is linear, if it is in one of the modify surfaces
+    modify_ref_face_list.reset();
+    for( j=modify_ref_face_list.size(); j--; )
+    {
+      ref_face_ptr = modify_ref_face_list.get_and_step();
+      if( ref_face_ptr->is_directly_related( ref_edge_ptr ) )
+      {
+        Curve *curve_ptr = ref_edge_ptr->get_curve_ptr();
+        GeometryType curve_type = curve_ptr->geometry_type();
+        if( curve_type != STRAIGHT_CURVE_TYPE )
+        {
+          PRINT_ERROR( "Curve %d is not linear. Curves that are in the 'modify'\n"
+            "       surfaces attached to the tweak vertex must be linear.\n", 
+            ref_edge_ptr->id() );
+          return CUBIT_FAILURE;
+        }
+        else
+          break;
+      }
+    }
+  }
+
+  // Project the location to the given surfaces and make sure all of these locations
+  // are the same
+  modify_ref_face_list.reset();
+
+  CubitVector ref_loc( target_loc ); // Reference location
+  ref_face_ptr = modify_ref_face_list.get_and_step();
+  ref_face_ptr->move_to_surface( ref_loc );
+  int ref_surf_id = ref_face_ptr->id();
+
+  for( i=modify_ref_face_list.size()-1; i--; )
+  {
+    ref_face_ptr = modify_ref_face_list.get_and_step();
+
+    CubitVector proj_loc( target_loc );
+    ref_face_ptr->move_to_surface( proj_loc );
+
+    if( !ref_loc.about_equal( proj_loc ) )
+    {
+      PRINT_ERROR( "Target location must project to all of the 'modify' surfaces at\n"
+        "       exactly the same location - the tweaked Vertex %d will move to this\n"
+        "       common (same) projected location, tweaking the modify surfaces with it.\n"
+        "       Given target location = %f, %f, %f\n"
+        "       Projected location on Surface %d = %f, %f, %f\n"
+        "       Projected location on Surface %d = %f, %f, %f\n",
+        ref_vertex_ptr->id(),
+        target_loc.x(), target_loc.y(), target_loc.z(),
+        ref_surf_id, ref_loc.x(), ref_loc.y(), ref_loc.z(),
+        ref_face_ptr->id(), proj_loc.x(), proj_loc.y(), proj_loc.z() );
+
+      return CUBIT_FAILURE;
+    }
+  }
+
+  // It looks like the inputs are valid so get ready to do the tweak
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+  {
+    if( keep_old )
+      CubitUndo::save_state();
+    else
+      CubitUndo::save_state_with_cubit_file( ref_vertex_list );
+  }
+
+  Point *point_ptr = point_list.get();
+
+  // Do tweak to target
+  BodySM *new_bodysm_ptr;
+  CubitStatus stat = gme_ptr->tweak_target( point_ptr, surface_list, 
+                                            ref_loc,
+                                            new_bodysm_ptr, 
+                                            keep_old, preview );
+
+  if( CubitUndo::get_undo_enabled() && preview == CUBIT_FALSE )
+    if( stat == CUBIT_FAILURE )
+      CubitUndo::remove_last_undo();
+
+  if( stat == CUBIT_FAILURE)
+    return stat;
+
+  DLIList<BodySM*> new_bodysm_list;
+  new_bodysm_list.append( new_bodysm_ptr );
+  DLIList<Body*> new_body_list;
+
+  if( preview == CUBIT_FALSE )
+  {
+    // Update DAG
+    stat = finish_sm_op( old_body_list, new_bodysm_list, new_body_list );
+
+    if( CubitUndo::get_undo_enabled() )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+      else if( keep_old )
+        CubitUndo::note_result_bodies( new_body_list );
+    }
+  }
+
   // Update graphics
   DLIList<Body*> moved_bodies(new_body_list);
   moved_bodies.intersect(old_body_list);
   while (moved_bodies.size())
     moved_bodies.pop()->notify_sub_all_observers( GEOMETRY_MODIFIED );
 
-  return CUBIT_SUCCESS;
+  return stat;
 }
 
-
 // KGM
 #if 0
 bool GeometryModifyTool::contains_intermediate_geometry(DLIList<RefFace*>& ref_face_list) const
@@ -8598,15 +15261,16 @@
 }
 #endif
 
+/*
 //the following surface tool operations added by Tyronne Lim (CAT) ********************
 CubitStatus GeometryModifyTool::create_net_surface( DLIList<Surface*>& ref_face_list, BodySM *& new_body,
                                                     DLIList<DLIList<CubitVector*>*> &vec_lists_u,
                                                     DLIList<DLIList<CubitVector*>*> &vec_lists_v,
                                                     double net_tol, CubitBoolean heal )
-{
+{ 
    GeometryModifyEngine* GMEPtr = get_engine(ref_face_list.get());
    return GMEPtr->create_net_surface( ref_face_list, new_body, vec_lists_u, vec_lists_v, net_tol, heal );
-}
+} */
 
 CubitStatus GeometryModifyTool::create_net_surface( DLIList<RefEdge*>& u_curves, DLIList<RefEdge*>& v_curves,
                                                     double net_tol, CubitBoolean heal )
@@ -8643,14 +15307,29 @@
   DLIList<Curve*> curves_in_v(bridge_list.size());
   CAST_LIST( bridge_list, curves_in_v, Curve );
 
-  BodySM *new_body = NULL;
-  if( !GME_ptr->create_net_surface( curves_in_u, curves_in_v, new_body, net_tol, heal ) )
+  BodySM *new_smbody = NULL;
+  if( !GME_ptr->create_net_surface( curves_in_u, curves_in_v, new_smbody, net_tol, heal ) )
     return CUBIT_FAILURE;
 
-  if( GeometryQueryTool::instance()->make_Body( new_body ) )
+  if (CubitUndo::get_undo_enabled())
+    CubitUndo::save_state();
+
+  Body* new_body = NULL;
+  new_body = GeometryQueryTool::instance()->make_Body( new_smbody );
+  if( new_body )
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::note_result_body(new_body);
+
     return CUBIT_SUCCESS;
+  }
   else
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::remove_last_undo();
+
     return CUBIT_FAILURE;
+  }
 }
 
 CubitStatus GeometryModifyTool::create_offset_surface( RefFace* ref_face_ptr, double offset_distance )
@@ -8661,18 +15340,235 @@
   Surface *tmp_surf = NULL;
   tmp_surf = CAST_TO( bridge_ptr, Surface );
 
-  BodySM *new_body;
-  if( !GMEPtr->create_offset_surface( tmp_surf, new_body, offset_distance ) )
+  BodySM *new_smbody;
+  if( !GMEPtr->create_offset_surface( tmp_surf, new_smbody, offset_distance ) )
     return CUBIT_FAILURE;
 
-  if( GeometryQueryTool::instance()->make_Body( new_body ) )
+  if (CubitUndo::get_undo_enabled())
+    CubitUndo::save_state();
+
+  Body* new_body = NULL;
+  new_body = GeometryQueryTool::instance()->make_Body( new_smbody );
+  if( new_body )
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::note_result_body(new_body);
+
     return CUBIT_SUCCESS;
+  }
   else
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::remove_last_undo();
+
     return CUBIT_FAILURE;
+  }
 }
 
-CubitStatus GeometryModifyTool::create_offset_body( Body *body_ptr, Body *&new_body, double offset_distance )
+//-----------------------------------------------------------------------------
+// Purpose       : This function creates a sheet body or bodies by offsetting
+//                 the given faces. An 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.
+//
+// Special Notes :
+//
+// Creator       : Steve Storm
+//
+// Creation Date : 05/04/08
+//-----------------------------------------------------------------------------
+CubitStatus
+GeometryModifyTool::create_offset_sheet( DLIList<RefFace*> &ref_face_list,
+                                         double offset_distance,
+                                         DLIList<RefFace*> *add_ref_face_list_ptr,
+                                         DLIList<double> *add_offset_list_ptr,
+                                         DLIList<Body*> &new_body_list,
+                                         CubitBoolean preview )
 {
+  if( !ref_face_list.size() )
+  {
+    return CUBIT_SUCCESS;
+  }
+  else
+  {
+    for (int i = 0; i < ref_face_list.size(); i++)
+    {
+      RefFace *temp = ref_face_list.get_and_step();
+      if (temp->get_surface_ptr()->is_cylindrical() == 16)
+      {
+        DLIList<Curve*> curves;
+        CubitVector loc;
+        double rad;
+        temp->get_surface_ptr()->curves(curves);
+        curves.reset();
+        int j = 0;
+        while (curves.get()->geometry_type() != ELLIPSE_CURVE_TYPE && curves.get()->geometry_type() != ARC_CURVE_TYPE)
+        {
+          curves.step();
+          if (j == curves.size())
+          {
+              break;
+          }   
+          j++;
+        }
+        curves.get()->get_center_radius(loc, rad);
+        if (offset_distance >= rad)
+        {
+          CubitVector norm, close, result;
+          double angle;
+          temp->get_surface_ptr()->closest_point(loc, &close, &norm);
+          result.set(loc.x()-close.x(), loc.y()-close.y(), loc.z()-close.z());
+          angle = result.interior_angle(norm);
+          if (angle < GEOMETRY_RESABS && angle > -GEOMETRY_RESABS)
+          {
+            PRINT_ERROR("Offset is greater than the radius of curvature for surface %i.\n", temp->id());
+            PRINT_WARNING("No body will be created for surface %i.\n", temp->id());
+            if (ref_face_list.size() > 1)
+            {
+              ref_face_list.remove_all_with_value(temp);
+            }
+            else
+            {
+              return CUBIT_FAILURE;
+            }
+          }
+        }
+      }
+    }
+    for (int i = 0; i < add_ref_face_list_ptr->size(); i++)
+    {
+      RefFace *temp = ref_face_list.get_and_step();
+      if (temp->get_surface_ptr()->is_cylindrical() == 16)
+      {
+        DLIList<Curve*> curves;
+        CubitVector loc;
+        double rad;
+        temp->get_surface_ptr()->curves(curves);
+        curves.reset();
+        while (curves.get()->geometry_type() != ELLIPSE_CURVE_TYPE && curves.get()->geometry_type() != ARC_CURVE_TYPE)
+        {
+          curves.step();
+        }
+        curves.get()->get_center_radius(loc, rad);
+        if (offset_distance >= rad)
+        {
+          CubitVector norm, close, result;
+          double angle;
+          temp->get_surface_ptr()->closest_point(loc, &close, &norm);
+          result.set(loc.x()-close.x(), loc.y()-close.y(), loc.z()-close.z());
+          angle = result.interior_angle(norm);
+          if (angle < GEOMETRY_RESABS && angle > -GEOMETRY_RESABS)
+          {
+            PRINT_ERROR("Offset is greater than the radius of curvature for surface %i.\n", temp->id());
+            PRINT_WARNING("No body will be created for surface %i.\n", temp->id());
+            add_ref_face_list_ptr->remove_all_with_value(temp);
+          }
+        }
+      }
+    }
+  }
+
+  DLIList<RefFace*> all_ref_face_list(ref_face_list.size());
+  all_ref_face_list = ref_face_list;
+  if( add_ref_face_list_ptr->size() )
+    all_ref_face_list += *add_ref_face_list_ptr;
+
+  // Check for virtual geometry
+  DLIList<RefEntity*> ref_ent_list;
+  CAST_LIST_TO_PARENT(all_ref_face_list, ref_ent_list);
+  if ( GeometryQueryTool::instance()->contains_intermediate_geometry(ref_ent_list) )
+  {
+    PRINT_ERROR("OFFSETTING surfaces containing virtual geometry is not\n"
+      "       allowed. Delete virtual geometry on these surfaces\n"
+      "       before operation.\n" );
+    return CUBIT_FAILURE;
+  }
+
+  // Look for a common GeometryModifyEngine for all of the RefFaces
+  int count = all_ref_face_list.size();
+  DLIList<TopologyBridge*> bridge_list(count);
+  DLIList<TopologyEntity*> entity_list(count);
+  CAST_LIST_TO_PARENT( all_ref_face_list, entity_list );
+
+  GeometryModifyEngine* GME_ptr =
+    common_modify_engine( entity_list, bridge_list );
+  if(! GME_ptr )
+  {
+     PRINT_ERROR("Cannot construct offset sheet(s) using surfaces that\n"
+                 "       do not share a common geometry engine.\n");
+     return CUBIT_FAILURE;
+  }
+
+  // Get Surfaces from the RefFaces
+  DLIList<Surface*> surface_list(ref_face_list.size());
+  int i;
+  RefFace *ref_face_ptr;
+  for( i=ref_face_list.size(); i--; )
+  {
+    ref_face_ptr = ref_face_list.get_and_step();
+    surface_list.append( ref_face_ptr->get_surface_ptr() );
+  }
+
+  DLIList<Surface*> add_surf_list;
+  if( add_ref_face_list_ptr->size() )
+  {
+    for( i=add_ref_face_list_ptr->size(); i--; )
+    {
+      ref_face_ptr = add_ref_face_list_ptr->get_and_step();
+      add_surf_list.append( ref_face_ptr->get_surface_ptr() );
+    }
+  }
+
+  DLIList<BodySM*> BodySM_list;
+  if( add_surf_list.size() )
+  {
+    if( GME_ptr->create_offset_sheet( surface_list, offset_distance, &add_surf_list, 
+      add_offset_list_ptr, BodySM_list, preview ) == CUBIT_FAILURE )
+      return CUBIT_FAILURE;
+  }
+  else
+  {
+    if( GME_ptr->create_offset_sheet( surface_list, offset_distance, NULL, 
+      NULL, BodySM_list, preview ) == CUBIT_FAILURE )
+      return CUBIT_FAILURE;
+  }
+
+  if( !BodySM_list.size() )
+    return CUBIT_FAILURE;
+
+  BodySM *bodysm_ptr;
+  Body* body_ptr;
+  for( i=BodySM_list.size(); i--; )
+  {
+    DLIList<Surface*> surfs;
+    bodysm_ptr = BodySM_list.get_and_step();
+    bodysm_ptr->surfaces(surfs);
+    if (!surfs.size())
+    {
+      PRINT_WARNING("Empty body created.  Body deleted.\n");
+      PRINT_WARNING("Empty body likely due to an offset larger than the radius of curvature of a surface.\n");
+      bodysm_ptr->get_geometry_query_engine()->delete_solid_model_entities(bodysm_ptr);
+      break;
+    }
+
+    body_ptr = GeometryQueryTool::instance()->make_Body( bodysm_ptr );
+    if( body_ptr )
+      new_body_list.append( body_ptr );
+  }
+
+  if( new_body_list.size() )
+    return CUBIT_SUCCESS;
+  else
+    return CUBIT_FAILURE;
+}
+
+CubitStatus
+GeometryModifyTool::create_offset_body( Body *body_ptr, Body *&new_body,
+                                        double offset_distance )
+{
   GeometryModifyEngine* GMEPtr = get_engine(body_ptr);
 
   BodySM *body_sm = body_ptr->get_body_sm_ptr();
@@ -8686,20 +15582,44 @@
   if( !GMEPtr->create_offset_body( body_sm, new_body_sm, offset_distance ) )
     return CUBIT_FAILURE;
 
+  if (CubitUndo::get_undo_enabled())
+    CubitUndo::save_state();
+
   new_body = GeometryQueryTool::instance()->make_Body( new_body_sm );
 
   if( new_body )
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::note_result_body(new_body);
+
     return CUBIT_SUCCESS;
+  }
   else
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::remove_last_undo();
+
     return CUBIT_FAILURE;
+  }
 }
 
-CubitStatus GeometryModifyTool::create_skin_surface( DLIList<RefEdge*>& ref_edges, Body*& new_body )
+CubitStatus GeometryModifyTool::create_skin_surface( DLIList<RefEdge*>& ref_edges, Body*& new_body,
+                                                     DLIList<RefEdge*>& guides)
 {
   DLIList<TopologyBridge*> bridge_list;
   DLIList<TopologyEntity*> entity_list;
   CAST_LIST_TO_PARENT( ref_edges, entity_list );
 
+  DLIList<TopologyBridge*> guide_bridge_list;
+  DLIList<TopologyEntity*> guide_entity_list;
+  CAST_LIST_TO_PARENT(guides, guide_entity_list);
+
+  if (ref_edges.size() < 2)
+  {
+     PRINT_ERROR("Must specify at least 2 curves to create a skinned surface.\n");
+     return CUBIT_FAILURE;
+  }
+
   GeometryModifyEngine* GME_ptr =
     common_modify_engine( entity_list, bridge_list );
   if(! GME_ptr )
@@ -8709,20 +15629,48 @@
      return CUBIT_FAILURE;
   }
 
+  if (guides.size() > 0)
+  {
+      GeometryModifyEngine* GME_ptr2 =
+          common_modify_engine( guide_entity_list, guide_bridge_list );
+      if (GME_ptr != GME_ptr2)
+      {
+          PRINT_ERROR("Performing create skin with geometry from\n"
+			"different modeling engines is not allowed.\n");
+		  return CUBIT_FAILURE;
+      }
+  }
+
   DLIList<Curve*> curves_to_skin(bridge_list.size());
   CAST_LIST( bridge_list, curves_to_skin, Curve );
 
+  DLIList<Curve*> guide_curves(guide_bridge_list.size());
+  CAST_LIST(guide_bridge_list, guide_curves, Curve);
+
   BodySM *new_body_sm = NULL;
-  if( !GME_ptr->create_skin_surface( curves_to_skin, new_body_sm ) )
+  if( !GME_ptr->create_skin_surface( curves_to_skin, new_body_sm, guide_curves ) )
     return CUBIT_FAILURE;
 
+  if (CubitUndo::get_undo_enabled())
+    CubitUndo::save_state();
+
   new_body = NULL;
   new_body = GeometryQueryTool::instance()->make_Body( new_body_sm );
 
   if( new_body )
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::note_result_body(new_body);
+
     return CUBIT_SUCCESS;
+  }
   else
+  {
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::remove_last_undo();
+
     return CUBIT_FAILURE;
+  }
 }
 
 
@@ -8755,6 +15703,9 @@
     loft_surfaces.reset();
     BodySM* new_body_sm = 0;
 
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::save_state();
+
     CubitStatus result = result_ptr->loft_surfaces_to_body(
         loft_surfaces.get_and_step(),
         takeoff1,
@@ -8770,14 +15721,97 @@
     if(result && new_body_sm)
     {
         new_body = GeometryQueryTool::instance()->make_Body(new_body_sm);
+
+        if( CubitUndo::get_undo_enabled() )
+          CubitUndo::note_result_body(new_body);
     }
-
+    else
+    {
+      if( CubitUndo::get_undo_enabled() )
+        CubitUndo::remove_last_undo();
+    }
    return result;
 }
 
-CubitStatus GeometryModifyTool::create_surface( DLIList<CubitVector*>& vec_list, Body *&new_body,
-                                                RefFace *ref_face_ptr,CubitBoolean project_points )
+CubitStatus GeometryModifyTool::create_surface( DLIList<RefVertex*> &vert_list, 
+                                                Body *&new_body )
 {
+   //determine which vertices are free and which are not...
+   //copy ones that are not
+   vert_list.reset();
+   DLIList<Point*> points;
+   GeometryModifyEngine *GMEPtr = get_engine( vert_list.get()->get_point_ptr() );
+
+   DLIList<RefVertex*> free_ref_vertices;
+   int i;
+   for( i=vert_list.size(); i--; )
+   {
+     RefVertex *tmp_vert = vert_list.get_and_step();
+
+     if( tmp_vert->num_parent_ref_entities() == 0 )
+       free_ref_vertices.append( tmp_vert );
+
+     Point *tmp_point = tmp_vert->get_point_ptr();
+     if( GMEPtr != get_engine( tmp_point ) )
+     {
+       PRINT_INFO("Vertices are not from same modeling engine.\n");
+       return CUBIT_FAILURE;
+     }
+
+     if( tmp_vert->get_parents() == 0 )
+     {
+       points.append( tmp_point ); 
+     }
+     else
+     {
+       Point *new_point = GMEPtr->make_Point( tmp_vert->coordinates() );
+       points.append( new_point );
+     }
+   }
+
+   BodySM* body_sm = NULL;
+   CubitStatus stat = GMEPtr->create_surface( points, body_sm );
+
+   if( stat == CUBIT_FAILURE )
+     return stat;
+
+   if (CubitUndo::get_undo_enabled())
+     CubitUndo::save_state();
+
+   if( body_sm )
+     new_body = GeometryQueryTool::instance()->make_Body(body_sm);
+
+   if (new_body)
+   {
+     if (CubitUndo::get_undo_enabled())
+       CubitUndo::note_result_body(new_body);
+
+     stat = CUBIT_SUCCESS;
+   }
+   else
+   {
+     if (CubitUndo::get_undo_enabled())
+       CubitUndo::remove_last_undo();
+
+     stat = CUBIT_FAILURE;
+   }
+
+   for( i=free_ref_vertices.size(); i--; )
+   {
+     RefVertex *free_vertex = free_ref_vertices.get_and_step();
+     CubitObserver::notify_static_observers( free_vertex, TOP_LEVEL_ENTITY_DESTRUCTED );
+     CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, free_vertex );
+     GeometryQueryTool::instance()->history().add_event(evt);
+   }
+
+   return stat;
+}
+
+CubitStatus GeometryModifyTool::create_surface( DLIList<CubitVector*>& vec_list, 
+                                                Body *&new_body,
+                                                RefFace *ref_face_ptr,
+                                                CubitBoolean project_points )
+{
    GeometryModifyEngine* GMEPtr = gmeList.get();
    if( ref_face_ptr )
    {
@@ -8796,12 +15830,28 @@
 
    if( stat == CUBIT_FAILURE )
      return stat;
+
+   if (CubitUndo::get_undo_enabled())
+     CubitUndo::save_state();
+
    if( body_sm )
      new_body = GeometryQueryTool::instance()->make_Body(body_sm);
-   if( !new_body )
-     return CUBIT_FAILURE;
+
+   if (new_body)
+   {
+     if (CubitUndo::get_undo_enabled())
+       CubitUndo::note_result_body(new_body);
+
+     stat = CUBIT_SUCCESS;
+   }
    else
-     return CUBIT_SUCCESS;
+   {
+     if (CubitUndo::get_undo_enabled())
+       CubitUndo::remove_last_undo();
+
+     stat = CUBIT_FAILURE;
+   }
+   return stat;
 }
 
 CubitStatus GeometryModifyTool::create_weld_surface( CubitVector &root,
@@ -8825,6 +15875,9 @@
         return CUBIT_FAILURE;
     }
 
+    if (CubitUndo::get_undo_enabled())
+      CubitUndo::save_state();
+
     surfaces.reset();
     BodySM* new_body_sm = 0;
     CubitStatus result = GMEPtr->create_weld_surface(
@@ -8838,6 +15891,16 @@
     if(result && new_body_sm)
     {
         new_body = GeometryQueryTool::instance()->make_Body(new_body_sm);
+        if (new_body)
+        {
+          if (CubitUndo::get_undo_enabled())
+            CubitUndo::note_result_body(new_body);
+        }
+        else
+        {
+          if (CubitUndo::get_undo_enabled())
+            CubitUndo::remove_last_undo();
+        }
     }
     return result;
 }
@@ -8862,7 +15925,10 @@
   entity->get_child_ref_entities(children);
   children.last();
   for (int i = children.size(); i--; )
+  {
+    //PRINT_INFO("Removing dead entity on %s %d\n", children.get()->class_name(), children.get()->id() );
     remove_dead_entity_names( children.step_and_get() );
+  }
 }
 
 //-------------------------------------------------------------------------
@@ -8884,6 +15950,529 @@
   return 0;
 }
 
+CubitStatus GeometryModifyTool::tolerant_imprint( DLIList<RefFace*> &ref_faces,
+                                                  DLIList<RefEdge*> &ref_edge_list,
+                                                  DLIList<Body*> &new_bodies,
+                                                  bool merge )
+{
+  if( ref_faces.size() > 2 )
+    return CUBIT_FAILURE;
+
+  ref_faces.reset();
+  RefFace *face1 = ref_faces.get_and_step();
+  RefFace *face2 = ref_faces.get_and_step();
+
+  if(ref_edge_list.size() > 0)
+  {
+    //collect all the bodies containing any edge on these 2 surfaces
+    //so you can merge them afterward
+    DLIList<Body*> bodies_to_merge;
+    if( merge )
+    {
+      DLIList<RefEdge*> tmp_edges;
+      face1->ref_edges( tmp_edges);
+
+      int j;
+      for( j=tmp_edges.size(); j--; )
+      {
+        RefEdge *tmp_edge = tmp_edges.get_and_step();
+        DLIList<Body*> body_list;
+        tmp_edge->bodies( body_list );
+        bodies_to_merge += body_list;
+      }
+
+      for( j=ref_edge_list.size(); j--; )
+      {
+        RefEdge *tmp_edge = ref_edge_list.get_and_step();
+        DLIList<Body*> body_list;
+        tmp_edge->bodies( body_list );
+        bodies_to_merge += body_list;
+      }
+
+      tmp_edges.clean_out();
+      face2->ref_edges( tmp_edges );
+
+      for( j=tmp_edges.size(); j--; )
+      {
+        RefEdge *tmp_edge = tmp_edges.get_and_step();
+        DLIList<Body*> body_list;
+        tmp_edge->bodies( body_list );
+        bodies_to_merge += body_list;
+      }
+      bodies_to_merge.uniquify_unordered();
+    }
+
+    DLIList<RefEdge*> edges_to_imprint_onto_face1;
+    DLIList<RefEdge*> edges_to_imprint_onto_face2;
+
+    //sort edges...
+    //edges on face1 and not on face2 will be imprinted on face2
+    //edges on face2 and not on face1 will be imprinted on face1
+    int i;
+    for(i=ref_edge_list.size(); i--; )
+    {
+      RefEdge *tmp_edge = ref_edge_list.get_and_step();
+      DLIList<RefFace*> tmp_faces;
+      tmp_edge->ref_faces( tmp_faces );
+
+      if( tmp_faces.move_to( face1 ) && !tmp_faces.move_to( face2 ) )
+        edges_to_imprint_onto_face2.append( tmp_edge );
+      else if( tmp_faces.move_to( face2 ) && !tmp_faces.move_to( face1 ) )
+        edges_to_imprint_onto_face1.append( tmp_edge );
+      else
+        PRINT_ERROR("Will not imprint curve %d onto either surface.\n", tmp_edge->id() );
+    }
+
+    //if there are edges to impint onto both surfaces
+    if( edges_to_imprint_onto_face1.size() &&
+        edges_to_imprint_onto_face2.size() )
+    {
+      //get the modify engine
+      DLIList<Surface*> surf_list( 1 );
+      DLIList<Curve*> curve_list( edges_to_imprint_onto_face2.size() );
+      DLIList<RefFace*> ref_face_list( 1 );
+      ref_face_list.append( face2 );
+      GeometryModifyEngine* gme = common_modify_engine( ref_face_list,
+                                                        edges_to_imprint_onto_face2,
+                                                        surf_list,
+                                                        curve_list );
+      if ( !gme )
+      {
+        PRINT_ERROR("Performing IMPRINT with entities containing geometry from\n"
+                    "different modeling engines is not allowed.\n" );
+        return CUBIT_FAILURE;
+      }
+
+      //copy the specified boundary curves of face1 to imprint onto face2...
+      //these could be stale after we imprint face1
+      DLIList<Curve*> copied_curves;
+      for(i=curve_list.size(); i--; )
+      {
+        Curve *copied_curve = gme->make_Curve( curve_list.get_and_step() );
+        copied_curves.append( copied_curve );
+      }
+
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::save_state_with_cubit_file( ref_faces );
+
+      //do the imprint onto face1
+      Body *new_body = NULL;
+      CubitStatus status;
+      status = tolerant_imprint( face1, edges_to_imprint_onto_face1, new_body );
+
+      //if we failed...get out
+      if( status == CUBIT_FAILURE )
+      {
+        //delete the copied curves
+        for( i=copied_curves.size(); i--; )
+          gme->get_gqe()->delete_solid_model_entities( copied_curves.get_and_step() );
+
+        if( CubitUndo::get_undo_enabled() )
+          CubitUndo::remove_last_undo();
+
+        return CUBIT_FAILURE;
+      }
+
+      DLIList<Body*> original_body_list;
+      face2->bodies( original_body_list );
+
+      //get the Surface* ptr
+      Surface *surface2 = face2->get_surface_ptr();
+
+      DLIList<BodySM*> body_sm_list;
+      for(i=original_body_list.size(); i--;)
+        body_sm_list.append(original_body_list.get_and_step()->get_body_sm_ptr());
+
+      int process_composites = 0;
+      if(contains_composites(original_body_list))
+        process_composites = 1;
+
+      if(process_composites)
+      {
+        // Push virtual attributes down to solid model topology before
+        // doing the imprint.
+        do_attribute_setup();
+        push_vg_attributes_before_modify(body_sm_list);
+        // This must be done after pushing the vg atts because it uses them.
+        push_imprint_attributes_before_modify(body_sm_list);
+      }
+
+      //do the imprint onto face2
+      BodySM *new_bodysm = NULL;
+      DLIList<TopologyBridge*> new_tbs, att_tbs, temporary_bridges;
+      status = gme->tolerant_imprint_surface_with_curves( surface2, copied_curves, temporary_bridges, new_bodysm,
+        &new_tbs, &att_tbs);
+      temporary_bridges.uniquify_ordered();
+      while(temporary_bridges.size())
+        delete temporary_bridges.pop();
+
+      DLIList<BodySM*> new_body_list;
+      if(new_bodysm)
+        new_body_list.append(new_bodysm);
+
+
+      //delete the copied curves
+      for( i=copied_curves.size(); i--; )
+        gme->get_gqe()->delete_solid_model_entities( copied_curves.get_and_step() );
+
+      if( status == CUBIT_FAILURE )
+      {
+        if( CubitUndo::get_undo_enabled() )
+          CubitUndo::remove_last_undo();
+
+        if(process_composites)
+        {
+          remove_pushed_attributes(new_body_list, original_body_list);
+          do_attribute_cleanup();
+        }
+
+        return CUBIT_FAILURE;
+      }
+      else
+      {
+        if(process_composites)
+        {
+          // Analyze the results and adjust virtual attributes as necessary.
+        DLIList<TopologyBridge*> tb_list;
+        CAST_LIST(new_body_list, tb_list, TopologyBridge);
+          GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+            tb_list, original_body_list);
+
+          // Clean up attributes.
+          remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
+
+          // Restore the virtual geometry.
+          restore_vg_after_modify(new_body_list, original_body_list, gme);
+          remove_pushed_attributes(new_body_list, original_body_list);
+        }
+      }
+
+      DLIList<BodySM*> new_bodies;
+      new_bodies.append( new_bodysm );
+      DLIList<Body*> result_bodies;
+      status = finish_sm_op( original_body_list, new_bodies, result_bodies );
+
+      if(process_composites)
+        do_attribute_cleanup();
+
+      if( status == CUBIT_FAILURE )
+      {
+        if( CubitUndo::get_undo_enabled() )
+          CubitUndo::remove_last_undo();
+        return CUBIT_FAILURE;
+      }
+    }
+    //user specified edges that will only imprint onto face1...do it anyway
+    else if( edges_to_imprint_onto_face1.size() )
+    {
+      if( CubitUndo::get_undo_enabled() )
+      {
+        DLIList<RefFace*> tmp_faces(1);
+        tmp_faces.append( face1 );
+        CubitUndo::save_state_with_cubit_file( tmp_faces );
+      }
+
+      bool undo_enabled = CubitUndo::get_undo_enabled();
+      CubitUndo::set_undo_enabled( false );
+
+      Body *new_body = NULL;
+      CubitStatus stat = tolerant_imprint( face1, edges_to_imprint_onto_face1,
+                                          new_body, merge );
+
+    if( undo_enabled )
+      CubitUndo::set_undo_enabled( true );
+
+    if( CubitUndo::get_undo_enabled() )
+    {
+      if( stat == CUBIT_FAILURE )
+        CubitUndo::remove_last_undo();
+    }
+
+      return stat;
+    }
+    //user specified edges that will only imprint onto face2...do it anyway
+    else if( edges_to_imprint_onto_face2.size() )
+    {
+      if( CubitUndo::get_undo_enabled() )
+      {
+        DLIList<RefFace*> tmp_faces(1);
+        tmp_faces.append( face2 );
+        CubitUndo::save_state_with_cubit_file( tmp_faces );
+      }
+
+      bool undo_enabled = CubitUndo::get_undo_enabled();
+      CubitUndo::set_undo_enabled( false );
+
+      Body *new_body = NULL;
+      CubitStatus stat = tolerant_imprint( face2, edges_to_imprint_onto_face2,
+                                          new_body, merge );
+
+      if( undo_enabled )
+        CubitUndo::set_undo_enabled( true );
+
+      if( CubitUndo::get_undo_enabled() )
+      {
+        if( stat == CUBIT_FAILURE )
+          CubitUndo::remove_last_undo();
+      }
+
+      return stat;
+    }
+
+    if( merge )
+      MergeTool::instance()->merge_bodies( bodies_to_merge );
+  }
+  else
+  {
+    DLIList<RefFace*> faces_not_to_merge;
+    Body *body1 = face1->body();
+    Body *body2 = face2->body();
+    /*
+    if(merge)
+    {
+      DLIList<RefFace*> tmp_faces;
+      body1->ref_faces(tmp_faces);
+      if(tmp_faces.move_to(face1))
+        tmp_faces.extract();
+      faces_not_to_merge = tmp_faces;
+
+      tmp_faces.clean_out();
+      body2->ref_faces(tmp_faces);
+      if(tmp_faces.move_to(face2))
+        tmp_faces.extract();
+      faces_not_to_merge += tmp_faces;
+    }
+    */
+
+    //get the modify engine
+    DLIList<Surface*> surf_list( 1 );
+    DLIList<RefFace*> ref_face_list( 2 );
+    ref_face_list.append( face1 );
+    ref_face_list.append( face2 );
+    GeometryModifyEngine* gme = common_modify_engine( ref_face_list, surf_list);
+
+    if ( !gme )
+    {
+      PRINT_ERROR("Performing IMPRINT with entities containing geometry from\n"
+                  "different modeling engines is not allowed.\n" );
+      return CUBIT_FAILURE;
+    }
+
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::save_state_with_cubit_file( ref_faces );
+
+    //do the imprint onto face1
+    DLIList<BodySM*> new_bodysm_list;
+    CubitStatus status = gme->tolerant_imprint(surf_list, new_bodysm_list);
+
+    //if we failed...get out
+    if( status == CUBIT_FAILURE )
+    {
+      if( CubitUndo::get_undo_enabled() )
+        CubitUndo::remove_last_undo();
+
+      return CUBIT_FAILURE;
+    }
+
+    DLIList<Body*> result_bodies;
+    DLIList<Body*> original_body_list;
+    original_body_list.append(body1);
+    original_body_list.append(body2);
+    status = finish_sm_op( original_body_list, new_bodysm_list, result_bodies );
+
+    /*
+    if( merge )
+    {
+      DLIList<RefFace*> faces_to_merge, tmp_faces;
+      body1->ref_faces(faces_to_merge);
+      body2->ref_faces(tmp_faces);
+      faces_to_merge -= faces_not_to_merge;
+      if(faces_to_merge.size() > 1)
+      {
+        MergeTool::instance()->merge_reffaces(faces_to_merge);
+      }
+    }
+    */
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+
+CubitStatus GeometryModifyTool::tolerant_imprint( RefFace *ref_face,
+                                                  DLIList<RefEdge*> &ref_edge_list,
+                                                  Body *&new_body,
+                                                  bool merge )
+{
+  int i;
+  DLIList<Body*> bodies_to_merge;
+  if( merge )
+  {
+    DLIList<RefEdge*> tmp_edges;
+    ref_face->ref_edges( tmp_edges );
+
+    for( i=tmp_edges.size(); i--; )
+    {
+      RefEdge *tmp_edge = tmp_edges.get_and_step();
+      DLIList<Body*> body_list;
+      tmp_edge->bodies( body_list );
+      bodies_to_merge += body_list;
+    }
+
+    for( i=ref_edge_list.size(); i--; )
+    {
+      RefEdge *tmp_edge = ref_edge_list.get_and_step();
+      DLIList<Body*> body_list;
+      tmp_edge->bodies( body_list );
+      bodies_to_merge += body_list;
+    }
+
+    bodies_to_merge.uniquify_unordered();
+  }
+
+
+  DLIList<Body*> original_body_list;
+  ref_face->bodies( original_body_list );
+
+  DLIList<Surface*> surf_list( 1 );
+  DLIList<Curve*> curve_list(ref_edge_list.size());
+  DLIList<RefFace*> ref_face_list( 1 );
+  ref_face_list.append( ref_face );
+  GeometryModifyEngine* gme = common_modify_engine( ref_face_list,
+                                                    ref_edge_list,
+                                                    surf_list,
+                                                    curve_list,
+                                                    true);
+  if ( !gme )
+  {
+    PRINT_ERROR("Performing IMPRINT with entities containing geometry from\n"
+                "different modeling engines is not allowed.\n" );
+    return CUBIT_FAILURE;
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefFace*> ref_faces(1);
+    ref_faces.append( ref_face );
+    CubitUndo::save_state_with_cubit_file( ref_faces );
+  }
+
+  DLIList<BodySM*> body_sm_list;
+  for(i=original_body_list.size(); i--;)
+    body_sm_list.append(original_body_list.get_and_step()->get_body_sm_ptr());
+
+  int process_composites = 0;
+  if(contains_composites(original_body_list))
+    process_composites = 1;
+
+  DLIList<TopologyBridge*> tb_list;
+  if(process_composites)
+  {
+    // Turn certain attributes on.
+    do_attribute_setup();
+    // Push virtual attributes down to solid model topology before
+    // doing the imprint.
+    push_vg_attributes_before_modify(body_sm_list);
+    DLIList<TopologyBridge*> tmp_tb_list;
+    CAST_LIST(surf_list, tmp_tb_list, TopologyBridge);
+    // Put "ORIGINAL" attributes on the bodies being imprinted and
+    // the curves as these originally existed.
+    push_named_attributes_to_curves_and_points(tmp_tb_list, "ORIGINAL");
+    CAST_LIST(curve_list, tb_list, TopologyBridge);
+    push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
+    push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
+  }
+
+  CubitStatus status = CUBIT_FAILURE;
+  DLIList<BodySM*> new_body_list;
+  DLIList<TopologyBridge*> new_tbs, att_tbs;
+  // The bridges doing the imprinting often get split during the process but
+  // because of the way we are making copies, the IMPRINTER attribute doesn't
+  // get propagated to them.  temporary_bridges will be filled in with any
+  // additional IMPRINTER bridges we need to consider below when deciding whether to
+  // keep composite attributes.
+  DLIList<TopologyBridge*> temporary_bridges;
+  for(i=surf_list.size(); i>0; i--)
+  {
+    Surface *cur_surf = surf_list.get_and_step();
+    BodySM *new_body_sm = NULL;
+    CubitStatus tmp_status = gme->tolerant_imprint_surface_with_curves(
+                                                cur_surf, curve_list,
+                                                temporary_bridges,
+                                                new_body_sm,
+                                                &new_tbs, &att_tbs);
+    if(new_body_sm)
+      new_body_list.append(new_body_sm);
+    if(tmp_status == CUBIT_SUCCESS)
+      status = tmp_status;
+  }
+
+  temporary_bridges.uniquify_ordered();
+
+  if( status == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
+
+    if(process_composites)
+    {
+      remove_pushed_attributes(new_body_list, original_body_list);
+      do_attribute_cleanup();
+    }
+    return CUBIT_FAILURE;
+  }
+  else
+  {
+    if(process_composites)
+    {
+      // Analyze the results and adjust virtual attributes as necessary.
+      DLIList<TopologyBridge*> tmp_tb_list;
+      CAST_LIST(new_body_list, tmp_tb_list, TopologyBridge);
+      tb_list.merge_unique(tmp_tb_list);
+      // The bridges coming back in temporary_bridges may not have IMPRINTER
+      // attributes on them becuase of the way they were generated below.  Make
+      // sure they get IMPRINTER attributes.
+      push_named_attributes_to_curves_and_points(temporary_bridges, "IMPRINTER");
+      tb_list += temporary_bridges;
+      GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+        tb_list, original_body_list);
+
+      while(temporary_bridges.size())
+        delete temporary_bridges.pop();
+
+      // Clean up attributes.
+      remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
+
+      // Restore the virtual geometry.
+      restore_vg_after_modify(new_body_list, original_body_list, gme);
+      remove_pushed_attributes(new_body_list, original_body_list);
+    }
+  }
+
+  DLIList<Body*> result_bodies;
+  status = finish_sm_op( original_body_list, new_body_list, result_bodies );
+
+  if(process_composites)
+    do_attribute_cleanup();
+
+  if( status == CUBIT_FAILURE )
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
+    return CUBIT_FAILURE;
+  }
+
+  if( merge )
+    MergeTool::instance()->merge_bodies( bodies_to_merge );
+
+  if( result_bodies.size() == 1 )
+    new_body = result_bodies.get();
+  else
+    return CUBIT_FAILURE;
+
+  return status;
+}
+
 CubitStatus GeometryModifyTool::tolerant_imprint( DLIList<Body*> &bodies,
                                       DLIList<Body*> &new_bodies, bool merge )
 {
@@ -8902,7 +16491,7 @@
   //make sure that merge tolerance is not inapproiate for model
   int i;
   CubitBox bounding_box( CubitVector(0,0,0),
-                         CubitVector(CUBIT_DBL_MAX, 
+                         CubitVector(CUBIT_DBL_MAX,
                                      CUBIT_DBL_MAX,
                                      CUBIT_DBL_MAX ) );
   for( i=bodies.size(); i--; )
@@ -8910,26 +16499,29 @@
     CubitBox tmp_box = bodies.get_and_step()->bounding_box();
     if(bounding_box.max_x() == CUBIT_DBL_MAX)
       bounding_box = tmp_box;
-    else if( tmp_box.diagonal().length_squared() < 
+    else if( tmp_box.diagonal().length_squared() <
         bounding_box.diagonal().length_squared() )
       bounding_box = tmp_box;
   }
-   
-  //get the merge tolerance 
+
+  //get the merge tolerance
   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
- 
-  //if the merge tolerance is greater than 1/10th the length of the 
+
+  //if the merge tolerance is greater than 1/10th the length of the
   //diagonal of the bounding box of the smallest volume, fail!
-  double tenth_smallest_bbox = 0.1*(bounding_box.diagonal().length()); 
-  if( tolerance > tenth_smallest_bbox ) 
+  double tenth_smallest_bbox = 0.1*(bounding_box.diagonal().length());
+  if( tolerance > tenth_smallest_bbox )
   {
-    PRINT_ERROR("Merge tolerance is set excessively high.  Must be lowner than %lf\n", 
+    PRINT_ERROR("Merge tolerance is set excessively high.  Must be lower than %lf\n",
                  tenth_smallest_bbox );
     PRINT_INFO("       (Merge tolerance must be less than than 1/10th of the diagonal\n"
                         "of the bounding box of the smallest volume)\n");
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state_with_cubit_file( bodies );
+
   body_sm_list.clean_out();
   DLIList<Body*> old_body_list;
   old_body_list += bodies;
@@ -8948,40 +16540,56 @@
     do_attribute_setup();
     push_vg_attributes_before_modify(body_sm_list);
     // This must be done after pushing the vg atts because it uses them.
-    push_imprint_attributes_before_modify(body_sm_list);
+    DLIList<TopologyBridge*> tb_list;
+    CAST_LIST(body_sm_list, tb_list, TopologyBridge);
+    push_named_attributes_to_curves_and_points(tb_list, "IMPRINTER");
+    push_named_attributes_to_curves_and_points(tb_list, "ORIGINAL");
   }
 
   DLIList<BodySM*> new_body_list;
   DLIList<TopologyBridge*> new_tbs, att_tbs;
-  CubitStatus result = gme->tolerant_imprint( body_sm_list, new_body_list, &new_tbs, &att_tbs ) ;
+  CubitStatus result = gme->tolerant_imprint( body_sm_list, new_body_list, &new_tbs, &att_tbs );
 
-  if(process_composites)
-  {
-    // Analyze the results and adjust virtual attributes as necessary.
-    GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
-      new_body_list, bodies);
 
-    // Clean up attributes.
-    remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
-
-    // Restore the virtual geometry.
-    restore_vg_after_modify(new_body_list, bodies);
-  }
-
   if(result == CUBIT_FAILURE)
   {
     if(process_composites)
+    {
+      remove_pushed_attributes(new_body_list, bodies);
       do_attribute_cleanup();
+    }
     return result;
   }
+  else
+  {
+    if(process_composites)
+    {
+      // Analyze the results and adjust virtual attributes as necessary.
+       DLIList<TopologyBridge*> tb_list;
+       CAST_LIST(new_body_list, tb_list, TopologyBridge);
+      GeometryQueryTool::instance()->ige_attribute_after_imprinting(new_tbs, att_tbs,
+        tb_list, bodies);
 
+      // Clean up attributes.
+      remove_imprint_attributes_after_modify(body_sm_list, new_body_list);
+
+      // Restore the virtual geometry.
+      restore_vg_after_modify(new_body_list, bodies, gme);
+      remove_pushed_attributes(new_body_list, bodies);
+    }
+  }
+
   result = finish_sm_op( bodies, body_sm_list, new_bodies );
 
   if(process_composites)
     do_attribute_cleanup();
 
-  if(!result)
+  if(result == CUBIT_FAILURE)
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
   if( merge )
     MergeTool::instance()->merge_bodies( bodies );
@@ -9000,6 +16608,9 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state_with_cubit_file( bodies );
+
   CubitStatus status = CUBIT_FAILURE;
   DLIList<BodySM*> modified_bodies;
   int i;
@@ -9013,11 +16624,600 @@
     }
   }
 
-  DLIList<Body*> dummy_list;
-  if(!finish_sm_op( bodies, modified_bodies, dummy_list))
+  if( status == CUBIT_FAILURE )
+  {
+    PRINT_WARNING("Did not remove any sliver curves\n");
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
     return CUBIT_FAILURE;
+  }
 
+  DLIList<Body*> dummy_list;
+  status = finish_sm_op( bodies, modified_bodies, dummy_list );
+  if( status == CUBIT_FAILURE )
+  {
+    PRINT_WARNING("Did not remove any sliver curves\n");
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
+    return CUBIT_SUCCESS;
+  }
+
   return status;
 }
 
+void GeometryModifyTool::split_surface_with_narrow_region(RefFace *face,
+                                                      DLIList<CubitVector> &split_pos1_list,
+                                                      DLIList<CubitVector> &split_pos2_list)
+{
+  int k;
+  if(split_pos1_list.size() > 0)
+  {
+    DLIList<DLIList<CubitVector*>*> vec_lists;
+    DLIList<CubitVector*> pt_list;
+    for(k=split_pos1_list.size(); k--;)
+    {
+      CubitVector split_pos1 = split_pos1_list.get_and_step();
+      CubitVector split_pos2 = split_pos2_list.get_and_step();
+      face->move_to_surface(split_pos1);
+      face->move_to_surface(split_pos2);
+      DLIList<CubitVector*> *vec_list = new DLIList<CubitVector*>;
+      vec_list->append( new CubitVector(split_pos1));
+      vec_list->append( new CubitVector(split_pos2));
+      vec_lists.append( vec_list );
+    }
 
+    GeometryModifyTool::instance()->split_surface(face,
+      pt_list, vec_lists );
+
+    while( vec_lists.size() )
+    {
+      DLIList<CubitVector*> *vec_list = vec_lists.pop();
+      while( vec_list->size() ) delete vec_list->pop();
+      delete vec_list;
+    }
+    /*
+    while( pt_list.size() )
+      delete( pt_list.pop() );
+      */
+  }
+}
+
+void GeometryModifyTool::fixup_merged_entities( DLIList<int> &merged_surface_ids,
+                                                DLIList<int> &merged_curve_ids ) const
+{
+  //use ids to find surviving merged entities
+  DLIList<RefFace*> ref_face_list;
+  DLIList<RefEdge*> ref_edge_list;
+
+  int i;
+  //see what merged survived operation
+  for( i=merged_surface_ids.size(); i--; )
+  {
+    int face_id = merged_surface_ids.get_and_step();
+    RefFace *surviving_merged_face = RefEntityFactory::instance()->get_ref_face( face_id );
+    if( surviving_merged_face )
+      ref_face_list.append( surviving_merged_face );
+  }
+
+  //see what merged survived operation
+  for( i=merged_curve_ids.size(); i--; )
+  {
+    int edge_id = merged_curve_ids.get_and_step();
+    RefEdge *surviving_merged_edge = RefEntityFactory::instance()->get_ref_edge( edge_id );
+    if( surviving_merged_edge )
+      ref_edge_list.append( surviving_merged_edge );
+  }
+
+  //fix up merged faces -- some might need to be reversed
+  for(i=ref_face_list.size(); i--; )
+  {
+    RefFace *merged_face = ref_face_list.get_and_step();
+    BasicTopologyEntity *bte = static_cast<BasicTopologyEntity*>(merged_face);
+
+    //get the first bridge of the entity
+    DLIList<TopologyBridge*> face_bridge_list;
+    bte->bridge_manager()->get_bridge_list( face_bridge_list );
+
+    //if there are 2 bridges in the list, it's still merged...do nothing
+    if( face_bridge_list.size() > 1 )
+      continue;
+
+    //get the center of the RefFace
+    CubitVector center = merged_face->center_point();
+
+    //get the normal according to the RefFace
+    CubitVector ref_face_normal = merged_face->normal_at( center );
+
+    //get the normal at the center from the underlying Surface
+    Surface *surface_ptr = CAST_TO( face_bridge_list.get(), Surface );
+    CubitVector surface_normal;
+    surface_ptr->closest_point( center, NULL, &surface_normal );
+
+    //if normals are opposite, flip sense of surface_ptr
+    if( fabs(ref_face_normal.interior_angle( surface_normal ) - 180 ) < 0.1  )
+      merged_face->reverse_normal();
+
+    //One more thing.....if surface is a composite, update the graphics
+    //on the hidden curve...could have been deleted.
+    if ( GeometryQueryTool::instance()->ige_is_composite( surface_ptr ) )
+      merged_face->notify_all_observers( TOPOLOGY_MODIFIED );
+  }
+
+  //fix up merged edges -- some might need to be reversed
+  for(i=ref_edge_list.size(); i--; )
+  {
+    RefEdge *merged_edge = ref_edge_list.get_and_step();
+    BasicTopologyEntity *bte = static_cast<BasicTopologyEntity*>(merged_edge);
+
+    //get the first bridge of the entity
+    DLIList<TopologyBridge*> edge_bridge_list;
+    bte->bridge_manager()->get_bridge_list( edge_bridge_list );
+
+    //get start/end points of the edge
+    CubitVector edge_start_point = merged_edge->start_vertex()->coordinates();
+    CubitVector edge_end_point = merged_edge->end_vertex()->coordinates();
+
+    //get start/end point of the curve
+    edge_bridge_list.reset();
+    Curve *curve_ptr = CAST_TO( edge_bridge_list.get(), Curve);
+    DLIList<Point*> tmp_points;
+    curve_ptr->points( tmp_points );
+    CubitVector curve_start_point = tmp_points.get_and_step()->coordinates();
+    CubitVector curve_end_point = tmp_points.get_and_step()->coordinates();
+
+    //check to see if curve sense needs to be reversed
+    if( edge_start_point.distance_between( curve_start_point ) < GEOMETRY_RESABS &&
+          edge_end_point.distance_between( curve_end_point ) < GEOMETRY_RESABS )
+    {
+      //do nothing...everything is fine
+      continue;
+    }
+    else
+    {
+      if( edge_start_point.distance_between( curve_end_point ) < GEOMETRY_RESABS &&
+            edge_end_point.distance_between( curve_start_point ) < GEOMETRY_RESABS )
+      {
+        //switch sense of ref entity
+        merged_edge->reverse_tangent();
+      }
+    }
+  }
+}
+
+void GeometryModifyTool::get_merged_curve_and_surface_ids(
+                                          DLIList<Body*> &bodies,
+                                          DLIList<int> &merged_surface_ids,
+                                          DLIList<int> &merged_curve_ids ) const
+{
+  int i;
+  for( i=bodies.size(); i--; )
+  {
+    DLIList<RefEntity*> merged_children;
+
+    MergeTool::instance()->contains_merged_children( bodies.get_and_step(),
+                                                     merged_children );
+
+    int j;
+    for( j=merged_children.size(); j--; )
+    {
+      RefEntity *ref_ent = merged_children.get_and_step();
+
+      RefFace *ref_face = CAST_TO( ref_ent, RefFace );
+
+      if( ref_face )
+        merged_surface_ids.append( ref_face->id() );
+      else
+      {
+        RefEdge *ref_edge = CAST_TO( ref_ent, RefEdge );
+
+        if( ref_edge )
+          merged_curve_ids.append( ref_edge->id() );
+      }
+    }
+  }
+}
+
+void GeometryModifyTool::plane_preview(DLIList<Body*>& body_list,
+                                       const CubitVector &pt1,
+                                       const CubitVector &pt2,
+                                       const CubitVector &pt3)
+{
+  CubitPlane plane;
+  if( plane.mk_plane_with_points( pt1, pt2, pt3) == CUBIT_FAILURE)
+  {
+       PRINT_INFO( "Unable to create plane from given information.\n" );
+       return ;
+  }
+
+  CubitBox bounding_box;
+  Body* body_ptr = body_list.get_and_step();
+  bounding_box = body_ptr->bounding_box();
+
+  int i;
+  for( i=1; i<body_list.size(); i++ )
+  {
+     body_ptr = body_list.get_and_step();
+     bounding_box |= body_ptr->bounding_box();
+  }
+
+  int extension_type = 1;
+  double extension = 10; //10%
+  CubitVector p1, p2, p3, p4;
+
+  if( AnalyticGeometryTool::instance()->
+         min_pln_box_int_corners( plane, bounding_box, extension_type,
+         extension, p1, p2, p3, p4 ) == CUBIT_FAILURE )
+  {
+     PRINT_INFO( "Unable to create plane from given information.\n" );
+     return ;
+  }
+
+  GPoint gp[4];
+  gp[0].x=p1.x(); gp[0].y=p1.y(); gp[0].z=p1.z();
+  gp[1].x=p2.x(); gp[1].y=p2.y(); gp[1].z=p2.z();
+  gp[2].x=p3.x(); gp[2].y=p3.y(); gp[2].z=p3.z();
+  gp[3].x=p4.x(); gp[3].y=p4.y(); gp[3].z=p4.z();
+
+  // clear previous previews
+  GfxPreview::clear();
+
+  // Get the color to draw in
+  int color = CUBIT_BLUE;
+  GfxPreview::draw_quad(gp, color);
+  GfxPreview::flush();
+  return;
+}
+
+void GeometryModifyTool::march_path(CubitVector &start_pos,
+                                    RefFace *start_face,
+                                    CubitVector &march_dir,  // should be normalized
+                                    double &step_size)
+{
+  double cos_45 = 0.70710678118654752440084436210485;
+  double geo_tol = GeometryQueryTool::instance()->get_sme_resabs_tolerance();
+  CubitVector point_on_surf = start_pos;
+  RefVolume *v = start_face->ref_volume();
+  RefFace *cur_face = start_face;
+  CubitVector norm = cur_face->normal_at(point_on_surf, v); 
+  CubitVector sweep_dir = norm;
+
+  RefEdge *snap_edge = NULL;
+  bool snapped_to_edge_last_time = false;
+  bool turned = false;
+  CubitVector old_pos = point_on_surf;
+  while(!turned)
+  {
+    CubitVector new_pos;
+    if(snapped_to_edge_last_time)
+    {
+      // Just set the new position to the position on the
+      // edge.  This will force us to jump out without doing
+      // anything and then on the next loop we will start 
+      // onto the new face.
+      new_pos = old_pos;
+      snapped_to_edge_last_time = false;
+      continue;
+    }
+    else
+    {
+      // Calculate a new step along the vector.
+      new_pos = old_pos + step_size * march_dir;
+    }
+
+//GfxDebug::draw_point(new_pos, 5);
+//GfxDebug::flush();
+
+    cur_face->get_surface_ptr()->closest_point_trimmed(new_pos, point_on_surf);
+
+//GfxDebug::draw_point(point_on_surf, 6);
+//GfxDebug::flush();
+
+    norm = cur_face->normal_at(point_on_surf, v); 
+    if(sweep_dir % norm < cos_45)
+    {
+      turned = true;
+      /*
+GfxDebug::draw_point(old_pos, 3);
+GfxDebug::draw_point(point_on_surf, 3);
+GfxDebug::draw_line(old_pos, point_on_surf, 3);
+GfxDebug::flush();
+*/
+    }
+    else
+    {
+      bool snapping_to_edge = true;
+      CubitVector proj_dir = point_on_surf - new_pos;
+      double proj_dist = proj_dir.length();
+      if(proj_dist < geo_tol)
+        snapping_to_edge = false;
+      else
+      {
+        proj_dir /= proj_dist;
+        double dot = proj_dir % norm;
+        if(dot > .99 || dot < -.99)
+          snapping_to_edge = false;
+      }
+      if(!snapping_to_edge)
+      {
+        snap_edge = NULL;
+GfxDebug::draw_point(old_pos, 3);
+GfxDebug::draw_point(point_on_surf, 3);
+GfxDebug::draw_line(old_pos, point_on_surf, 3);
+GfxDebug::flush();
+        // didn't snap to boundary
+        old_pos = point_on_surf;
+      }
+      else
+      {
+        // probably snapped to the boundary
+        DLIList<RefEdge*> face_edges;
+        RefEdge *best_edge = NULL;
+        cur_face->ref_edges(face_edges);
+        int i;
+        DLIList<RefEdge*> possible_edges;
+        CubitVector closest;
+        for(i=face_edges.size(); i>0; i--)
+        {
+          RefEdge *e = face_edges.get_and_step();
+//GfxDebug::draw_ref_edge(e, 8);
+//GfxDebug::flush();
+          e->closest_point_trimmed(point_on_surf, closest);
+//GfxDebug::draw_point(point_on_surf, 66);
+//GfxDebug::draw_point(closest, 77);
+//GfxDebug::flush();
+          double cur_dist = (closest - point_on_surf).length();
+          if(cur_dist < geo_tol)
+          {
+            possible_edges.append(e);
+          }
+        }
+        if(possible_edges.size() == 1)
+          best_edge = possible_edges.get();
+        else if(possible_edges.size() > 1)
+        {
+          int h;
+          double smallest_dist = CUBIT_DBL_MAX;
+          for(h=possible_edges.size(); h>0; h--)
+          {
+            RefEdge *ce = possible_edges.get_and_step();
+            ce->closest_point_trimmed(old_pos, closest);
+            double cur_dist = (old_pos-closest).length();
+            if(cur_dist < smallest_dist)
+            {
+              smallest_dist = cur_dist;
+              best_edge = ce;
+            }
+          }
+        }
+        if(best_edge)
+        {
+          if(snap_edge && snap_edge == best_edge)
+          {
+GfxDebug::draw_point(old_pos, 3);
+GfxDebug::draw_point(point_on_surf, 3);
+GfxDebug::draw_line(old_pos, point_on_surf, 3);
+GfxDebug::flush();
+            old_pos = point_on_surf;
+            snapped_to_edge_last_time = true;
+          }
+          else
+          {
+            snap_edge = best_edge;
+            cur_face = best_edge->other_face(cur_face, v);
+            CubitVector old_pos_save = old_pos;
+            old_pos = closest;
+            i = 0;
+            snapped_to_edge_last_time = true;
+
+            GeometryModifyEngine *gme = get_engine((TopologyBridge*)best_edge->get_curve_ptr());
+            if(gme)
+            {
+              Point *pt1 = gme->make_Point(old_pos_save);
+              Point *pt2 = gme->make_Point(new_pos);
+              CubitVector const* pt3 = NULL;
+              Curve *crv = gme->make_Curve(STRAIGHT_CURVE_TYPE, pt1, pt2, pt3,CUBIT_FORWARD);
+              if(crv)
+              {
+                CubitVector pos1, pos2;
+                double dist;
+                GeometryQueryTool::instance()->entity_entity_distance(crv, best_edge->get_curve_ptr(), pos1,
+                  pos2, dist);
+                GfxDebug::draw_point(pos2, 9);
+                GfxDebug::flush();
+                old_pos = pos2;
+                delete crv;
+                delete pt1;
+                delete pt2;
+GfxDebug::draw_point(old_pos_save, 3);
+GfxDebug::draw_point(pos2, 3);
+GfxDebug::draw_line(old_pos_save, pos2, 3);
+GfxDebug::flush();
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+ // GfxDebug::draw_point(point_on_surf, 4);
+ // GfxDebug::flush();
+}
+
+CubitStatus GeometryModifyTool::stitch( DLIList<Body*> &bodies_to_stitch,
+                                        DLIList<Body*> &result_list,
+                                        bool tighten_gaps,
+                                        double tolerance )
+{
+  if (!okay_to_modify( bodies_to_stitch, "STITCH" ))
+    return CUBIT_FAILURE;
+
+  //get all the BodySMs from 'bodies_to_stitch'
+  int i;
+  for( i=bodies_to_stitch.size(); i--; )
+  {
+    Body *tmp_body = bodies_to_stitch.get_and_step();
+    if( !tmp_body->is_sheet_body() )
+    {
+      PRINT_ERROR("Can't stitch body %d.  It's a solid body\n", tmp_body->id() ); 
+      return CUBIT_FAILURE;
+    }
+  }
+  
+  DLIList<TopologyEntity*> entity_list(bodies_to_stitch.size());
+  DLIList<TopologyBridge*> bridge_list(bodies_to_stitch.size());
+  DLIList<BodySM*>         bodysm_list(bodies_to_stitch.size());
+  CAST_LIST_TO_PARENT(bodies_to_stitch, entity_list);
+  GeometryModifyEngine *gme = common_modify_engine(entity_list, bridge_list);
+  
+  if( entity_list.size() != bridge_list.size() )
+  {
+    PRINT_ERROR("Cannot stitch entities of different geometry engines.\n");
+    return CUBIT_FAILURE;
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state_with_cubit_file( bodies_to_stitch );
+
+  CAST_LIST(bridge_list, bodysm_list, BodySM);
+  DLIList<BodySM*> new_bodies;
+  CubitStatus result = gme->stitch( bodysm_list, new_bodies, tighten_gaps, tolerance );
+
+  if( result == CUBIT_FAILURE && CubitUndo::get_undo_enabled() )
+    CubitUndo::remove_last_undo();
+
+  if (!finish_sm_op(bodies_to_stitch, new_bodies, result_list))
+  {
+    result = CUBIT_FAILURE;
+    CubitUndo::remove_last_undo();
+  }
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( result == CUBIT_SUCCESS )
+      CubitUndo::note_result_bodies( result_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  return result;
+}
+
+
+
+CubitStatus GeometryModifyTool::discover_topology(RefFace *surf, CubitVector &pos,
+                                                  double &step_size,
+                                                  int num_subdivisions)
+{
+  CubitStatus ret = CUBIT_SUCCESS;
+
+  CubitVector point_on_surf;
+  surf->get_surface_ptr()->closest_point_trimmed(pos, point_on_surf);
+  RefVolume *v = surf->ref_volume();
+  CubitVector norm = surf->normal_at(point_on_surf, v); 
+  CubitVector march_dir = norm * CubitVector(1,0,0);
+  if(march_dir.length() < .001)
+  {
+    march_dir = norm * CubitVector(0,1,0);
+    if(march_dir.length() < .001)
+    {
+      march_dir = norm * CubitVector(0,0,1);
+      if(march_dir.length() < .001)
+      {
+        PRINT_ERROR("Couldn't find a good march direction.\n");
+        ret = CUBIT_FAILURE;
+      }
+    }
+  }
+
+  if(ret == CUBIT_SUCCESS)
+  {
+    // Get initial 4 directions.
+    march_dir.normalize();
+    DLIList<CubitVector> march_directions;
+    CubitVector v1 = march_dir;
+    CubitVector v3 = -march_dir;
+    CubitVector v2 = norm*march_dir;
+    CubitVector v4 = -v2;
+    march_directions.append(v1);
+    march_directions.append(v2);
+    march_directions.append(v3);
+    march_directions.append(v4);
+
+    // Now subdivide directions further if requested.
+    int i;
+    // make sure we start at the end to process the all of the original directions correctly
+    march_directions.last();  
+    for(i=march_directions.size(); i>0; i--)
+    {
+      CubitVector cur_dir = march_directions.get_and_step();
+      CubitVector next_dir = march_directions.get();
+      subdivide_pie(cur_dir, next_dir, num_subdivisions, march_directions);
+    }
+
+    for(i=march_directions.size(); i>0; i--)
+    {
+      CubitVector cur_dir = march_directions.get_and_step();
+      march_path(point_on_surf, surf, cur_dir, step_size);
+    }
+  }
+
+  return ret;
+}
+
+void GeometryModifyTool::subdivide_pie(CubitVector &dir1, CubitVector &dir2, int num_subdivisions,
+                                       DLIList<CubitVector> &all_directions)
+{
+  if(num_subdivisions > 0)
+  {
+    CubitVector mid = dir1 + dir2;
+    mid.normalize();
+    all_directions.append(mid);
+    if(num_subdivisions > 1)
+    {
+      subdivide_pie(dir1, mid, num_subdivisions-1, all_directions);
+      subdivide_pie(mid, dir2, num_subdivisions-1, all_directions);
+    }
+  }
+}
+
+//-------------------------------------------------------------------------
+// traverse the body object and calls premodify function on each structure
+//-------------------------------------------------------------------------
+void GeometryModifyTool::body_premodify(Body* body) const
+{
+	// skip if the mesh autodelete is disabled
+	if (!get_mesh_autodelete()) { return; }
+
+	// volumes
+	DLIList<RefVolume*> temp_vols;
+	body->ref_volumes(temp_vols);
+	for (int v = 0; v < temp_vols.size(); v++) {
+		RefVolume* volume = temp_vols.get_and_step();
+		volume->geometry_premodify();
+
+		// faces
+		DLIList<RefFace*> temp_faces;
+		volume->ref_faces(temp_faces);
+		for (int f = 0; f < temp_faces.size(); f++) {
+			RefFace* face_ptr = temp_faces.get_and_step();
+			face_ptr->geometry_premodify();
+
+			//edges
+			DLIList<RefEdge*> temp_edges;
+			face_ptr->ref_edges(temp_edges);
+			for (int e = 0; e < temp_edges.size(); e++) {
+				RefEdge* edge_ptr = temp_edges.get_and_step();
+				edge_ptr->geometry_premodify();
+
+				// vertices
+				DLIList<RefVertex*> temp_vertices;
+				edge_ptr->ref_vertices(temp_vertices);
+				for (int vertices = 0; vertices < temp_vertices.size(); vertices++) {
+					RefVertex* vertex_ptr = temp_vertices.get_and_step();
+					vertex_ptr->geometry_premodify();
+				}
+			}
+		}
+	}
+}

Modified: cgm/branches/cubit/geom/GeometryModifyTool.hpp
===================================================================
--- cgm/branches/cubit/geom/GeometryModifyTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryModifyTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -36,7 +36,6 @@
 class RefFace;
 class RefVolume;
 class RefVertex;
-class RefEdge;
 class RefFace;
 class RefVolume;
 template <class X> class DLIList;
@@ -60,12 +59,14 @@
 class GeometryEntity;
 
 
+//! Interface class for modifying geometry. 
 class CUBIT_GEOM_EXPORT GeometryModifyTool
 {
+
+  friend class MergeTool;
 public :
 
-  static GeometryModifyTool* instance( GeometryModifyEngine* GMEPtr = NULL);
-  /**<
+  /*!
     *  \return GeometryModifyTool* - Pointer to the singleton GeometryModifyTool object
     *  \arg SMEPtr
     *   Pointer to a SolidModelingEngine object. The default value
@@ -79,92 +80,102 @@
     *  Hence, this instance function should specifically be called at
     *  startup with a valid non-NULL input SMEPtr.
     */
+  static GeometryModifyTool* instance( GeometryModifyEngine* GMEPtr = NULL);
 
+  static void delete_instance();
+
+  //! \brief Destructor.
   ~GeometryModifyTool();
-  ///<  Destructor.
 
-  /**
-   <HR><H3>Geometric primitive creation functions</H3>
-  */
-  Body* sphere( double radius );
-  /**<  Creates an ACIS sphere and assigns it to a Body $
+  /*! Creates an ACIS sphere and assigns it to a Body $
     *  {radius} input radius
     *  Returns the new Body or NULL
     */
-
-  Body* brick( double wid, double dep, double hi );
-  /**<  Creates an ACIS cuboid and assigns it to a Body $
+  //! \brief Creates a sphere.
+  Body* sphere( double radius,
+                int x_shift = 0,
+                int y_shift = 0,
+                int z_shift = 0,
+                double inner_radius = 0,
+                bool delete_side = false );
+  
+  /*!  Creates an ACIS cuboid and assigns it to a Body $
     *  {wid, dep, hi} input width, depth, height
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a brick (cube).
+  Body* brick( double wid, double dep, double hi );
 
-  Body* brick( const CubitVector &center,
-               const CubitVector axes[3],
-               const CubitVector &extension );
-  /**<  Creates an ACIS cuboid and assigns it to a Body $
+  /*!  Creates an ACIS cuboid and assigns it to a Body $
     *  {center, axes, extension} input center, xyz axes, extension
     *     (extension vector is 1/2 width, height, depth)
     *  If one of dimensions is zero a planar sheet should be created.
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a brick (cube).
+  Body* brick( const CubitVector &center,
+               const CubitVector axes[3],
+               const CubitVector &extension );
 
-  Body* prism( double height, int sides, double major, double minor );
-  /**<  Creates an ACIS prism and assigns it to a Body $
+  /*!  Creates an ACIS prism and assigns it to a Body $
     *  {height, major, minor} input height, major and minor radii. $
     *  {sides} input number of sides. Must be >= 3.
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a brick (cube).
+  Body* prism( double height, int sides, double major, double minor );
 
-  Body* pyramid( double height, int sides, double major, double minor,
-                 double top=0.0 );
-  /**<  Creates an ACIS pyramid and assigns it to a Body $
+  /*!  Creates an ACIS pyramid and assigns it to a Body $
     *  {height, major, minor} input height, major and minor radii. $
     *  {sides} input number of sides. Must be >= 3.
     *  {top} radius at top of pyramid.
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a pyramid. 
+  Body* pyramid( double height, int sides, double major, double minor,
+                 double top=0.0 );
 
-  Body* cylinder( double hi, double r1, double r2, double r3 );
-  /**<  Creates an ACIS frustum and assigns it to a Body $
+  /*!  Creates an ACIS frustum and assigns it to a Body $
     *  {hi} input height $
     *  {r1} input radius in x-direction at base $
     *  {r2} input radius in y-direction at base $
     *  {r3} input radius in x-direction at top
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a clyinder. 
+  Body* cylinder( double hi, double r1, double r2, double r3 );
 
-  Body* torus( double r1, double r2 );
-  /**<  Creates an ACIS torus and assigns it to a Body $
+  /*!  Creates an ACIS torus and assigns it to a Body $
     *  {r1} input major_radius $
     *  {r2} input minor_radius
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a torus. 
+  Body* torus( double r1, double r2 );
 
+  /*! Creates a Body consisting of a planar sheet (no volume)
+    * p1 - 1st corner of the sheet
+    * p2 - 2nd corner of the sheet
+    * p3 - 3rd corner of the sheet
+    * p4 - 4th corner of the sheet
+    */
+  //! \brief Creates a planar surface from using four vertices.
   Body* planar_sheet( const CubitVector& p1,
                       const CubitVector& p2,
                       const CubitVector& p3,
                       const CubitVector& p4 );
-  /**< Creates a solid body consisting of a planar sheet (no volume)
-    * {p1} - 1st corner of the sheet
-    * {p2} - 2nd corner of the sheet
-    * {p3} - 3rd corner of the sheet
-    * {p4} - 4th corner of the sheet
-    */
 
-  Body* planar_sheet( const CubitVector &center,
-                      const CubitVector axes[2],
-                      double width, double height );
-  /**<  Creates an ACIS body consisting of a planar sheet (no volume)
+  /*!  Creates an body consisting of a planar sheet (no volume)
     *  {center, axes, width, height} - input location, orientation and
     *                                  size of sheet
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a surface from using four vertices.
+  Body* planar_sheet( const CubitVector &center,
+                      const CubitVector axes[2],
+                      double width, double height );
 
-  Body* planar_sheet( const CubitPlane& plane,
-                      const CubitBox& bounding_box,
-                      int extension_type = 0,
-                      double extension = 0.0 );
-  /**<  Creates an ACIS body consisting of a planar sheet (no volume)
+  /*!  Creates an ACIS body consisting of a planar sheet (no volume)
     *  {plane} - plane it will lie in
     *  {bounding_box} - 3D bounding box it must expand.  Plane will
     *                   have minimal area required to just cut the box.
@@ -172,13 +183,20 @@
     *  {extension} - distance sheet is to extend outside of bounding box
     *  Returns the new Body or NULL
     */
+  //! \brief Creates a surface from a plane and bounding box. 
+  Body* planar_sheet( const CubitPlane& plane,
+                      const CubitBox& bounding_box,
+                      int extension_type = 0,
+                      double extension = 0.0 );
 
-  /// <HR><H3>Geometry transformation (move, scale, etc.)</H3>
+  
+  //! \brief Scale a body non-uniformly. (x,y,z directions) 
+  CubitStatus scale ( Body *&entity, 
+                      const CubitVector& factors, 
+                      bool check_to_transform = true,
+                      bool preview = false);
 
-  CubitStatus scale ( Body *&entity, const CubitVector& factors, bool check_to_transform = true  );
-
-  Body* copy_body ( Body* body_ptr );
-  /**<  \return  Body*
+  /*!  \return  Body*
     *  \return - A pointer to a newly created body.
     *  \arg body_ptr
     *  A pointer to a Body which is to used to make copy.
@@ -188,15 +206,25 @@
     *  created Body are geometrically identical. If the copying
     *  operation fails for some reason, the function returns NULL.
     */
+  //! \brief Copy a Body.
+  Body* copy_body ( Body* body_ptr );
 
-  RefEntity* copy_refentity( RefEntity *old_entity );
-  /**<  Takes a RefEntity (RefVertex, RefEdge, or RefFace) and creates a
+  /*!  Takes a RefEntity (RefVertex, RefEdge, or RefFace) and creates a
     *  copy of it using the make_RefXxxxx commands.
     */
+  //! \brief Copy a RefEntity. 
+  RefEntity* copy_refentity( RefEntity *old_entity );
 
-  CubitStatus reverse( Body* body_ptr );
-  /* Turn body inside-out */
+  //! \brief Turn bodies inside-out 
+  CubitStatus reverse( DLIList<Body*> &body_list );
 
+  //! \brief Reverse the given faces using the solid modeller (flip normals) 
+  CubitStatus reverse( DLIList<RefFace*> &ref_face_list );
+
+  /*!  Aligns the body that contains my_face to match my_face
+    *  with the target face..
+    */
+  //! \brief Align the body, which contains my_face, with the target_face.
   CubitStatus align_body( Body *body_ptr,
                           RefFace *my_face,
                           RefFace *target_face,
@@ -204,9 +232,8 @@
                           CubitVector &axis,
                           CubitVector &target_center,
                           double &angle );
-  /**<  aligns the body that contains my_face to match my_face
-    *  with the target face..
-    */
+
+  //! \brief Aligns a surface or vertex of the body with a plane defined an axis defined by 2 points.
   CubitStatus align_body( Body *body_ptr,
                           DLIList<RefEntity*>& ref_ent_list,
                           CubitVector first_vector,
@@ -216,8 +243,14 @@
                           CubitVector &axis_of_rot,
                           double &angle,
                           double &angle_2 );
-  ///< <HR><H3>Geometry modification (booleans, decomposition, etc.)</H3>
 
+  
+  /*!  This function accepts two bodies in the first list.  The second body
+       in the list is subtracted from and the first and the result is put
+       into the outsideBodies list.  intersectBodies list is the result of 
+       intersecting the original two bodies in the first list. 
+  */ 
+  //! \brief Intersects and subtracts the two bodies in the list. 
   CubitStatus chop( DLIList<Body*> &bodies,
                     DLIList<Body*> &intersectBodies,
                     DLIList<Body*> &outsideBodies,
@@ -225,38 +258,60 @@
                     bool keep_old = false,
                     bool nonreg = false );
 
+  //! \brief Thickens a sheet body (surface) into a solid body.  Can do both directions. 
   CubitStatus thicken( DLIList<Body*>& bodies,
                        DLIList<Body*>& new_bodies,
                        double depth,
                        bool both = false );
-
+  //! \brief Boolean unite.
   CubitStatus unite( DLIList<Body*> &bodies,
                      DLIList<Body*> &newBodies,
                      bool keep_old = false );
 
+  //! \brief Boolean unite.
   CubitStatus unite( DLIList<BodySM*> &body_sm_list,
                      DLIList<BodySM*> &new_body_sm_list,
-                     bool keep_old = false );
+                     bool keep_old = false);
 
-  CubitStatus subtract( DLIList<Body*> &tool_body_list, DLIList<Body*> &from_bodies,
+  //! \brief Boolean subtract.   
+  CubitStatus subtract( DLIList<Body*> &tool_body_list, 
+                        DLIList<Body*> &from_bodies,
                         DLIList<Body*> &new_bodies,
                         bool imprint = false,
                         bool keep_old = false );
 
-  CubitStatus subtract( Body* tool_body, DLIList<Body*> &from_bodies,
+  //! \brief Boolean subtract.  Subtracts the tool from all the blanks.
+  CubitStatus subtract( Body* tool_body, 
+                        DLIList<Body*> &from_bodies,
                         DLIList<Body*> &new_bodies,
                         bool imprint = false,
                         bool keep_old = false );
 
-
+  /*! \brief Checks for consistent normals across body. Uses surf_ref
+    as a reference surface.  All other surfaces in volume should have 
+    normal point in likewise direction (in or out of volume).
+    */
+  //! \brief Checks for consistent normals across body.  
   CubitStatus validate_normals( DLIList<Body*>& bodies,
                                 RefFace *surf_ref,
                                 bool reverse );
+  
+  //! \brief Boolean intersect.
+  CubitStatus intersect( Body *tool_body_ptr, 
+                         DLIList<Body*> &from_bodies,
+                         DLIList<Body*> &new_bodies,
+                         bool keep_old = false );
 
-  CubitStatus intersect( Body *tool_body_ptr, DLIList<Body*> &from_bodies,
+  //! \brief Boolean intersect.
+  CubitStatus intersect( DLIList<Body*> &from_bodies,
                          DLIList<Body*> &new_bodies,
                          bool keep_old = false );
 
+  /*!  Cuts the given bodies with the points defining a plane.
+    *  This is mainly used for vis purposes to section a body with
+    *  a plane and only retain half of it.
+    */
+  //! \brief Cuts body with plane, throwing away one side.
   CubitStatus section( DLIList<Body*> &section_body_list,
                        const CubitVector &point_1,
                        const CubitVector &point_2,
@@ -264,42 +319,102 @@
                        DLIList<Body*> &new_body_list,
                        CubitBoolean keep_normal_side,
                        CubitBoolean keep_old = CUBIT_FALSE );
-  /**<  Cuts the given bodies with the points defining a plane.
-    *  This is mainly used for vis purposes to section a body with
-    *  a plane and only retain half of it.
-    */
 
+  //! \brief Splits periodic curves and surfaces.
   CubitStatus split_periodic( Body *body_ptr,
                               Body *&new_body_ptr );
-  /**<  calls solid modeling engine to split the periodic body.
-    */
+  
+  //! \brief Stitches sheet bodies at common edges to form larger sheet body or solid. 
+  CubitStatus stitch( DLIList<Body*> &bodies_to_stitch,
+                      DLIList<Body*> &result_list,
+                      bool tighten_gaps,
+                      double tolerance = -1.0 );
 
-  CubitStatus split_surface( RefFace *ref_face_ptr,
-                             DLIList<CubitVector*> &locations,
-                             DLIList<DLIList<CubitVector*>*> &vec_lists,
-                             CubitBoolean preview_flg = CUBIT_FALSE,
-                             CubitBoolean create_ref_edges_flg = CUBIT_FALSE );
-  /**< Split function for simple surface splitting.  Temporary Curves are
+  //! \brief Beta function.
+  CubitStatus discover_topology(RefFace *ref_face_ptr,
+                                CubitVector &pos,
+                                double &step_size,
+                                int num_subdivisions);
+
+  //! \brief Beta function.
+  void march_path(CubitVector &start_pos,
+                  RefFace *start_face,
+                  CubitVector &march_dir,
+                  double &step_size);
+
+  //! \brief Beta function.
+  void subdivide_pie(CubitVector &dir1, CubitVector &dir2, int num_subdivisions,
+                                       DLIList<CubitVector> &all_directions);
+  
+  /*! Split function for simple surface splitting.  Temporary Curves are
     * created on the RefFace and used to split the RefFace.  The curves are
     * created from the input vec_lists (straight lines, arcs or splines).
     * The input locations are the original input locations from the user,
     * which are displayed for user reference.  If the preview_flg is CUBIT_TRUE,
     * the curves are displayed but no splitting occurs.  If the preview_flg is
     * CUBIT_TRUE and the create_ref_edges_flg is CUBIT_TRUE, then RefEdges are
-    * created (but no splitting occurs).
+    * created (but no splitting occurs).  The clear_previous_previews flag
+    * controls whether previous previews are cleared from the graphics window
+    * (only applicable if preview_flg is CUBIT_TRUE).
     */
+  //! \brief Splits a surface with a curve defined by positions.
+  CubitStatus split_surface( RefFace *ref_face_ptr,
+                             DLIList<CubitVector*> &locations,
+                             DLIList<DLIList<CubitVector*>*> &vec_lists,
+                             CubitBoolean preview_flg = CUBIT_FALSE,
+                             CubitBoolean create_ref_edges_flg = CUBIT_FALSE,
+                             CubitBoolean clear_previous_previews = CUBIT_TRUE );
 
-  CubitStatus split_surfaces( DLIList<RefFace*> &ref_face_list,
-                              int num_segs,
-                              double fraction,
-                              double distance,
-                              RefEdge *from_curve_ptr,
-                              DLIList<RefVertex*> &corner_vertex_list,
-                              DLIList<RefVertex*> &through_vertex_list,
-                              RefEdge *curve_dir_ptr = NULL,
-                              CubitBoolean preview_flg = CUBIT_FALSE,
-                              CubitBoolean create_ref_edges_flg = CUBIT_FALSE );
-  /**<  Splits a surface or connected set of surfaces in one direction.
+
+  /*! Same behavior as other split_surface function only it handles multiple surface
+      and multiple lists of curves.
+    */
+  //! \brief Splits MULTIPLE surfaces with a curves defined by positions.
+  CubitStatus split_surface( DLIList<RefFace*> &ref_face_list,
+                             DLIList<CubitVector*> &locations,
+                             DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
+                             CubitBoolean preview_flg = CUBIT_FALSE,
+                             CubitBoolean create_ref_edges_flg = CUBIT_FALSE,
+                             CubitBoolean clear_previous_previews = CUBIT_TRUE );
+
+  /*!  Splits surfaces by extending curves at the end of hardlines across the
+    *   surface.  Only works on planar surfaces and by extending linear curves.
+    *   If specified vertex list is provided, only try to extend curves
+    *   attached to those vertices, and error out if unable to perform the
+    *   operation using any vertex.  If no vertex list is provided, find
+    *   appropriate vertices automatically, and limit the split to gaps less
+    *   than or equal to the specified "split surface extend gap threshold".
+    *   {ref_face_list} - list of connected surfaces to split
+    *   {ref_vertex_list} - (OPTIONAL) - vertices to extend from. Function will
+    *                       error out if unable to extend from any vertex. If
+    *                       not supplied, function will automatically find
+    *                       valid vertices to extend from on the surfaces (AUTO
+    *                       mode), and will limit the split to gaps less than
+    *                       or equal to the specified extend gap threshold (see
+    *                       setting below).
+    *   {preview_flg} - routine only displays graphics preview of splits
+    *   {create_ref_edges_flg} - valid only if preview_flg=CUBIT_TRUE.  If
+    *                            CUBIT_TRUE, create RefEdges *instead* of
+    *                            splitting.
+    * Note: this function uses SplitSurfaceTool.  Three other settings can be
+    *       specified that control this function.  They are (static):
+    *         SplitSurfaceTool::set_extend_gap_threshold - for AUTO mode,
+    *          only split the surface if distance is less than or equal to
+    *          this value.
+    *         SplitSurfaceTool::set_extend_tolerance - snaps to vertices along
+    *           curves within this tolerance so as to avoid creating short
+    *           curves when splitting surfaces.
+    *         SplitSurfaceTool:set_extend_normal - if TRUE, if a projection
+    *          normal to the curve is less distance than a projection in the
+    *          direction of the curve, use the normal projection instead.
+    */
+  //! \brief  Splits surfaces by extending curves at the end of hardlines across the surface.
+  CubitStatus split_surfaces_extend( DLIList<RefFace*> &ref_face_list,
+                                     DLIList<RefVertex*> &ref_vertex_list,
+                                     CubitBoolean preview_flg = CUBIT_FALSE,
+                                     CubitBoolean create_ref_edges_flg = CUBIT_FALSE );
+
+  /*!  Splits a surface or connected set of surfaces in one direction.
     *   Particularly useful for splitting fillets to prepare the model
     *   for sweeping.
     *   {ref_face_list} - list of connected surfaces to split
@@ -354,24 +469,26 @@
     *           below this becomes the triangle point (if sideAngleThreshold
     *           criteria is also met)
     */
+  //! \brief Splits a surface or connected set of surfaces in one direction.
+  CubitStatus split_surfaces( DLIList<RefFace*> &ref_face_list,
+                              int num_segs,
+                              double fraction,
+                              double distance,
+                              RefEdge *from_curve_ptr,
+                              DLIList<RefVertex*> &corner_vertex_list,
+                              DLIList<RefVertex*> &through_vertex_list,
+                              RefEdge *curve_dir_ptr = NULL,
+                              CubitBoolean preview_flg = CUBIT_FALSE,
+                              CubitBoolean create_ref_edges_flg = CUBIT_FALSE );
 
-  CubitStatus split_surfaces_offset(
-      DLIList<RefFace*> &ref_face_list,
-      DLIList<RefEdge*> &edge_list,
-      int num_segs,
-      double distance,
-      CubitBoolean partition_flg = CUBIT_FALSE,
-      CubitBoolean blunt_flg = CUBIT_FALSE,
-      CubitBoolean preview_flg = CUBIT_FALSE,
-      CubitBoolean create_ref_edges_flg = CUBIT_FALSE);
-  /**< Splits a surface a specified distance from a curve.
+  /*! Splits surfaces a specified distance from curves.
   *   {ref_face_list} - list of surfaces to split
   *   {edge_list} - list of curves to offset from
   *   {num_segs} - number of segments to create (i.e, 2 segments
   *                means to split using two offset curves).
   *   {distance} - distance to offset
   *   {partition_flg} - (OPTIONAL) creates partitions of the offset curves. This typically provides
-  *                         \surfaces easily map meshed
+  *                         surfaces easily map meshed
   *   {blunt_flg} - (OPTIONAL) if true the endings of the input curve graph are right angles
   *                     instead of arcs
   *   {preview_flg} - (OPTIONAL) user specifies forced vertices for
@@ -380,40 +497,73 @@
   *   {create_ref_edges_flg} - (OPTIONAL) Create curves instead of splitting surfaces
   *                                 Requires the preview flag
   */
+  //! \brief Splits surfaces a specified distance from curves.
+  CubitStatus split_surfaces_offset(
+      DLIList<RefFace*> &ref_face_list,
+      DLIList<RefEdge*> &edge_list,
+      int num_segs,
+      double distance,
+      CubitBoolean partition_flg = CUBIT_FALSE,
+      CubitBoolean blunt_flg = CUBIT_FALSE,
+      CubitBoolean preview_flg = CUBIT_FALSE,
+      CubitBoolean create_ref_edges_flg = CUBIT_FALSE);
 
-  CubitStatus webcut_with_cylinder( DLIList<Body*>& webcut_body_list,
-      double radius,
-      const CubitVector &axis,
-      const CubitVector& center,
-                                    DLIList<Body*> &results_list,
-                                    CubitBoolean imprint = CUBIT_FALSE,
-                                    CubitBoolean merge = CUBIT_FALSE );
-  /**<  Webcuts the bodies in the list with a cutting cylinder.
+  /*! Automatically create a midsurface from a volume.
+  *   {body_list_in} - list of bodies to midsurface
+  *   {body_list_out} - resulting midsurfaces
+  *   {lower_tol} - lower tolerance for finding surface pairs
+  *   {upper_tol} - upper tolerance for finding surface pairs
+  *   {preview} - preview midsurfaces
+  */
+  //! \brief Create a midsurface from a volume.
+  CubitStatus auto_mid_surface(
+	  DLIList<Body*> &body_list_in,
+	  DLIList<Body*> &body_list_out,
+      DLIList<Body*> &old_bodies_midsurfaced,
+      DLIList<double> &thickness_list,
+      double lower_tol,
+      double upper_tol,
+      CubitBoolean delete_midsurfaced,
+      CubitBoolean preview);
+	/** Automatically create a midsurface from a volume.
+	*   {body_list_in} - list of bodies to midsurface
+	*   {body_list_out} - resulting midsurfaces
+    *   {thickness_list} - list of matching thickness values for the body out list
+	*   {lower_tol} - lower tolerance for finding surface pairs
+	*   {upper_tol} - upper tolerance for finding surface pairs
+	*   {preview} - preview midsurfaces
+	*/
+
+  /*!  Webcuts the bodies in the list with a cutting cylinder.
     *  The cylinder is created by the given parameters.  This
     *  is done in the solid modeling engine to reduce the impact
     *  on body ids.
     */
+  //! \brief Webcuts bodies with a cylinder.
+  CubitStatus webcut_with_cylinder( DLIList<Body*>& webcut_body_list,
+                                    double radius,
+                                    const CubitVector &axis,
+                                    const CubitVector& center,
+                                    DLIList<Body*> &results_list,
+                                    DLIList<Body*> &neighboring_bodies,
+                                    ImprintType imprint_type = NO_IMPRINT,
+                                    CubitBoolean merge = CUBIT_FALSE ,
+                                    CubitBoolean preview = CUBIT_FALSE);
 
 #ifdef CAT
   CubitStatus webcut_across_translate( DLIList<Body*>& body_list,
                                        RefFace* plane_surf1,
                                        RefFace* plane_surf2,
                                        DLIList<Body*>& results_list,
-                                       CubitBoolean imprint = CUBIT_FALSE,
-                                       CubitBoolean merge = CUBIT_FALSE);
+                                       ImprintType imprint_type = NO_IMPRINT,
+                                       CubitBoolean merge = CUBIT_FALSE,
+                                       CubitBoolean preview = CUBIT_FALSE);
   /**<  Webcuts with a flat plate to make a body suitable for single-single
     *   sweeping.  Only experimental at this point.
     */
 #endif
 
-  CubitStatus webcut_with_brick( DLIList<Body*>& webcut_body_list,
-                                 const CubitVector &center,
-                                 const CubitVector axes[3],
-                                 const CubitVector &extension,
-                                 DLIList<Body*> &results_list,
-                                 CubitBoolean imprint = CUBIT_FALSE,
-                                 CubitBoolean merge = CUBIT_FALSE );
-  /**<  Webcuts the bodies in the list with a cutting brick.
+  /*!  Webcuts the bodies in the list with a cutting brick.
     *  The brick is created by the given parameters - center of
     *  brick, xyz axes, and extension.  Extension is 1/2 width,
     *  height and depth. If one of the brick dimensions is zero
@@ -421,29 +571,37 @@
     *  planar_sheet is called).  Brick creation is done in the
     *  solid modeling engine to reduce the impact on body ids.
     */
+  //! \brief Webcuts bodies with a brick (cube).
+  CubitStatus webcut_with_brick( DLIList<Body*>& webcut_body_list,
+                                 const CubitVector &center,
+                                 const CubitVector axes[3],
+                                 const CubitVector &extension,
+                                 DLIList<Body*> &results_list,
+                                 DLIList<Body*> &neighbor_list,
+                                 ImprintType imprint_type = NO_IMPRINT,
+                                 CubitBoolean merge = CUBIT_FALSE,
+                                 CubitBoolean preview = CUBIT_FALSE);
 
+
+  /*!  Webcuts the bodies in the list with a cutting planar sheet.
+    *  The sheet is created by the given parameters - center of
+    *  sheet, xy axes, and width and height. Sheet creation is done
+    *  in the solid modeling engine to reduce the impact on body ids.
+    */
+  //! \brief Webcuts bodies with a planar sheet.
   CubitStatus webcut_with_planar_sheet( DLIList<Body*>& webcut_body_list,
                                         const CubitVector &center,
                                         const CubitVector axes[2],
                                         double width,
                                         double height,
                                         DLIList<Body*> &results_list,
-                                        CubitBoolean imprint = CUBIT_FALSE,
-                                        CubitBoolean merge = CUBIT_FALSE );
-  /**<  Webcuts the bodies in the list with a cutting planar sheet.
-    *  The sheet is created by the given parameters - center of
-    *  sheet, xy axes, and width and height. Sheet creation is done
-    *  in the solid modeling engine to reduce the impact on body ids.
-    */
+                                        DLIList<Body*> &neighbor_list,
+                                        ImprintType imprint_type = NO_IMPRINT,
+                                        CubitBoolean merge = CUBIT_FALSE,
+                                        CubitBoolean preview = CUBIT_FALSE);
 
-  CubitStatus webcut_with_plane( DLIList<Body*>& webcut_body_list,
-                                 const CubitVector &vector1,
-                                 const CubitVector &vector2,
-                                 const CubitVector &vector3,
-                                 DLIList<Body*> &results_list,
-                                 CubitBoolean imprint = CUBIT_FALSE,
-                                 CubitBoolean merge = CUBIT_FALSE ) ;
-  /**<  \return  int
+
+  /*!  \return  int
     *  \return - Number of bodies that were webcut ( >= 0 )
     *  \arg webcut_body_list
     *  The list of bodies to be webcut
@@ -460,13 +618,18 @@
     *  The newly created bodies are merged and imprinted depeding on
     *  the respective flags.
     */
+  //! \brief Webcuts bodies with a plane.
+  CubitStatus webcut_with_plane( DLIList<Body*>& webcut_body_list,
+                                 const CubitVector &vector1,
+                                 const CubitVector &vector2,
+                                 const CubitVector &vector3,
+                                 DLIList<Body*> &results_list,
+                                 DLIList<Body*> &neighbor_list,
+                                 ImprintType imprint_type = NO_IMPRINT,
+                                 CubitBoolean merge = CUBIT_FALSE,
+                                 CubitBoolean preview = CUBIT_FALSE) ;
 
-  CubitStatus webcut_with_surface( DLIList<Body*>& webcut_body_list,
-                                   RefFace* refFace,
-                                   DLIList<Body*>& results_list,
-                                   CubitBoolean imprint = CUBIT_FALSE,
-                                   CubitBoolean merge = CUBIT_FALSE );
-  /**<  \return  int
+  /*!  \return  int
     *  \return - Number of bodies that were webcut ( >= 0 )
     *  \arg webcut_body_list
     *  The list of bodies to be webcut
@@ -485,12 +648,16 @@
     *  merged and imprinted depeding on the respective flags.
     *  It returns the number of bodies that were webcut.
     */
+  //! \brief Webcuts bodies with a surface -- must be planar.
+  CubitStatus webcut_with_surface( DLIList<Body*>& webcut_body_list,
+                                   RefFace* refFace,
+                                   DLIList<Body*>& results_list,
+                                   DLIList<Body*> &neighbor_list,
+                                   ImprintType imprint_type = NO_IMPRINT,
+                                   CubitBoolean merge = CUBIT_FALSE,
+                                   CubitBoolean preview = CUBIT_FALSE);
 
-  CubitStatus webcut_with_curve_loop( DLIList<Body*>& webcut_body_list,
-                              DLIList<RefEdge*>& refedge_list,
-                              DLIList<Body*>& results_list,
-                              CubitBoolean imprint = CUBIT_FALSE );
-   /**<  \return  int
+   /*!  \return  int
     *  \return - Number of bodies that were webcut ( >= 0 )
     *  \arg webcut_body_list
     *  The list of bodies to be webcut
@@ -509,23 +676,30 @@
     *  are merged and imprinted depending on the respective flags.
     *  It returns the number of bodies that were webcut.
     */
+  //! \brief Webcuts bodies with a surface defined by a curve loop.
+  CubitStatus webcut_with_curve_loop( DLIList<Body*>& webcut_body_list,
+                              DLIList<RefEdge*>& refedge_list,
+                              DLIList<Body*>& results_list,
+                              DLIList<Body*> &neighbor_list,
+                              ImprintType imprint_type = NO_IMPRINT,
+                              CubitBoolean merge = CUBIT_FALSE,
+                              CubitBoolean preview = CUBIT_FALSE);
 
-  CubitStatus webcut_with_sheet( DLIList<Body*>& webcut_body_list,
-                                 Body *sheet_body,
-                                 DLIList<Body*> &new_bodies,
-                                 CubitBoolean imprint = CUBIT_FALSE);
-  /**<  calls geometric modeling engine to webcut the body using
+  /*!  Webcut the bodies using
     *  the surface as the cutting tool.
     *  This is the real webcut with surface.  The others are
     *  just for planes...  The sheet body is a body with 0 volume.
     */
+  //! \brief Webcut bodies using a surface, need to be planar. 
+  CubitStatus webcut_with_sheet( DLIList<Body*>& webcut_body_list,
+                                 Body *sheet_body,
+                                 DLIList<Body*> &new_bodies,
+                                 DLIList<Body*> &neighbor_list,
+                                 ImprintType imprint_type = NO_IMPRINT,
+                                 CubitBoolean merge = CUBIT_FALSE,
+                                 CubitBoolean preview = CUBIT_FALSE);
 
-  CubitStatus webcut_with_body( DLIList<Body*>& webcut_body_list,
-		                    Body* body,
-		                    DLIList<Body*>& results_list,
-		                    CubitBoolean imprint = CUBIT_FALSE,
-		                    CubitBoolean merge = CUBIT_FALSE );
-  /**<  \return  int
+  /*!  \return  int
     *  \return - Number of bodies that were webcut ( >= 0 )
     *  \arg webcut_body_list
     *  The list of bodies to be webcut
@@ -542,17 +716,29 @@
     *  The newly created bodies are merged and imprinted depeding on
     *  the respective flags.
     */
+  //! \brief Webcuts bodies with a tool body.
+  CubitStatus webcut_with_body( DLIList<Body*>& webcut_body_list,
+		                Body* body,
+		                DLIList<Body*>& results_list,
+                                DLIList<Body*> &neighbor_list,
+                                ImprintType imprint_type = NO_IMPRINT,
+		                CubitBoolean merge = CUBIT_FALSE,
+                                CubitBoolean preview = CUBIT_FALSE);
 
-  CubitStatus webcut_with_extended_surf( DLIList<Body*> &webcut_body_list,
-                                         RefFace *face_to_extend,
-                                         DLIList<Body*> &new_bodies,
-                                         int &num_cut,
-                                         CubitBoolean imprint = CUBIT_FALSE);
-  /**<  calls geometric modeling engine to create a face extended
-    *  from the given refFace and then webcut the body using the
-    *  sheet generated.
+  /*!  Create a sheet extended from the tool surfaces
+    *  and then uses it to webcut the bodies.
     */
-
+  //! \brief Webcuts bodies by with an extended surface(s). 
+  CubitStatus webcut_with_extended_sheet( DLIList<Body*> &webcut_body_list,
+                                          DLIList<RefFace*> &ref_face_list,
+                                          DLIList<Body*> &new_bodies,
+                                          DLIList<Body*> &neighbor_list,
+                                          int &num_cut,
+                                          ImprintType imprint_type = NO_IMPRINT,
+                                          CubitBoolean merge = CUBIT_FALSE,
+                                          CubitBoolean preview = CUBIT_FALSE);
+  
+  //! \brief Webcuts bodies with a tool solid created by rotating surfaces about an axis.
   CubitStatus webcut_with_sweep_surfaces_rotated(
                             DLIList<Body*> &webcut_body_list,
                             DLIList<RefFace*> &tool_faces,
@@ -562,9 +748,12 @@
                             RefFace* stop_surf,
                             bool up_to_next,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint = false,
-                            CubitBoolean merge = false );
+                            DLIList<Body*> &neighbor_list,
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean merge = false,
+                            CubitBoolean preview = false);
 
+  //! \brief Webcuts bodies with a tool surface created by rotating curves about an axis.
   CubitStatus webcut_with_sweep_curves_rotated(
                             DLIList<Body*> &webcut_body_list,
                             DLIList<RefEdge*> &tool_curves,
@@ -573,9 +762,12 @@
                             double angle,
                             RefFace* stop_surf,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint = false,
-                            CubitBoolean merge = false );
+                            DLIList<Body*> &neighbor_list,
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean merge = false,
+                            CubitBoolean preview = false);
 
+  //! \brief Webcuts bodies with a tool solid created by sweeping surfaces along a vector.
   CubitStatus webcut_with_sweep_surfaces(
                             DLIList<Body*> &webcut_body_list,
                             DLIList<RefFace*> &tool_faces,
@@ -587,9 +779,12 @@
                             RefFace *stop_surf,
                             RefEdge* edge_to_sweep_along,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint = false,
-                            CubitBoolean merge = false );
+                            DLIList<Body*> &neighbor_list,
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean merge = false,
+                            CubitBoolean preview = false);
 
+  //! \brief Webcuts bodies with a tool surface created by sweeping curves along a vector.
   CubitStatus webcut_with_sweep_curves(
                             DLIList<Body*> &webcut_body_list,
                             DLIList<RefEdge*> &tool_curves,
@@ -598,49 +793,57 @@
                             RefFace *stop_surf,
                             RefEdge* edge_to_sweep_along,
                             DLIList<Body*> &new_bodies,
-                            CubitBoolean imprint = false,
-                            CubitBoolean merge = false );
+                            DLIList<Body*> &neighbor_list,
+                            ImprintType imprint_type = NO_IMPRINT,
+                            CubitBoolean merge = false,
+                            CubitBoolean preview = false);
+  
+  //! \brief Removes small topology; i.e, curves and surfaces.
+  CubitStatus remove_topology( DLIList<RefEdge*> &ref_edge_list,
+        DLIList<RefFace*> &ref_face_list, double backoff_distance,
+        double small_curve_size, DLIList<Body*> &new_body_list,
+        CubitBoolean propagate,
+        CubitBoolean preview);
 
+  /*!  Creates curves offset from a chain of curves.  The offset direction is
+    *  only used if there is one linear curve.  Otherwise, the offset direction
+    *  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.
+    */
+  //! \brief Creates curves offset from a chain of curves.  The offset direction is
   CubitStatus offset_curves( DLIList<RefEdge*>& ref_edge_list,
                              double offset_distance,
                              const CubitVector& offset_direction,
                              int gap_type = 1 );
-  /**<  Creates curves offset from a chain of curves.  The offset direction is
-    *  only used if there is one linear curve.  Otherwise, the offset direction
-    *  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 trim_curve( RefEdge* trim_curve,
-                          const CubitVector& trim_vector,
-                          const CubitVector& keep_vector );
-  /**<  Trims or extends a curve, up to the trim_vector.  If trimming, the
+  /*!  Trims or extends a curve, up to the trim_vector.  If trimming, the
     *  keep_vector determines which side of the curve to keep.  If the curve
     *  is not free, the curve is automatically copied before trimming (so
     *  a new curve results).
     */
+  //! \brief Trims or extends a curve, up to the trim_vector.  If trimming, the
+  CubitStatus trim_curve( RefEdge* trim_curve,
+                          const CubitVector& trim_vector,
+                          const CubitVector& keep_vector );
 
-  ///< <HR><H3>Topology modification (imprint, regularize, etc.)</H3>
-
+  //! \brief Imprints a group of bodies with one another.
   CubitStatus imprint( DLIList<Body*> &from_body_list,
                        DLIList<Body*> &new_body_list,
                        CubitBoolean keep_old = CUBIT_FALSE );
+
+  /*!  Imprints a list of Bodies with a list of RefEdges.  Useful for
+    *  splitting surfaces.  If edge pierces a surface a hardpoint will
+    *  result at the pierce location.  Interface is free of ACIS but
+    *  currently only works if all entities are ACIS entities.
+    */
+  //! \brief Imprints a list of Bodies with a list of RefEdges.  Useful for
   CubitStatus imprint( DLIList<Body*> &body_list,
                        DLIList<RefEdge*> &ref_edge_list,
                        DLIList<Body*>& new_body_list,
                        CubitBoolean keep_old_body = CUBIT_FALSE,
                        CubitBoolean show_messages = CUBIT_TRUE );
-  /**<  Imprints a list of Bodies with a list of RefEdges.  Useful for
-    *  splitting surfaces.  If edge pierces a surface a hardpoint will
-    *  result at the pierce location.  Interface is free of ACIS but
-    *  currently only works if all entities are ACIS entities.
-    */
 
-  CubitStatus imprint( DLIList<RefFace*> &ref_face_list,
-                       DLIList<RefEdge*> &ref_edge_list,
-                       DLIList<Body*>& new_body_list,
-                       CubitBoolean keep_old_body = CUBIT_FALSE );
-  /**<  Imprints a list of RefFaces with a list of RefEdges.  This is
+  /*!  Imprints a list of RefFaces with a list of RefEdges.  This is
     *  useful if the user has a curve which spans several surfaces on
     *  a body and only wants to imprint to selected surfaces.  Algorithm
     *  does not support imprinting to free surfaces.  This method
@@ -648,11 +851,12 @@
     *  body. Interface is free of ACIS but currently only works if all
     *  entities are ACIS entities.
     */
+  //! Imprints a list of RefFaces with a list of RefEdges.  This is
+  CubitStatus imprint( DLIList<RefFace*> &ref_face_list,
+                       DLIList<RefEdge*> &ref_edge_list,
+                       DLIList<Body*>& new_body_list,
+                       CubitBoolean keep_old_body = CUBIT_FALSE );
 
-  CubitStatus imprint( DLIList<Surface*> &surface_list,
-                       DLIList<DLIList<Curve*>*> &curve_lists_list,
-                       Body*& new_body,
-                       CubitBoolean keep_old_body = CUBIT_FALSE );
   /**<  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
@@ -660,15 +864,23 @@
     *  Also, the Curves need not be RefEntities.
     *  All input surfaces must be from the same body however.
     */
+  //! \brief Imprints a list of Surfaces with list of Curves, sorted per
+  CubitStatus imprint( DLIList<Surface*> &surface_list,
+                       DLIList<DLIList<Curve*>*> &curve_lists_list,
+                       Body*& new_body,
+                       CubitBoolean keep_old_body = CUBIT_FALSE,
+                       CubitBoolean expand = CUBIT_TRUE);
 
+  /*!  Imprints a list of bodies to a list of locations.  Useful for
+    *  splitting curves and creating hardpoints on surfaces.  Interface
+    *  is free of ACIS but currently only works if bodies are ACIS bodies.
+    */
+  //! \brief Imprints a list of bodies to a list of locations.  
   CubitStatus imprint( DLIList<Body*> &body_list,
                        DLIList<CubitVector*> &vector_list,
                        DLIList<Body*>& new_body_list,
-                       CubitBoolean keep_old_body = CUBIT_FALSE );
-  /**<  Imprints a list of bodies to a list of locations.  Useful for
-    *  splitting curves and creating hardpoints on surfaces.  Interface
-    *  is free of ACIS but currently only works if bodies are ACIS bodies.
-    */
+                       CubitBoolean keep_old_body = CUBIT_FALSE,
+                       CubitBoolean merge = CUBIT_FALSE );
 
   //HEADER- Sweep-related functions. All of these are implemented
   //HEADER- only for RefEntities whose underlying geometry is
@@ -676,91 +888,153 @@
   //HEADER- itself is free of ACIS.
 
 
+   //! \brief Imprints a list of RefFaces with a list of projected RefEdges.
    CubitStatus imprint_projected_edges( DLIList<RefFace*> &ref_face_list,
                                         DLIList<RefEdge*> &ref_edge_list,
                                         DLIList<Body*>& new_body_list,
                                         CubitBoolean keep_old_body,
                                         CubitBoolean keep_free_edges );
-   //- Imprints a list of RefFaces with a list of projected RefEdges.
 
+   //! \brief Imprints a list of Bodies with a list of RefEdges which are projected
+   //! to a list of RefFaces
    CubitStatus imprint_projected_edges( DLIList<RefFace*> &ref_face_list,
                                         DLIList<Body*> &body_list,
                                         DLIList<RefEdge*> &ref_edge_list,
                                         DLIList<Body*>& new_body_list,
                                         CubitBoolean keep_old_body,
                                         CubitBoolean keep_free_edges );
-   //- Imprints a list of Bodies with a list of RefEdges which are projected
-   //- to a list of RefFaces
 
+  //! \brief Tolerantly imprintings a list of curves on a list of surfaces.
+  //! Should be used when you have sloppy/out-of-tolerance geometry.
+  CubitStatus tolerant_imprint( DLIList<RefFace*> &ref_faces,
+                                DLIList<RefEdge*> &ref_edge_list,
+                                DLIList<Body*> &new_bodies,
+                                bool merge = false );
+
+  //! \brief Tolerantly imprintings a list of curves onto a single surface.
+  //!  Should be used when you have sloppy/out-of-tolerance geometry.
+  CubitStatus tolerant_imprint( RefFace *ref_face,
+                                DLIList<RefEdge*> &ref_edge_list,
+                                Body *&new_body, bool merge = false );
+
+  //! \brief Imprints bodies onto one another.  Should be used when you have sloppy/out-
+  //! of-tolerance geometry.
   CubitStatus tolerant_imprint( DLIList<Body*> &bodies, DLIList<Body*> &new_bodies,
                                 bool merge = false );
-  //imprints bodies onto one another.  Should be used when you have sloppy/out-
-  //of-tolerance geometry.
 
+  //! \brief Projects list RefEdges onto a list of RefFaces.
   CubitStatus project_edges( DLIList<RefFace*> &ref_face_list,
                               DLIList<RefEdge*> &ref_edge_list_in,
-                              DLIList<RefEdge*> &ref_edge_list_new );
-    //- Projects list RefEdges to a list of RefFaces
+                             DLIList<RefEdge*> &ref_edge_list_new,
+                             CubitBoolean trim_projected = CUBIT_FALSE);
 
+  //! \brief Removes all unnessesary faces, curves, vertices from a body. 
   CubitStatus regularize_body( Body *body_ptr, Body *&new_body );
-  /**<  Removes all unnessesary faces, curves, vertices and associated
-    *  data from a body.
-    */
 
+  //! \brief Removes all unnessesary faces, curves, vertices and associated
+  //! data from a refentity.
   CubitStatus regularize_refentity( RefEntity *old_entity_ptr,
                                     Body *&new_body_ptr);
-	//- Removes all unnessesary faces, curves, vertices and associated
-    // data from a refentity.
+  
+  //! \brief Tests if a RefEntity can have any unncessary child entities removed,
+  //! or simplified away. 
+  CubitStatus test_regularize_refentity( RefEntity *old_entity_ptr);
 
+  CubitStatus split_free_curve( RefEdge *ref_edge,
+                                CubitVector &split_location );
+
+  //! \brief Separates multi-volume bodies into single-volume bodies.
   CubitStatus split_body( Body *body_ptr,
                           DLIList<Body*> &new_bodies ) const;
-  /**<  calls solid modeling engine to split the body.
+    
+  /*!  Separates surfaces from sheet bodies into separate bodies.  Connected
+    *   surfaces will remain connected but be placed in a new body.
     */
+  //! \brief Separates surfaces from sheet bodies into separate bodies.  Connected
+  CubitStatus separate_surfaces( DLIList<RefFace*> &ref_face_list,
+                                 DLIList<Body*> &new_bodies );
 
+
   ///< <HR><H3>GeometryModifyTool options and settings</H3>
-
+  
+  //! \brief Sets group imprint flag.
   static void set_group_imprint(CubitBoolean flag) {groupImprint = flag;}
+  //! \brief Gets group imprint flag.
   static CubitBoolean get_group_imprint() {return groupImprint;}
-  ///<  get/set minIds flag
 
+  //! \brief Sets all edges imprint flag.
   static void set_all_edges_imprint( CubitBoolean flag );
+  //! \brief Gets all edges imprint flag.
   static CubitBoolean get_all_edges_imprint();
-  /**<  sets/gets the allEdgesImprint flag.
-    */
 
+  //! \brief Gets boolean regularize flag.
   static void boolean_regularize( CubitBoolean flag );
+  //! \brief Sets boolean regularize flag.
   static CubitBoolean boolean_regularize();
-  /**<  sets/gets the booleanRegularize flag.
-    */
 
+  //! \brief Gets unite mixed models flag.
+  static CubitBoolean unite_mixed_models();
+  //! \brief Sets unite mixed models flag.
+  static void unite_mixed_models( CubitBoolean flag );
 
+  //! \brief Gets new ids flag.
+  static CubitBoolean get_new_ids() {return newIds;}
+  //! \brief Sets new ids flag.
   static void set_new_ids(CubitBoolean flag) {newIds = flag;}
-  static CubitBoolean get_new_ids() {return newIds;}
-  ///  get/set minIds flag
 
-  static void set_old_names(CubitBoolean flag)
-    { oldNames = flag; }
-  static CubitBoolean get_old_names()
-    { return oldNames; }
+  //! \brief Gets old names flag.
+  static CubitBoolean get_old_names() { return oldNames; }
+  //! \brief Sets old names flag.
+  static void set_old_names(CubitBoolean flag) { oldNames = flag; }
 
+  //! \brief Gets mesh autodelete flag. 
+  static CubitBoolean get_mesh_autodelete() {return meshAutodelete;}
+  //! \brief Sets mesh autodelete flag. 
+  static void set_mesh_autodelete(CubitBoolean flag) {meshAutodelete = flag;}
+
+  //! \brief Gets mesh autodelete-remesh flag. 
+  static CubitBoolean is_mesh_autodelete_remesh() {return meshAutodeleteRemesh;}
+  //! \brief Sets mesh autodelete-remesh flag. 
+  static void set_mesh_autodelete_remesh(CubitBoolean flag) {meshAutodeleteRemesh = flag;}
+
+  //! \brief Initializes all the settings in GeometryModifyTool to defaults
   static void initialize_settings();
 
 
-  static CubitStatus prepare_for_copy( RefEntity *ref_ents,
-                                       TopologyBridge *&top_bridge );
+  #ifdef PROE
+  CubitStatus prepare_for_topology_update( BodySM* old_bodysm );
 
-  static CubitStatus finish_copy( TopologyBridge *&new_bridge,
-                                  TopologyBridge *old_bridge );
+  CubitStatus finish_topology_update( BodySM* new_bodysm,
+                                      Body* old_body );
+  #endif
 
-  static CubitStatus clean_up_from_copy_failure( TopologyBridge *old_bridge );
+  //! \brief Gets the entity being copied, if any. 
+  static RefEntity* get_copy_entity() { return copyingEntity; }
 
-  static RefEntity* get_copy_entity() { return copyingEntity; }
+  //! \brief Sets the entity being copied.
   static void set_copy_entity( RefEntity *ent) { copyingEntity = ent; }
+  
+  double get_resultant_angle_score(RefFace *narrow_face,
+                                   RefFace *other_face,
+                                   RefEdge *common_edge);
 
+  double get_neighbor_type_score(RefEdge *common_edge,
+                                 RefFace *other_face,
+                                 double small_curve_size,
+                                 int &neighbor_is_narrow_or_small);
+
+  double get_dihedral_angle_score(RefFace *f1, RefFace *f2,
+                                  RefEdge *common_edge);
+
+  double get_edge_type_score(RefEdge *common_edge, double small_curve_size);
+  double get_diff_from_multiple_of_90(double angle);
+  void split_surface_with_narrow_region(RefFace *face,
+                                        DLIList<CubitVector> &split_pos1_list,
+                                        DLIList<CubitVector> &split_pos2_list);
+
   ///< <HR><H3>Topology/geometry creation functions</H3>
 
-  RefVertex* make_RefVertex(CubitVector const& point, int color = -1) const ;
-  /**<  \return  RefVertex*
+  /*!  \return  RefVertex*
     *  \return - A pointer to a newly created RefVertex
     *  \arg ref_vertex_type
     *  The type of the RefVertex
@@ -773,15 +1047,14 @@
     *  Allows the color to define during creation
     *  defaults to -1 or CUBIT_DEFAULT_COLOR
     */
+  //! \brief Creates a point from an x,y,z location
+  RefVertex* make_RefVertex(CubitVector const& point, int color = -1) const;
+  RefVertex* make_RefVertex( RefVertex *vertex ) const;
 
+  //! \brief Creates a sheet body from a surface.
   Body *make_Body(Surface *surface) const;
 
-  RefEdge* make_RefEdge( GeometryType ref_edge_type,
-                         RefVertex *ref_vertex_1,
-                         RefVertex *ref_vertex_2,
-                         DLIList<CubitVector*>& vector_list,
-                         RefFace* reffaca_ptr = NULL ) const ;
-  /**<  \return  RefEdge*
+  /*!  \return  RefEdge*
     *  \return - A pointer to a newly created RefEdge
     *  \arg ref_edge_type
     *  The type of the RefEdge
@@ -800,12 +1073,14 @@
     *  is created. If the input refface_ptr is not NULL, the points are
     *  first moved to the surface before interpolation.
     */
+  //! \brief Creates a curve from two or more points.
+  RefEdge* make_RefEdge( GeometryType ref_edge_type,
+                         RefVertex *ref_vertex_1,
+                         RefVertex *ref_vertex_2,
+                         DLIList<CubitVector*>& vector_list,
+                         RefFace* reffaca_ptr = NULL ) const ;
 
-  RefEdge* make_RefEdge(  RefVertex *ref_vertex_1,
-                          RefVertex *ref_vertex_2,
-                          RefFace* ref_face_ptr,
-                          RefVertex const* ref_vertex_3 = NULL ) const ;
-  /**<  \return  RefEdge*
+  /*!  \return  RefEdge*
     *  \return - A pointer to a newly created RefEdge
     *  \arg ref_edge_type
     *  The type of the RefEdge
@@ -819,21 +1094,22 @@
     *  line along the surface.  In periodic surfaces, a third point may
     *  be used to create the give the correct direction.
     */
-
-  RefEdge* make_RefEdge(RefEdge *ref_edge, bool copy_attribs = true) const;
-  /**<  Give a certain ref edge, create a new one.
+  //! \brief Creates a curve from two or more points, on a surface.
+  RefEdge* make_RefEdge(  RefVertex *ref_vertex_1,
+                          RefVertex *ref_vertex_2,
+                          RefFace* ref_face_ptr,
+                          RefVertex const* ref_vertex_3 = NULL ) const ;
+  
+  /*!  Give a certain ref edge, create a new one.
     *  This is useful when you are creating surfaces from curves already
     *  in the model.  If you use curves existing in the model (attached
     *  to other surfaces) then acis will mess up.  So we basically
     *  need a copy.  This will also create new vertices...
     */
-
-  RefEdge* make_RefEdge(GeometryType ref_edge_type,
-                        RefVertex *ref_vertex_1,
-                        RefVertex *ref_vertex_2,
-                        CubitVector const* intermediate_point = NULL,
-                        CubitSense sense = CUBIT_FORWARD) const ;
-  /**<  \return  RefEdge*
+  //! \brief Create a curve from an existing curve.
+  RefEdge* make_RefEdge(RefEdge *ref_edge, bool copy_attribs = true) const;
+  
+  /*!  \return  RefEdge*
     *  \return - A pointer to a newly created RefEdge
     *  \arg ref_edge_type
     *  The type of the RefEdge
@@ -878,17 +1154,36 @@
     *  3 points must form an isosceles triangle. This definition
     *  limits the user to generation of the tip of parabolic shapes only.
     */
+  //! \brief Create a curve, i.e. ellipse, parabola, straight, or arc curves.  
+  RefEdge* make_RefEdge(GeometryType ref_edge_type,
+                        RefVertex *ref_vertex_1,
+                        RefVertex *ref_vertex_2,
+                        CubitVector const* intermediate_point = NULL,
+                        CubitSense sense = CUBIT_FORWARD) const ;
 
+  //! \brief Create a surface from an existing one. 
   RefFace* make_RefFace(RefFace *from_ref_face,
                         CubitBoolean extended_from = CUBIT_FALSE) const;
-  /**<  create a refface from an existing one, creates underlying entities.
+
+  /*!  \return Body*
+    *  \return - Pointer to a newly created Body object.
+    *  \arg ref_face_list
+    *  The RefFace list from which we want to create an extended sheet.
+    *  \arg clip_box
+    *  An optional bounding box to clip the resultant sheet body by.
+    *  \arg preview
+    *  If true just draw the extended 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.
     */
+  //! \brief This function creates a sheet body by extending the input surfaces.
+  Body* make_extended_sheet( DLIList<RefFace*> &ref_face_list,
+                             CubitBox *clip_box_ptr = NULL,
+                             bool preview = false) const;
 
-  RefFace* make_RefFace(GeometryType ref_face_type,
-                        DLIList<RefEdge*>& ref_edge_list,
-                        RefFace *ref_face_ptr = NULL,
-                        bool check_edges = true ) const ;
-  /**<  \return  RefFace*
+  /*!  \return  RefFace*
     *  \return - A pointer to a newly created RefFace
     *  \arg ref_face_type
     *  The type of the RefFace
@@ -911,26 +1206,14 @@
     *  value can be a NULL pointer, if the RefFace cannot be succesfully
     *  made for some reason.
     */
+  //! \brief Creates a surface from bounding curves.
+  RefFace* make_RefFace(GeometryType ref_face_type,
+                        DLIList<RefEdge*>& ref_edge_list,
+                        bool is_free_face,
+                        RefFace *ref_face_ptr = NULL,
+                        bool check_edges = true ) const ;
 
-//  RefVolume* make_RefVolume(DLIList<RefFace*>& ref_face_list) const ;
-  /**<  \return  RefVlume*
-    *  \return - A pointer to a newly created RefVlume
-    *  \arg ref_volume_type
-    *  The type of the RefVolume
-    *  \arg ref_face_list
-    *  The RefFaces to use to create the RefVolume.
-    *
-    *  This function takes a type information and a list of
-    *  RefFaces to create a RefVolume. The underlying representation
-    *  of the RefVolume is determined by the GeometryQueryEngine of
-    *  the RefFaces. All the RefFaces in the list must be
-    *  associated with the same GeometryQueryEngine. The return
-    *  value can be a NULL pointer, if the RefVolume cannot be succesfully
-    *  made for some reason.
-    */
-
-  Body* make_Body(DLIList<RefVolume*>& ref_volume_list) const ;
-  /**<  \return  Body*
+  /*!  \return  Body*
     *  \return - A pointer to a newly created Body
     *  \arg ref_volume_list
     *  The RefVolumes to use to create the Body
@@ -943,19 +1226,17 @@
     *  pointer, if the RefFace cannot be succesfully made for some
     *  reason.
     */
+  //! \brief Creates a body from a list of volumes. 
+  Body* make_Body(DLIList<RefVolume*>& ref_volume_list) const ;
 
+  /*!  Creates a body from a ref_face.  This will always be a
+    *  sheet body, with no volume, consisting of a single face.
+    */
+  //! \brief Creates a body from a surface.
   Body* make_Body(RefFace *from_ref_face,
                   CubitBoolean extended_from = CUBIT_FALSE) const;
-  /**<  Creates a body from a ref_face.  This will always be a
-    *  sheet body, with no volume, consisting of a single face.
-    */
 
-  Body* make_Body(GeometryType ref_face_type,
-                  DLIList<RefEdge*>& ref_edge_list,
-                  RefFace *ref_face_ptr = NULL) const ;
-    // Each RefEdge in ref_edge_list MUST be a free edge, i.e., not
-    // attached to a RefFace, for this function to succeed!
-  /**<  \return  Body*
+  /*!  \return  Body*
     *  \return - A pointer to a newly created Body that has just one RefFace
     *  \arg ref_face_type
     *  The type of the RefFace
@@ -972,8 +1253,16 @@
     *  GeometryQueryEngine. The return value can be a NULL
     *  pointer, if the Body cannot be succesfully made for some
     *  reason.
+    *
+    *  Each RefEdge in ref_edge_list MUST be a free edge, i.e., not
+    *  attached to a RefFace, for this function to succeed!
     */
+  //! \brief Creates a body from a surface created from a list of curves.
+  Body* make_Body(GeometryType ref_face_type,
+                  DLIList<RefEdge*>& ref_edge_list,
+                  RefFace *ref_face_ptr = NULL) const ;
 
+  //! \brief Create bodies by sweeping curves or surfaces along a vector.
   CubitStatus sweep_translational(DLIList<RefEntity*>& ref_ent_list,
                                   const CubitVector& sweep_vector,
                                   double draft_angle,
@@ -981,8 +1270,22 @@
                                   CubitBoolean switchside,
                                   CubitBoolean rigid);
 
-   CubitStatus sweep_target(CubitPlane ref_plane,
+   CubitStatus sweep_curve_target(CubitPlane ref_plane,
 						 DLIList<RefEntity*>& ref_ent_list);
+
+   CubitStatus sweep_curve_target(DLIList<RefEdge*>& curve_list,
+                            Body *target_body,
+                            DLIList<Body*> &out_bodies,
+                            CubitVector direction,
+                            CubitPlane stop_plane,
+                            bool unite);
+
+   CubitStatus sweep_surface_target(RefFace *face,
+                                    Body *target_body,
+                                    CubitVector distance,
+                                    CubitPlane stop_plane,
+                                    double magnitude = 0.0);
+
    CubitStatus sweep_surface_target(CubitPlane ref_plane,
 						DLIList<RefEntity*>& ref_ent_list);
 
@@ -993,6 +1296,7 @@
                                   CubitBoolean switchside,
                                   CubitBoolean rigid);
 
+  //! \brief Creates bodies by sweeping surfaces or curves about an axis. 
   CubitStatus sweep_rotational(DLIList<RefEntity*>& ref_ent_list,
                                const CubitVector& point,
                                const CubitVector& direction,
@@ -1004,24 +1308,47 @@
                                CubitBoolean make_solid = CUBIT_FALSE,
                                CubitBoolean rigid = CUBIT_FALSE);
 
+  //! \brief Creates bodies by sweeping surfaces or curves along a curve. 
   CubitStatus sweep_along_curve(DLIList<RefEntity*>& ref_ent_list,
                                 DLIList<RefEdge*>& ref_edge_list,
                                 double draft_angle = 0.0,
                                 int draft_type = 0,
                                 CubitBoolean rigid = CUBIT_FALSE);
 
+  //! \brief Currently unsupported.
+  CubitStatus tweak_bend( DLIList<Body*> &bend_bodies,
+	                  DLIList<Body*> &new_body_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 );
+
+  /*! Chamfer curves on solid and 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.
+    */
+  //! \brief Chamfer curves on solid and sheet bodies. 
   CubitStatus tweak_chamfer( DLIList<RefEdge*> &ref_edge_list,
                              double left_offset,
                              DLIList<Body*> &new_body_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 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.
     */
-
+  //! \brief Chamfer vertices on solid or sheet bodies.
   CubitStatus tweak_chamfer( DLIList<RefVertex*> &ref_vertex_list,
                              double offset1,
                              DLIList<Body*> &new_body_list,
@@ -1032,170 +1359,255 @@
                              RefEdge *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
-    *   supplied, only one offset value is allowed and the edges are not used.
-    */
 
+  //! \brief Creates a round fillet (or blend) at the given curves on solid or
+  //!  sheet bodies.
   CubitStatus tweak_fillet( DLIList<RefEdge*> &ref_edge_list,
                             double radius,
                             DLIList<Body*> &new_body_list,
                             CubitBoolean keep_old_body = CUBIT_FALSE,
                             CubitBoolean preview = CUBIT_FALSE );
-  /**<  Create a round fillet (or blend) at the given curves on solid bodies.
+
+  /*! Creates 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.
     */
-
+  //! \brief Creates a round fillet (or blend) at the given curve. 
   CubitStatus tweak_fillet( RefEdge *ref_edge_ptr,
                             double start_radius,
                             double end_radius,
                             Body *&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.
-    */
 
+  //! \brief Create a round fillet (or blend) at the given vertices on sheet bodies.
   CubitStatus tweak_fillet( DLIList<RefVertex*> &ref_vertex_list,
                             double radius,
                             DLIList<Body*> &new_body_list,
                             CubitBoolean keep_old_body = CUBIT_FALSE,
                             CubitBoolean preview = CUBIT_FALSE );
-  /**<  Create a round fillet (or blend) at the given vertices on sheet bodies.
-    */
 
+  //! \brief Tweak specified faces of a volume or volumes along a vector.
   CubitStatus tweak_move( DLIList<RefFace*> &ref_face_list,
                           const CubitVector &delta,
                           DLIList<Body*> &new_body_list,
                           CubitBoolean keep_old_body = CUBIT_FALSE,
                           CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified faces of a volume or volumes along a vector.
-    */
 
+  //! \brief Tweak specified curves of a sheet body along a vector.
   CubitStatus tweak_move( DLIList<RefEdge*> &ref_edge_list,
                           const CubitVector &delta,
                           DLIList<Body*> &new_body_list,
                           CubitBoolean keep_old_body = CUBIT_FALSE,
                           CubitBoolean preview = CUBIT_FALSE );
-  /**<  Tweak specified curves of a sheet body along a vector.
+
+  /*! Tweak specified faces of a volume or volumes by offsetting those faces
+    * by the offset distance. Optionally supply additional faces with
+    * different offset distances.
     */
-
+  //! \brief Offsets a surface(s) on a volume(s).
   CubitStatus tweak_offset( DLIList<RefFace*> &ref_face_list,
                             double offset_distance,
+                            DLIList<RefFace*> *add_ref_face_list_ptr,
+                            DLIList<double> *add_offset_list_ptr,
                             DLIList<Body*> &new_body_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.
+
+  /*! Tweak specified curves of a sheet body or bodies by offsetting those
+    * curves by the offset distance.  Optionally supply additional curves with
+    * different offset distances.
     */
-
+  //! \brief Offset curves on sheet bodies.
   CubitStatus tweak_offset( DLIList<RefEdge*> &ref_edge_list,
                             double offset_distance,
+                            DLIList<RefEdge*> *add_ref_face_list_ptr,
+                            DLIList<double> *add_offset_list_ptr,
                             DLIList<Body*> &new_body_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.
-    */
 
-  CubitStatus tweak_remove( DLIList<RefFace*> &ref_face_list,
-                            DLIList<Body*> &new_body_list,
-                            CubitBoolean extend_adjoining = CUBIT_TRUE,
-                            CubitBoolean keep_surface = CUBIT_FALSE,
-                            CubitBoolean keep_old_body = CUBIT_FALSE,
-                            CubitBoolean individual = CUBIT_FALSE,
-                            CubitBoolean preview = CUBIT_FALSE);
-  /**<  Remove surfaces from a body or bodies and then extend the adjoining
-    *   surfaces to fill the gap or remove the hole.
-    */
+  //! \brief Performs tweak_remove operation on surfaces individually. 
+  CubitStatus tweak_remove_individually( DLIList<RefFace*> &ref_face_list,
+                                         DLIList<Body*> &new_body_list,
+                                         CubitBoolean keep_surface = CUBIT_FALSE,
+                                         CubitBoolean keep_old_body = CUBIT_FALSE,
+                                         CubitBoolean preview = CUBIT_FALSE );
 
+  //! \brief Performs tweak_remove operation on surfaces collectively. 
+  CubitStatus tweak_remove_together( DLIList<RefFace*> &ref_face_list,
+                                     DLIList<Body*> &new_body_list,
+                                     CubitBoolean extend_adjoining = CUBIT_TRUE,
+                                     CubitBoolean keep_surface = CUBIT_FALSE,
+                                     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.
+  */
+  //! \brief Removes a surface from a volume, extending neighboring surfaces.
   CubitStatus tweak_remove( DLIList<RefEdge*> &ref_edge_list,
                             DLIList<Body*> &new_body_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.
+
+  /*!  Tweak specified faces of a volume or volumes up to target surface.
+    *  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.
     */
-
+  //! \brief Extends (tweaks) surfaces up to a target surface.
   CubitStatus tweak_target( DLIList<RefFace*> &ref_face_list,
                             DLIList<RefFace*> &target_face_list,
                             DLIList<Body*> &new_body_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 target plane. 
+    *   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.
+    */
+
+  //! \brief Extends (tweaks) surfaces up to a target plane.
   CubitStatus tweak_target( DLIList<RefFace*> &ref_face_list,
                             CubitPlane &plane,
                             DLIList<Body*> &new_body_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 target surface
-    *   or plane.
+
+  /*!   Tweak specified edges of a surface or set of surfaces (in sheet
+    *   bodies) up to target surfaces or plane.  This essentially extends
+    *   or 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.
     */
-
+  //! \brief Extends (tweaks) curves up to a target surface.
   CubitStatus tweak_target( DLIList<RefEdge*> &ref_edge_list,
                             DLIList<RefFace*> &target_face_list,
                             DLIList<Body*> &new_body_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 );
+                            CubitBoolean preview = CUBIT_FALSE,
+                            double max_area_increase = 0 );
   CubitStatus tweak_target( DLIList<RefEdge*> &ref_edge_list,
                             CubitPlane &plane,
                             DLIList<Body*> &new_body_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 target surfaces or plane.  This essentially extends
-    *   or trims the attached surfaces of the sheet body.
+
+  /*!   Tweak specified edges of a surface or set of surfaces (in sheet
+    *   bodies) up to target plane.  This essentially extends
+    *   or 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.
     */
-
+  //! \brief Extends (tweaks) curves up to a target plane.
   CubitStatus tweak_target( DLIList<RefEdge*> &ref_edge_list,
                             DLIList<RefEdge*> &target_edge_list,
                             DLIList<Body*> &new_body_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 );
+                            CubitBoolean preview = CUBIT_FALSE,
+                            double max_area_increase = 0 );
   /**<  Tweak specified edges of a sheet body or bodies up to target curves
     *   that are part of a sheet body.  The target is a surface or surfaces
     *   created by thickening the owning surface of the target curve(s).
+    *   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.
     */
+  //! \brief Tweak specified vertex of a sheet body to a given location.
+  CubitStatus tweak_target( RefVertex *ref_vertex_ptr,
+                            DLIList<RefFace*> &modify_ref_face_list,
+                            CubitVector &target_loc,
+                            Body *&new_Body_ptr,
+                            CubitBoolean keep_old_body = CUBIT_FALSE,
+                            CubitBoolean preview = CUBIT_FALSE );
 
-
+  //! \brief Converts edges smaller than 'lengthlimit' into tolerant (or fat) vertices.
+  //! ACIS only.
   CubitStatus remove_curve_slivers( DLIList<Body*> &bodies, double lengthlimit );
-  //ACIS-specific function only.  Converts edges smaller than 'lengthlimit' into
-  //tolerant (or fat) vertices.
 
+  //! \brief Create a surface using arrays of points in u and v directions. 
   CubitStatus create_net_surface( DLIList<Surface*>& ref_face_list, BodySM *& new_body,
                                   DLIList<DLIList<CubitVector*>*> &vec_lists_u,
                                   DLIList<DLIList<CubitVector*>*> &vec_lists_v,
                                   double net_tol = 1e-3,
                                   CubitBoolean heal = CUBIT_TRUE );
 
-  CubitStatus create_net_surface( DLIList<RefEdge*>& u_curves, DLIList<RefEdge*>& v_curves,
+  //! \brief Create a surface using curves in u and v directions. 
+  CubitStatus create_net_surface( DLIList<RefEdge*>& u_curves, 
+                                  DLIList<RefEdge*>& v_curves,
                                   double net_tol = 1e-3,
                                   CubitBoolean heal = CUBIT_TRUE );
 
+  //! \brief Creates an offset surface some distance from a surface.
   CubitStatus create_offset_surface( RefFace* ref_face_ptr,
                                      double offset_distance );
 
+  /*! 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.
+    */
+  //! \brief Create a body(s) by offsetting the given surfaces. 
+  CubitStatus create_offset_sheet( DLIList<RefFace*> &ref_face_list,
+                                   double offset_distance,
+                                   DLIList<RefFace*> *add_ref_face_list_ptr,
+                                   DLIList<double> *add_offset_list_ptr,
+                                   DLIList<Body*> &new_body_list,
+                                   CubitBoolean preview = CUBIT_FALSE );
+
+  //! \brief Create a body by offsetting all the surface of the body. 
   CubitStatus create_offset_body( Body *body_ptr, Body *&new_body,
                                   double offset_distance );
 
-  CubitStatus create_skin_surface( DLIList<RefEdge*>& ref_edges, Body*& new_body );
-
-#ifdef BOYD14
-  CubitStatus loft_surfaces( RefFace *face1, const double &takeoff1,
-                             RefFace *face2, const double &takeoff2,
-                             Body*& new_body,
-                             CubitBoolean arc_length_option = CUBIT_FALSE,
-                             CubitBoolean twist_option = CUBIT_FALSE,
-                             CubitBoolean align_direction = CUBIT_TRUE,
-                             CubitBoolean perpendicular = CUBIT_TRUE,
-                             CubitBoolean simplify_option = CUBIT_FALSE);
-#endif
-
+  //! \brief Create a sheet body skinning (lofting) a series of curves.
+  CubitStatus create_skin_surface( DLIList<RefEdge*>& ref_edges, 
+                                   Body*& new_body,
+                                   DLIList<RefEdge*>& guides);
+  
+  //! \brief Create a solid body by lofting between two surfaces.
   CubitStatus loft_surfaces_to_body( RefFace *face1, const double &takeoff1,
 				     RefFace *face2, const double &takeoff2,
                                      Body*& new_body,
@@ -1205,11 +1617,50 @@
                                      CubitBoolean perpendicular,
                                      CubitBoolean simplify_option);
 
+  CubitStatus create_surface_curve(DLIList<RefEntity*> curve_entity,
+									DLIList<RefEntity*> target_entity,
+									CubitVector sweep_direction = CubitVector (0,0,0),
+									CubitBoolean distance_flag = CUBIT_FALSE);
+
+  CubitStatus idealize_hole_slot_geometry(DLIList<RefEntity*> idealize_entity,
+                                     DLIList<RefEntity*> exclude_entity,
+                                     double arc_radius,
+                                     double slot_arc_radius,
+                                     double slot_length,
+                                     CubitBoolean preview = CUBIT_FALSE);
+
+  CubitStatus idealize_fillet_geometry(DLIList<RefEntity*> idealize_entity,
+                                       DLIList<RefEntity*> exclude_entity,
+                                       double fillet_rad,
+                                       CubitBoolean internal_flg,
+                                       CubitBoolean external_flg,
+						               CubitBoolean preview = CUBIT_FALSE);
+
+  CubitStatus create_surface_doubler(DLIList<RefEntity*> doubler_entity,
+                                    DLIList<RefEntity*> target_entity,
+                                    DLIList<Body*> &body_list_out,
+                                    CubitBoolean internal_flg = CUBIT_FALSE,
+                                    CubitBoolean extend_flg = CUBIT_TRUE,
+                                    CubitPlane *limit_plane = NULL,
+                                    CubitVector sweep_direction = CubitVector(0,0,0),
+                                    CubitBoolean preview = CUBIT_FALSE);
+  
+  /*! Fits an analytic spline surface through positions.  If a surface is specified, 
+      positions are forced to lie on the surface and restrains the resultant surface
+      geometry to match the surface's geometry.  The project parameter will project 
+      the nodes or vertices to the specified surface. 
+  */
+  //! \brief  Fits an analytic spline surface through positions. 
   CubitStatus create_surface( DLIList<CubitVector*>& vec_list,
                               Body *&new_body,
                               RefFace *ref_face_ptr,
 			      CubitBoolean project_points );
 
+  CubitStatus create_surface( DLIList<RefVertex*> &vert_list, 
+                              Body *&new_body );
+
+
+  //! \brief Creates a simple triangular weld surface.
   CubitStatus create_weld_surface( CubitVector &root,
                                    RefFace *ref_face1,
                                    double leg1,
@@ -1217,139 +1668,103 @@
                                    double leg2,
                                    Body *&new_body );
 
-  CubitStatus create_body_from_surfs( DLIList<RefFace*> &ref_face_list,
-                                      Body *&new_body,
-                                      CubitBoolean keep_old = CUBIT_FALSE,
-                                      CubitBoolean heal = CUBIT_TRUE ) const;
-  /**<  Creates a body out of the surfaces in the ref_face_list.  The surfaces
+  /*!  Creates a body out of the surfaces in the ref_face_list.  The surfaces
     *  can be either free surfaces or sheet bodies or both.
-    *  The body should be healed.
+    *  The body should be healed.  The bounding curves and vertices between
+    *  the surfaces must be within tolerance.
     */
+  //! \brief Creates a body out of the specified surfaces. 
+  CubitStatus create_solid_bodies_from_surfs( DLIList<RefFace*> &ref_face_list,
+                                      DLIList<Body*> &new_bodies,
+                                      CubitBoolean keep_old = CUBIT_FALSE,
+                                      CubitBoolean heal = CUBIT_TRUE,
+                                      CubitBoolean sheet = CUBIT_FALSE ) const;
 
+  //! \brief Create curves from the intersection of two surfaces.
   CubitStatus surface_intersection( RefFace *ref_face1,
                                     RefFace *ref_face2,
                                     DLIList<RefEdge*> &ref_edge_list );
-  /**< Create curves from the intersection of two surfaces */
 
+  //! \brief Create an arc curve from three points.
   RefEdge* create_arc_three( RefVertex* ref_vertex1,
                              RefVertex* ref_vertex2,
                              RefVertex* ref_vertex3,
                              CubitBoolean full = CUBIT_FALSE );
+
+  //! \brief Create an arc curve tangent to three curves.
   RefEdge* create_arc_three( RefEdge* ref_edge1,
                              RefEdge* ref_edge2,
                              RefEdge* ref_edge3,
                              CubitBoolean full = CUBIT_FALSE );
+  
+  /*! \brief Create an arc curve from two points and a center point. 
+      If full option is specified, a full circle is created.*/
+  //! \brief Create an arc curve from two points and a center point. 
   RefEdge* create_arc_center_edge( RefVertex* ref_vertex1,
                                    RefVertex* ref_vertex2,
                                    RefVertex* ref_vertex3,
                                    const CubitVector &normal,
                                    double radius = CUBIT_DBL_MAX,
                                    CubitBoolean full = CUBIT_FALSE );
-  /**<  Methods to create arcs.  First uses 3 points on arc, next creates arc
-    *  tangent to 3 curves, last creates arc using center and two points on arc.
-    *  If full option is specified, a full circle is created.
-    */
 
+  //! \brief  Create a curve that is a combination of the specified curves.
   CubitStatus create_curve_combine( DLIList<RefEdge*>& ref_edge_list,
                                     RefEdge *&new_ref_edge_ptr );
-  /*<  Uses the solid modeller to create a new RefEdge that is a combination
-   *  of the input chain of edges.
-   */
 
 
-  static void set_sep_after_webcut_setting(CubitBoolean val)
-    {sepAfterWebcut = val;}
-  static CubitBoolean get_sep_after_webcut_setting()
-    {return sepAfterWebcut;}
-  /**< Gets/Sets the separate after webcut static flag.
-    */
+  //! \brief Sets sepAfterWebcut variable.
+  static void set_sep_after_webcut_setting(CubitBoolean val) {sepAfterWebcut = val;}
 
+  //! \brief Gets sepAfterWebcut variable.
+  static CubitBoolean get_sep_after_webcut_setting() {return sepAfterWebcut;}
+
+  /*!  Returns CUBIT_TRUE if all the entities have the same geometric query engine and
+    *  if that is the same one as the default. */
+  //! \brief Check to determine if all entities are of the same geometry engine.
   CubitBoolean same_modify_engine(DLIList<TopologyEntity*> &topo_list) const;
-  /**<  Returns CUBIT_TRUE if all the entities have the same geometric query engine and
-    *  if that is the same one as the default.
-    */
 
-  CubitBoolean same_modify_engine(DLIList<RefEntity*> &ref_entity_list,
-				  CubitBoolean check_children = CUBIT_FALSE) const;
-  /**<  Returns CUBIT_TRUE if all the entities have the same geometric query engine and
+  /*!  Returns CUBIT_TRUE if all the entities have the same geometric query engine and
     *  if that is the same one as the default.  If the check_children parameter is
     *  CUBIT_TRUE, all the child entities will also be checked.
     */
+  //! \brief Check to determine if all entities are of the same geometry engine as 
+  //! active geometry engine.
+  CubitBoolean same_modify_engine(DLIList<RefEntity*> &ref_entity_list,
+				  CubitBoolean check_children = CUBIT_FALSE) const;
 
-  GeometryModifyEngine* common_modify_engine( DLIList<Body*>& bodies,
-                                              DLIList<BodySM*>& bodysms ) const;
+  
+  //! \brief Determines if specified RefFaces and RefEdges are of the same geometry engine.
+  //! Returns common engine, if any, and underlying surfaces and curves. 
   GeometryModifyEngine* common_modify_engine( DLIList<RefFace*>& faces,
                                               DLIList<RefEdge*>& edges,
                                               DLIList<Surface*>& surfaces,
-                                              DLIList<Curve*>& curves ) const;
-  GeometryModifyEngine* common_modify_engine( DLIList<RefFace*>& faces,
-                                              DLIList<Surface*>& surfaces ) const;
-  GeometryModifyEngine* common_modify_engine( DLIList<RefEdge*>& edges,
-                                              DLIList<Curve*>& curves ) const;
-  GeometryModifyEngine* common_modify_engine( DLIList<RefVertex*>& vertices,
-                                              DLIList<Point*>& points ) const;
+                                              DLIList<Curve*>& curves,
+                                              CubitBoolean allow_composites = CUBIT_FALSE) const;
 
-  GeometryModifyEngine* common_modify_engine( DLIList<TopologyEntity*>& topology_list,
-                                              DLIList<TopologyBridge*>& engine_bridges,
-                                              CubitBoolean allow_virtual_engine
-                                              = CUBIT_FALSE ) const;
-  /**<  \return GeometryModifyEngine*
-    *   A GeometryModifyEngine common at least one
-    *   TopologyBridge of each of the passed TopologyEntities, or
-    *   NULL if no common geometry engine is found.
-    *   \arg topology_list
-    *   The input list of TopologyEntities
-    *   \arg engine_bridges
-    *   Pass back the list of TopolgyBridges associated with each
-    *   of the passed TopologyEntities (topology_list) and owned
-    *   by the returned geometry engine.
-    *   \arg allow_virtual_engine
-    *   Return VirtualGeometryEngine::instance() if no common
-    *   geometry enginge can be found.
-    *
-    *   Look for a common geometry engine other than the
-    *   VirtualGeometryEngine.  If no common geometry engine other
-    *   than VGE can be found and allow_virtual_engine is FALSE,
-    *   NULL is returned.  If allow_virtual_engine is TRUE, and no
-    *   common geometry engine is found, VGE will be returned, and
-    *   engine_bridges will be populated with any virtual geometry
-    *   if possible, otherwise with the first topology bridge attached
-    *   to each of the passed TopologyEntities.
-    */
 
+
+  //! \brief Add a geometry modify engine to the list.
   void add_gme(GeometryModifyEngine *gme_ptr);
-    /**< add a geometry modify engine to the list
-     */
 
+  //! \brief < remove a geometry modify engine from the list; returns CUBIT_FAILURE
+  //!  if it wasn't in the list.
   CubitStatus remove_gme(GeometryModifyEngine *gme_ptr);
-    /**< remove a geometry modify engine from the list; returns CUBIT_FAILURE
-     *   if it wasn't on the list
-     */
 
+  //! \brief Returns a list of GeometryModifyEngines.
   void get_gme_list(DLIList<GeometryModifyEngine*> &gme_list);
-    /**< return the list of gme's
-     */
 
+  //! \brief Gets the current active GeometryModifyEngine.
   GeometryModifyEngine *get_gme() const;
-    /**< return the first gme on the list
-     */
 
-//  GeometryModifyEngine *get_gme(const EntityType gme_type);
-    /**< return the gme of the specified type
-     */
 
+  //! \brief Gets the GeometryModifyEngine of this entity.
   GeometryModifyEngine *get_engine(TopologyBridge *tb_ptr) const;
-    /**< get the geometry modify engine associated with this entity
-     */
 
+  //! \brief Gets the GeometryModifyEngine of this entity.
   GeometryModifyEngine *get_engine(TopologyEntity *te_ptr,
                                    TopologyBridge** bridge = 0) const;
-    /**< get the geometry modify engine associated with this entity
-     */
-  CubitStatus get_offset_intersections( RefEdge* ref_edge1, RefEdge* ref_edge2,
-                                        DLIList<CubitVector*>& intersection_list,
-                                        double offset, CubitBoolean ext_first = CUBIT_TRUE );
-  /***< Finds the intersections of a certain distance (offset) between two
+
+  /*! Finds the intersections of a certain distance (offset) between two
     * curves.  The two curves must lie in a plane.  The first curve is offset
     * the offset distance in both directions, and the bounded intersections with
     * the second curve are found.  The first curve can optionally be extended
@@ -1359,36 +1774,49 @@
     * diameter on an arc in an engineering drawing.  The function allocates the
     * CubitVectors in the returned list, so be sure to free them.
     */
+  //! \brief Finds the intersections of a certain distance (offset) between two curves.
+  CubitStatus get_offset_intersections( RefEdge* ref_edge1, RefEdge* ref_edge2,
+                                        DLIList<CubitVector*>& intersection_list,
+                                        double offset, CubitBoolean ext_first = CUBIT_TRUE );
 
-  CubitStatus get_offset_intersections( RefEdge* ref_edge_ptr, RefFace* ref_face_ptr,
-                                        DLIList<CubitVector*> &intersection_list,
-                                        double offset = 0.0,
-                                        CubitBoolean ext_surf = CUBIT_TRUE );
-  /**< Finds intersections (points) of the curve and surface.  The surface can
+  /*! Finds intersections (points) of the curve and surface.  The surface can
     * be offset - it is offset to each side and intersections are found.  By
     * default the surface is extended to infinity (if possible) and the
     * intersections are found.  The function allocates the CubitVectors in
     * the returned list, so be sure to free them.
     */
+  //! \brief Finds intersections (points) of the curve and surface.  
+  CubitStatus get_offset_intersections( RefEdge* ref_edge_ptr, RefFace* ref_face_ptr,
+                                        DLIList<CubitVector*> &intersection_list,
+                                        double offset = 0.0,
+                                        CubitBoolean ext_surf = CUBIT_TRUE );
 
+  //! \brief From two surface, create a midplane, then trim it with a body.
   CubitStatus get_mid_plane( RefFace *ref_face_1,
                              RefFace *ref_face_2,
                              Body *body_to_trim_to,
                              DLIList<RefFace*> &mid_plane_surfs ) const;
-  /**< Given 2 surfaces, this function returns trimmed surfaces of
-    *  the mid plane.
-    */
 
+  //! \brief Given 2 surfaces, this returns trimmed surfaces of
+  //!  the midsurface (this is an ALPHA feature).
   CubitStatus get_mid_surface( RefFace *ref_face_1,
                              RefFace *ref_face_2,
                              Body *body_to_trim_to,
                              DLIList<RefFace*> &mid_plane_surfs ) const;
-  /**< Given 2 surfaces, this function returns trimmed surfaces of
-    *  the midsurface (this is an ALPHA feature).
-    */
 
-CubitStatus set_default_gme(GeometryModifyEngine* GMEPtr);
+  //! \brief Sets the active geometry engine.
+  CubitStatus set_default_gme(GeometryModifyEngine* GMEPtr);
 
+  //! Get a subset of bodies from 'remaining_bodies' that share
+  //! a common GeometryModifyEngine.  Remove them from
+  //! 'remaining_bodies', put the Bodies and corresponding BodySMs in
+  //! 'engine_bodies' and 'engine_body_sms', and return the engine.
+  //! Returns NULL if all bodies remaining in the list have no
+  //! modify engine.
+  //! \brief Groups Bodies with the same underlying geometry engine into a list.
+  GeometryModifyEngine* group_bodies_by_engine( DLIList<Body*>& remaining_bodies,
+                                                DLIList<Body*>& engine_bodies,
+                                                DLIList<BodySM*>& engine_body_sms ) const;
 protected :
 
   GeometryModifyTool(GeometryModifyEngine* GMEPtr);
@@ -1414,32 +1842,50 @@
 
   CubitStatus okay_to_modify( DLIList<Body*>& bodies, const char* op ) const;
 
-public:  /* needed by OffsetSplitTool*/
-  CubitStatus finish_webcut( DLIList<Body*>& input_bodies,
-                             DLIList<BodySM*>& webcut_results,
-                             CubitBoolean merge,
-                             CubitStatus webcut_status,
-                             DLIList<Body*>& new_bodies,
-                             CubitBoolean print_info = CUBIT_TRUE ) const;
-    //- Helper function for all webcut functions.
-    //- Finish up DAG update, merging, etc. after GME does webcut.
-    //I input_bodies
-    //I- The list of bodies that were webcut
-    //I webcut_results
-    //I- The new bodies returned by the GME webcut.
-    //I merge
-    //I- Merge after webcut
-    //I webcut_status
-    //I- The return value from the GME webcut function
-    //O new_bodies
-    //O- The new Bodies constructed from the passed BodySMs.
-    //R CubitStatus
-    //R- CUBIT_FAILURE on error, webcut_status on success.
-    //- Does separate_body_after_webcut for all bodies if
-    //- webcut_status == CUBIT_SUCCESS
-    //- Merges bodies if webcut_status == CUBIT_SUCCESS AND merge == CUBIT_TRUE
+  GeometryModifyEngine* common_modify_engine( DLIList<Body*>& bodies,
+                                              DLIList<BodySM*>& bodysms ) const;
 
-  /* needed by AcisEdgeTool */
+  GeometryModifyEngine* common_modify_engine( DLIList<RefFace*>& faces,
+                                              DLIList<Surface*>& surfaces,
+                                              CubitBoolean allow_composites = CUBIT_FALSE ) const;
+  GeometryModifyEngine* common_modify_engine( DLIList<RefEdge*>& edges,
+                                              DLIList<Curve*>& curves,
+                                              CubitBoolean allow_composites = CUBIT_FALSE ) const;
+  GeometryModifyEngine* common_modify_engine( DLIList<RefVertex*>& vertices,
+                                              DLIList<Point*>& points,
+                                              CubitBoolean allow_composites = CUBIT_FALSE ) const;
+
+  GeometryModifyEngine* common_modify_engine( DLIList<TopologyEntity*>& topology_list,
+                                              DLIList<TopologyBridge*>& engine_bridges,
+                                              CubitBoolean allow_composites
+                                              = CUBIT_FALSE ) const;
+  /**<  \return GeometryModifyEngine*
+    *   A GeometryModifyEngine common at least one
+    *   TopologyBridge of each of the passed TopologyEntities, or
+    *   NULL if no common geometry engine is found.
+    *   \arg topology_list
+    *   The input list of TopologyEntities
+    *   \arg engine_bridges
+    *   Pass back the list of TopolgyBridges associated with each
+    *   of the passed TopologyEntities (topology_list) and owned
+    *   by the returned geometry engine.
+    *   \arg allow_virtual_engine
+    *   Return VirtualGeometryEngine::instance() if no common
+    *   geometry enginge can be found.
+    *
+    *   Look for a common geometry engine other than the
+    *   VirtualGeometryEngine.  If no common geometry engine other
+    *   than VGE can be found and allow_virtual_engine is FALSE,
+    *   NULL is returned.  If allow_virtual_engine is TRUE, and no
+    *   common geometry engine is found, VGE will be returned, and
+    *   engine_bridges will be populated with any virtual geometry
+    *   if possible, otherwise with the first topology bridge attached
+    *   to each of the passed TopologyEntities.
+    */
+
+public:  
+
+  //! \brief Internal use only. 
   CubitStatus finish_sm_op( DLIList<Body*>& input_bodies,
                             DLIList<BodySM*>& new_bodies,
                             DLIList<Body*>& result_bodies,
@@ -1466,7 +1912,8 @@
   GeometryModifyEngine* tweak_setup( DLIList<RefFace*>& input_faces,
                                      const char* tweak_function_name,
                                      DLIList<Body*>& old_bodies_out,
-                                     DLIList<Surface*>& surfaces_out );
+                                     DLIList<Surface*>& surfaces_out,
+                                     CubitBoolean allow_composites = CUBIT_FALSE);
 
   GeometryModifyEngine* tweak_setup( DLIList<RefEdge*>& input_edges,
                                      const char* tweak_function_name,
@@ -1505,20 +1952,6 @@
     //O curve_list
     //O- Curves corresponding to edges in edge_list.
 
-  CubitStatus sweep_finish( const char* const sweep_function_name,
-                            DLIList<Body*>& input_body_list,
-                            DLIList<BodySM*>& new_body_list,
-                            CubitBoolean restore_newids );
-    //- Common cleanup code for sweep functions
-    //I sweep_function_name
-    //I- Name to use in error messages.
-    //I input_body_list
-    //I- Bodies that may need to be updated.
-    //I new_body_list
-    //I- bodies returned by GeometryModifyEngine
-    //I restore_newids
-    //I- Passed back from sweep_setup -- restore setting state.
-
   CubitStatus imprint_singly( DLIList<Body*>& body_list,
                               DLIList<Body*>& new_bodies,
                               CubitBoolean keep_old );
@@ -1531,57 +1964,61 @@
   Body* update_body( Body* body ) const;
     //- Destroy or update modified body, as appropriate.
 
+  void body_premodify(Body* body) const;
+    //- traverse the body object and calls premodify function on each structure
+
+
 private :
 
+  //! \brief Static pointer to the unique instance of this class.
   static GeometryModifyTool* instance_;
-  /**<  static pointer to the unique instance of this class.
-    */
 
+  //! \brief Use group imprinting, which is much faster. Default: true.
   static CubitBoolean groupImprint;
-  /**<  if true, the new group imprint function is called, which is much faster;
-    */
 
+  //! \brief An object will be unmeshed if modified or deleted. Default: true.
+  static CubitBoolean meshAutodelete;
+
+  //! \brief  An object will be cached if the mesh is autodeleted
+  //!  and can be remeshed later.  Default: false.
+  static CubitBoolean meshAutodeleteRemesh;
+
+  //! \brief Causes code to reuse old ids, which are more persistent.  Default: false.
   static CubitBoolean newIds;
-  /**<  if true, causes code to reuse old ids, which are more persistent
-    */
 
+  //! \brief Attempt entity naming backwards compatible with v8/pre-bool-on-merged.  Default:
+  //! false.
   static CubitBoolean oldNames;
-  /**< Attempt entity naming backwards compatible with v8/pre-bool-on-merged
-    */
 
+  //! \brief Separate the result bodies of webcutting into single-body volumes. 
+  //!  Default: true.
   static CubitBoolean sepAfterWebcut;
-  /**< Will separate after webcutting the bodies into multiple bodies that
-    *  only contain 1 volume each.
-    */
 
-  static CubitBoolean allEdgesImprint;
-  /**<  Option for acis to know if we should imprint all of the edges
+  /*!  Option for acis to know if we should imprint all of the edges
     *  or only relevant ones.  For now, default is false, but check
     *  the .cc file.  The user can control this by a "set" nonregimprint
-    *  command.
+    *  command.  Default: true.
     */
+  static CubitBoolean allEdgesImprint;
 
+  //! \brief Regularized booleans are performed.  Default: true.
   static CubitBoolean booleanRegularize;
-    /**< If true, regularized booleans are performed;
-     *  Otherwise, nonregularized booleans are performed.
-     */
 
+  //! \brief Unite operations can mix sheet bodies with solid bodies.  Default: true.
+  static CubitBoolean uniteMixedModels;
+
+  /*! Pointer to the entity being copied.  When copying an entity, used to 
+      prevent to copying of unique id and saved-merged-ids attributes. 
+  */
+  //! \brief This pointer points to the entity that is being copied.  
   static RefEntity *copyingEntity;
-    //- This pointer points to the entity that is being copied.
 
+  //! \brief The list of geometry modify engines.
   DLIList<GeometryModifyEngine*> gmeList;
-  /**<  The list of geometry modify engines
-    */
 
-  GeometryModifyEngine* group_bodies_by_engine( DLIList<Body*>& remaining_bodies,
-                                                DLIList<Body*>& engine_bodies,
-                                                DLIList<BodySM*>& engine_body_sms ) const;
-    //- Get a subset of bodies from 'remaining_bodies' that share
-    //- a common GeometryModifyEngine.  Remove them from
-    //- 'remaining_bodies', put the Bodies and corresponding BodySMs in
-    //- 'engine_bodies' and 'engine_body_sms', and return the engine.
-    //- Returns NULL if all bodies remaining in the list have no
-    //- modify engine.
+  void get_merged_curve_and_surface_ids( DLIList<Body*> &bodies,
+                                         DLIList<int> &merged_surface_ids,
+                                         DLIList<int> &merged_curve_ids ) const;
 
   CubitStatus separate_body_after_webcut (DLIList<Body*> &input_list,
                                           DLIList<Body*> &output_list) const;
@@ -1590,6 +2027,9 @@
     *   only be called after webcutting. (Checks sepAfterWebcut flag.)
     */
 
+  void fixup_merged_entities( DLIList<int> &merged_surface_ids,
+                              DLIList<int> &merged_curve_ids ) const;
+
   bool contains_intermediate_geom(DLIList<Body*>& list) const;
   bool contains_intermediate_geom(DLIList<TopologyBridge*>& list) const;
   bool contains_composites(DLIList<TopologyBridge*>& bridge_list ) const;
@@ -1602,15 +2042,136 @@
     * are virtual.
     */
 #endif
-  
+
   void do_attribute_setup(void);
   void do_attribute_cleanup(void);
   void push_vg_attributes_before_modify(DLIList<BodySM*> &old_sms);
   CubitStatus restore_vg_after_modify(DLIList<BodySM*> &new_sms,
+                                      DLIList<Body*> &old_bodies,
+                                      GeometryModifyEngine *gme);
+  void remove_pushed_attributes(DLIList<BodySM*> &new_sms,
                                       DLIList<Body*> &old_bodies);
   void push_imprint_attributes_before_modify(DLIList<BodySM*> &old_sms);
+  void push_named_attributes_to_curves_and_points(DLIList<TopologyBridge*> &tb_list, const char *name_in);
   void remove_imprint_attributes_after_modify(DLIList<BodySM*> &body_sms,
                                               DLIList<BodySM*> &new_sms);
+
+  //! draw a preview of a plane for webcut previews
+  static void plane_preview(DLIList<Body*> &body_list,
+                            const CubitVector &pt1,
+                            const CubitVector &pt2,
+                            const CubitVector &pt3);
+
+  void propagate_from_small_edge( RefEdge *edge,
+                                  DLIList<RefEdge*> &small_edges,
+                                  DLIList<RefFace*> &narrow_faces,
+                                  DLIList<RefFace*> &processed_faces,
+                                  double small_edge_length);
+  void propagate_over_narrow_face( RefFace *narrow_face,
+                                   RefEdge *edge,
+                                   DLIList<RefFace*> &processed_faces,
+                                   DLIList<RefEdge*> &small_edges,
+                                   DLIList<RefFace*> &narrow_faces,
+                                   double small_edge_length);
+
+  static CubitStatus prepare_for_copy( RefEntity *ref_ents,
+                                       TopologyBridge *&top_bridge );
+
+  static CubitStatus finish_copy( TopologyBridge *&new_bridge,
+                                  TopologyBridge *old_bridge );
+
+  CubitStatus sweep_finish( const char* const sweep_function_name,
+                            DLIList<Body*>& input_body_list,
+                            DLIList<BodySM*>& new_body_list,
+                            DLIList<Body*>& output_body_list,
+                            CubitBoolean restore_newids );
+    //- Common cleanup code for sweep functions
+    //I sweep_function_name
+    //I- Name to use in error messages.
+    //I input_body_list
+    //I- Bodies that may need to be updated.
+    //I new_body_list
+    //I- SMbodies returned by GeometryModifyEngine
+    //I output_body_list
+    //I- ref_bodies returned by GeometryModifyEngine
+    //I restore_newids
+    //I- Passed back from sweep_setup -- restore setting state.
+
+  CubitStatus finish_webcut( DLIList<Body*>& input_bodies,
+                             DLIList<BodySM*>& webcut_results,
+                             CubitBoolean merge,
+                             CubitStatus webcut_status,
+                             DLIList<Body*>& new_bodies,
+                             DLIList<int> *merged_surface_ids = NULL,
+                             DLIList<int> *merged_curve_ids = NULL,
+                             CubitBoolean print_info = CUBIT_TRUE ) const;
+    //- Helper function for all webcut functions.
+    //- Finish up DAG update, merging, etc. after GME does webcut.
+    //I input_bodies
+    //I- The list of bodies that were webcut
+    //I webcut_results
+    //I- The new bodies returned by the GME webcut.
+    //I merge
+    //I- Merge after webcut
+    //I webcut_status
+    //I- The return value from the GME webcut function
+    //O new_bodies
+    //O- The new Bodies constructed from the passed BodySMs.
+    //R CubitStatus
+    //R- CUBIT_FAILURE on error, webcut_status on success.
+    //- Does separate_body_after_webcut for all bodies if
+    //- webcut_status == CUBIT_SUCCESS
+    //- Merges bodies if webcut_status == CUBIT_SUCCESS AND merge == CUBIT_TRUE
+
+  CubitStatus tweak_remove( DLIList<RefFace*> &ref_face_list,
+                            DLIList<Body*> &new_body_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 extend the adjoining
+    *   surfaces to fill the gap or remove the hole.  Only called by
+    *   tweak_remove_individually, tweak_remove_together.
+    */
+
+  void get_neighboring_bodies( DLIList<Body*> &input_bodies,
+                               DLIList<Body*> &neighboring_bodies );
+
+
+  CubitStatus unite_separately( GeometryModifyEngine *gme_ptr,
+                                DLIList<Body*> &body_list,
+                                DLIList<Body*> &new_body_list,
+                                bool keep_old );
+  CubitStatus unite_all( GeometryModifyEngine *gme_ptr,
+                         DLIList<Body*> &body_list,
+                         DLIList<Body*> &new_body_list,
+                         bool keep_old );
+  /**<  Private functions called to unite bodies.  First form separates the
+    *   body list into sheets & solids and unites each group together 
+    *   separately.  Second one unites all bodies together (including sheets
+    *   & solids.
+    */
+
+  CubitStatus unite_private( GeometryModifyEngine *gme_ptr,
+                             DLIList<Body*> &body_list,
+                             DLIList<Body*> &new_body_list,
+                             bool keep_old );
+  /**<  Private lower level function called to unite bodies
+    */
+
+
+  static CubitStatus clean_up_from_copy_failure( TopologyBridge *old_bridge );
+
+  GeometryModifyEngine * pull_common_surfs( DLIList<RefFace*> &ref_face_list,
+                                            DLIList<RefFace*> &common_face_list,
+                                            DLIList<Surface*> &common_surf_list );
+    /**< Pull RefFaces with a common GeometryModifyEngine out of the input
+      *  ref_face_list.  Place their surfaces in the output RefFace and Surface
+      *  lists, and return the common modify engine.  Note the function returns
+      *  a NULL pointer if a RefFace without a modify engine is found in the
+      *  input list.
+      */
+
 };
 
 inline void GeometryModifyTool::set_all_edges_imprint( CubitBoolean flag )
@@ -1618,13 +2179,15 @@
 inline CubitBoolean GeometryModifyTool::get_all_edges_imprint()
 {return allEdgesImprint;}
 
-// added by Lingyun Pan, Cat
 inline CubitBoolean GeometryModifyTool::boolean_regularize()
 {return booleanRegularize;}
-
 inline void GeometryModifyTool::boolean_regularize(CubitBoolean flag)
-{booleanRegularize= flag;}
+{booleanRegularize = flag;}
 
+inline CubitBoolean GeometryModifyTool::unite_mixed_models()
+{return uniteMixedModels;}
+inline void GeometryModifyTool::unite_mixed_models(CubitBoolean flag)
+{uniteMixedModels = flag;}
 
 inline void GeometryModifyTool::add_gme(GeometryModifyEngine *gme_ptr)
 {

Modified: cgm/branches/cubit/geom/GeometryQueryEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/GeometryQueryEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryQueryEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -39,3 +39,7 @@
 CubitStatus GeometryQueryEngine::get_underlying_surfaces(Surface * surf_ptr,
                                  DLIList<TopologyBridge*>& surf_list)
 { return CUBIT_SUCCESS; }
+
+CubitStatus GeometryQueryEngine::get_underlying_bridges(TopologyBridge* bridge_ptr,
+                                 DLIList<TopologyBridge*>& bridge_list)
+{ return CUBIT_SUCCESS; }

Modified: cgm/branches/cubit/geom/GeometryQueryEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/GeometryQueryEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryQueryEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -28,8 +28,10 @@
 class GMem;
 
 class TopologyBridge;
+class TopologyEntity;
 class GeometryEntity;
 class BodySM;
+class Lump; 
 class Surface;
 class Curve;
 class Point;
@@ -39,41 +41,43 @@
 
 public:
 
+    //!- virtual destructor
   virtual ~GeometryQueryEngine() {}
-    //- virtual destructor
 
+     //!R CubitStatus
+     //!R- CUBIT_SUCCESS/CUBIT_FAILURE
+     //!I ref_entity_list
+     //!I- A list of RefEntities to be exported or saved to a file.
+     //!I file_name
+     //!I- The name of the file to write to.
+     //!I file_type
+     //!I- An optional type of file.
+     //!- Export the current CUBIT geometry (everything in the Model) to a
+     //!- solid model format. Valid file types are:
+     //!-    "ACIS_SAT"    --  ACIS ASCII (SAT) file format
+     //!-    "ACIS_SAB"    --  ACIS BINARY (SAB) file format
+     //!-    "ACIS_DEBUG"  --  ACIS ASCII debug format
+     //!-    "IGES"        --  IGES file
+     //!-    "STEP"        --  STEP file
+     //!I logfile_name
+     //!I- Optional - name of logfile.
+     //!- No logfile gets created for SAB/SAT files, but for IGES and
+     //!- STEP file a logfile always gets created.  Default filenames
+     //!- are assigned if one is not given (iges_export.log, step_export.log).
+     //!-
+     //!- The function returns CUBIT_FAILURE if anything goes wrong with
+     //!- export - improper file type, inaccessible file, mismatch between
+     //!- the underlying representation and file type. It returns
+     //!- CUBIT_SUCCESS if everything goes well.
       virtual CubitStatus export_solid_model(
                                    DLIList<TopologyBridge*>& bridge_list,
                                    const char* file_name,
                                    const char* file_type,
                                    const CubitString &cubit_version,
                                    const char* logfile_name = NULL ) = 0;
-     //R CubitStatus
-     //R- CUBIT_SUCCESS/CUBIT_FAILURE
-     //I ref_entity_list
-     //I- A list of RefEntities to be exported or saved to a file.
-     //I file_name
-     //I- The name of the file to write to.
-     //I file_type
-     //I- An optional type of file.
-     //- Export the current CUBIT geometry (everything in the Model) to a
-     //- solid model format. Valid file types are:
-     //-    "ACIS_SAT"    --  ACIS ASCII (SAT) file format
-     //-    "ACIS_SAB"    --  ACIS BINARY (SAB) file format
-     //-    "ACIS_DEBUG"  --  ACIS ASCII debug format
-     //-    "IGES"        --  IGES file
-     //-    "STEP"        --  STEP file
-     //I logfile_name
-     //I- Optional - name of logfile.
-     //- No logfile gets created for SAB/SAT files, but for IGES and
-     //- STEP file a logfile always gets created.  Default filenames
-     //- are assigned if one is not given (iges_export.log, step_export.log).
-     //-
-     //- The function returns CUBIT_FAILURE if anything goes wrong with
-     //- export - improper file type, inaccessible file, mismatch between
-     //- the underlying representation and file type. It returns
-     //- CUBIT_SUCCESS if everything goes well.
-
+    
+     //! Saves out a temporary geometry file.  Entities in list must all be 
+     //! of same modeling engine.
      virtual CubitStatus save_temp_geom_file(
                                  DLIList<TopologyBridge*> &ref_entity_list,
                                  const char *filename,
@@ -81,12 +85,40 @@
                                  CubitString &created_file,
                                  CubitString &created_file_type ) = 0;
 
+     //! Imports entities into CGM from file that was embedded in a cub file.  
+     //! This file is could an ACIS, granite, catia, or another supported
+     //! solid modeling engine file.
      virtual CubitStatus import_temp_geom_file(
                                  FILE* file_ptr,
                                  const char* file_name,
                                  const char* file_type,
                                  DLIList<TopologyBridge*> &bridge_list  ) = 0;
 
+     //!R CubitStatus
+     //!R- CUBIT_SUCCESS/CUBIT_FAILURE
+     //!I file_ptr
+     //!I- A pointer to the file to read (can be NULL for IGES and STEP files).
+     //!I file_type
+     //!I- Type of file.
+     //!- Reads in geometry and creates the necessary Reference entities
+     //!- associated with the input geometry.
+     //!- Valid file types are:
+     //!-    "ACIS_SAT"    --  ACIS ASCII (SAT) file format
+     //!-    "ACIS_SAB"    --  ACIS BINARY (SAB) file format
+     //!-    "IGES"        --  IGES file
+     //!-    "STEP"        --  STEP file
+     //!I heal_step - auto-healing of step bodies on import.  This is recommended
+     //!              because they always need it.
+     //!I import_bodies (etc...)
+     //!I- Should bodies be import.
+     //!- Function can selectively import solid bodies, free surfaces, free
+     //!- curves, or free vertices.  For example, the user may not want
+     //!- to import any free entities.
+     //!-
+     //!- The function returns CUBIT_FAILURE if anything goes wrong with
+     //!- import - improper file type, inaccessible file, mismatch between
+     //!- the underlying representation and file type. It returns
+     //!- CUBIT_SUCCESS if everything goes well.
      virtual CubitStatus import_solid_model(
                                 const char* file_name,
                                 const char* file_type,
@@ -100,31 +132,6 @@
                                 bool import_vertices = true,
                                 bool free_surfaces = true
 					                      ) = 0;
-     //R CubitStatus
-     //R- CUBIT_SUCCESS/CUBIT_FAILURE
-     //I file_ptr
-     //I- A pointer to the file to read (can be NULL for IGES and STEP files).
-     //I file_type
-     //I- Type of file.
-     //- Reads in geometry and creates the necessary Reference entities
-     //- associated with the input geometry.
-     //- Valid file types are:
-     //-    "ACIS_SAT"    --  ACIS ASCII (SAT) file format
-     //-    "ACIS_SAB"    --  ACIS BINARY (SAB) file format
-     //-    "IGES"        --  IGES file
-     //-    "STEP"        --  STEP file
-     //I heal_step - auto-healing of step bodies on import.  This is recommended
-     //              because they always need it.
-     //I import_bodies (etc...)
-     //I- Should bodies be import.
-     //- Function can selectively import solid bodies, free surfaces, free
-     //- curves, or free vertices.  For example, the user may not want
-     //- to import any free entities.
-     //-
-     //- The function returns CUBIT_FAILURE if anything goes wrong with
-     //- import - improper file type, inaccessible file, mismatch between
-     //- the underlying representation and file type. It returns
-     //- CUBIT_SUCCESS if everything goes well.
 
       virtual CubitStatus get_underlying_curves(Curve * curve_ptr,
                                  DLIList<TopologyBridge*>& curve_list)  ;
@@ -132,6 +139,8 @@
       // - curves from virtual curves.
       virtual CubitStatus get_underlying_surfaces(Surface * surf_ptr,
                                  DLIList<TopologyBridge*>& surf_list)  ;
+      virtual CubitStatus get_underlying_bridges(TopologyBridge* bridge_ptr,
+                                 DLIList<TopologyBridge*>& bridge_list);
 
       virtual CubitStatus get_intersections(
                                     Curve* ref_edge1, CubitVector& point1,
@@ -185,24 +194,29 @@
       //- on those entities. Supports vertices, curves, surfaces, volumes and bodies.
 
       virtual void delete_solid_model_entities(DLIList<BodySM*>& body_list) const = 0;
-  virtual CubitStatus delete_solid_model_entities( BodySM* body_ptr ) const = 0;
-  virtual CubitStatus delete_solid_model_entities(Surface* surf_ptr ) const = 0;
-  virtual CubitStatus delete_solid_model_entities( Curve* curve_ptr ) const = 0;
-  virtual CubitStatus delete_solid_model_entities( Point* point_ptr ) const = 0;
+      virtual CubitStatus delete_solid_model_entities( BodySM* body_ptr ) const = 0;
+      virtual CubitStatus delete_solid_model_entities(Surface* surf_ptr ) const = 0;
+      virtual CubitStatus delete_solid_model_entities( Curve* curve_ptr ) const = 0;
+      virtual CubitStatus delete_solid_model_entities( Point* point_ptr ) const = 0;
       //- Deletes the solid model entities associcated with the input
       //- free-floating RefEntity. If the input RefEntity is not free-floating,
       //- then its underlying ACIS ENTITYs are not deleted and CUBIT_FAILURE
       //- is returned.
       //- Returns CUBIT_SUCCESS if all went well, otherwise, CUBIT_FAILURE.
 
-      virtual CubitStatus fire_ray(BodySM *body,
-                                   const CubitVector &ray_start_point,
-                                   const CubitVector &unit_direction,
-                                   DLIList<double> &ray_params,
-                                   DLIList<GeometryEntity*> *entity_list = NULL
-                                   ) const = 0;
-      //- fire a ray at the specified body, returning the entities hit and
-      //- the parameters along the ray; return CUBIT_FAILURE 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 = 0;
+    //- 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.  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 get_isoparametric_points(Surface* ref_face_ptr,
                                                int &nu, int &nv,
@@ -226,6 +240,9 @@
     //O vector showning transform.
     //O-Computes the transform from the transformed body.
 
+  virtual int curve_is_on_ignored_surface(Curve *curve,
+                    Surface *surf) { return 0; }
+
   virtual const char* modeler_type() = 0;
   virtual int get_major_version() = 0;
   virtual int get_minor_version() = 0;
@@ -251,9 +268,6 @@
    //- Set solid modeler options
 
   virtual CubitStatus get_graphics( Surface* surface_ptr,
-                                    int& number_of_triangles,
-                                    int& number_of_points,
-                                    int& number_of_facets,
                                     GMem* gMem,
                                     unsigned short normal_tolerance=15,
                                     double distance_tolerance=0,
@@ -263,19 +277,13 @@
     //I ref_face_ptr
     //I- The RefFAce for which hoops facetting information will be
     //I- gathered.
-    //O- The number of polygons (triangles) needed for facetting.
-    //O number_points
-    //O- The number of points needed for facetting
-    //O number_Facets
-    //O- The number of facets needed for facetting.
     //O gMem
     //O- The sturage place for facets (and points).
-    //= This function gathersw and outputs ACIS facet (and point)
+    //= This function gathers and outputs ACIS facet (and point)
     //- information for hoops involved in facetting an RefFace.  If
     //- all goes well, CUBIT_Success is retuned.
 
   virtual CubitStatus get_graphics( Curve* curve_ptr,
-                                    int& num_points,
                                     GMem* gMem = NULL,
                                     double tolerance = 0.0 ) const = 0;
     //R CubitStatus
@@ -310,6 +318,10 @@
   virtual CubitBoolean bodies_overlap (BodySM *body_ptr_1,
                                        BodySM *body_ptr_2 ) const = 0;
 
+  virtual CubitBoolean volumes_overlap (Lump *lump1, Lump *lump2 ) const = 0; 
+
+  virtual TopologyBridge* get_visible_entity_at_point(TopologyBridge* hidden_tb, CubitVector* point){return NULL;};
+
    protected:
 
    private:

Modified: cgm/branches/cubit/geom/GeometryQueryTool.cpp
===================================================================
--- cgm/branches/cubit/geom/GeometryQueryTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryQueryTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -9,14 +9,15 @@
 #include "ProgressTool.hpp"
 #include "GeometryDefines.h"
 #include "GeometryEntity.hpp"
+#include "GeomMeasureTool.hpp"
 #include "GeometryQueryTool.hpp"
+#include "GeometryModifyTool.hpp"
 #include "AnalyticGeometryTool.hpp"
 #include "MergeTool.hpp"
 #include "GeometryQueryEngine.hpp"
 #include "DAG.hpp"
 #include "TBOwnerSet.hpp"
 
-
 #include "RefEntity.hpp"
 #include "RefEntityFactory.hpp"
 #include "BasicTopologyEntity.hpp"
@@ -73,10 +74,19 @@
 #include "ModelQueryEngine.hpp"
 
 #include "CubitTransformMatrix.hpp"
+#include "CubitUndo.hpp"
+#include "GMem.hpp"
+#include "IntersectionTool.hpp"
 
-double GeometryQueryTool::geometryToleranceFactor = 500.0;
+#include "GfxPreview.hpp" //DJQ
+#include "GfxDebug.hpp" //DJQ
+
+double GeometryQueryTool::geometryToleranceFactor = DEFAULT_GEOM_FACTOR;
 GeometryQueryTool* GeometryQueryTool::instance_ = 0;
 CubitBoolean GeometryQueryTool::useFacetBBox = CUBIT_FALSE;
+CubitBoolean GeometryQueryTool::trackMergedAwayEnts = CUBIT_FALSE;
+DLIList<int> GeometryQueryTool::uidsOfImportingEnts;
+int GeometryQueryTool::entitiesMergedAway = 0;
 
 const int GeometryQueryTool::CGM_MAJOR_VERSION = 10;
 const int GeometryQueryTool::CGM_MINOR_VERSION = 0;
@@ -86,12 +96,13 @@
   CubitBoolean GeometryQueryTool::bboxMergeTest = CUBIT_TRUE;
   int GeometryQueryTool::internalSurfaceMergeTest = 2; // 0=off, 1=all, 2=splines only
 #else
+//test
   // Cat prefers to avoid internal checks altogether as they cause problems with splines
   CubitBoolean GeometryQueryTool::bboxMergeTest = CUBIT_FALSE;
   int GeometryQueryTool::internalSurfaceMergeTest = 0; // 0=off, 1=all, 2=splines only
 #endif // ndef CAT
 
-double GeometryQueryTool::curveSliverCleanUpTolerance = geometryToleranceFactor*GEOMETRY_RESABS ; 
+double GeometryQueryTool::curveSliverCleanUpTolerance = geometryToleranceFactor*GEOMETRY_RESABS ;
 double GeometryQueryTool::surfaceSliverCleanUpTolerance = -1.0;
 
 // static CubitStatus import_actuate(DLIList<RefEntity*> &entity_list);
@@ -158,7 +169,6 @@
 GeometryQueryTool::~GeometryQueryTool ()
 {
 
-
   //Kill the geometry query engine(s).
    int i;
    for (i = gqeList.size(); i > 0; i--)
@@ -168,59 +178,24 @@
    gqeList.clean_out();
 
    instance_ = NULL;
-
 }
 
 //-------------------------------------------------------------------------
-// Purpose       : Reads a geometry file (named fileName).  If the file
-//                 cannot be found in the current directory, and if includePath
-//                 is not NULL, the include path specified by includePath is
-//                 added to the file name, and it is searched in the given
-//                 order. The file type specified in the "type" argument
-//                 determines what type of geometry file it is -- the default
-//                 is an ACIS SAT file.
+// Purpose       : Function to delete instance variable
 //
 // Special Notes :
 //
-// Creator       : Xuechen Liu
+// Creator       : Corey Ernst
 //
-// Creation Date : 07/11/96
+// Creation Date : 12/31/07
 //-------------------------------------------------------------------------
-CubitStatus GeometryQueryTool::read_geometry_file(char const* fileName,
-                                             const char* includePath,
-                                             const char* type)
+void GeometryQueryTool::delete_instance()
 {
-   CubitStatus result = CUBIT_SUCCESS;
-
-   FILE* file = fopen(fileName, "r");
-
-     // If the file is not in the current directory, add a path to it.
-   CubitString file_and_path;
-   if (!file && includePath)
-   {
-      file_and_path = includePath;
-      file_and_path += CubitString("/");
-      file_and_path += CubitString(fileName);
-      file = fopen(file_and_path.c_str(), "r");
-   }
-   else
-     file_and_path = fileName;
-
-     // If the file is opened successfully.
-   if (file)
-   {
-     fclose(file);
-     result = import_solid_model(file_and_path.c_str(), type);
-     if (result != CUBIT_SUCCESS)
-       PRINT_ERROR("The specified file type is not supported!\n");
-   }
-   else
-   {
-      PRINT_ERROR("Cannot open geometry file: %s .\n", fileName);
-      result = CUBIT_FAILURE;
-   }
-
-   return result;
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
 }
 
 //-------------------------------------------------------------------------
@@ -240,7 +215,7 @@
                                              std::list<CubitString> &types_written)
 {
   int i;
-
+// clear all attributes
   if (ref_entity_list.size() == 0) {
 
       // All bodies are to be exported
@@ -508,97 +483,320 @@
 }
 
 //-------------------------------------------------------------------------
-// Purpose       : Fire a ray and see which entities it hits
+// Purpose       : Fire a ray at a list of entities and return the
+//                 parameters along the ray (distance from origin of ray)
+//                 where it hits the entities; optionally find the
+//                 corresponding entities it hit.
 //
 // Special Notes :
 //
-// Creator       : Tim Tautges (this wrapper function added by
-//                              Brett Clark)
+// Creator       : Steve Storm
 //
-// Creation Date : 3/18/97
+// Creation Date : 3/29/2007
 //-------------------------------------------------------------------------
+CubitStatus GeometryQueryTool::fire_ray( CubitVector &origin,
+                                         CubitVector &direction,
+                                         DLIList<RefEntity*> &at_entity_list,
+                                         DLIList<double> &ray_params,
+                                         int max_hits,
+                                         double ray_radius,
+                                         DLIList<RefEntity*> *hit_entity_list_ptr )
+{
+  int i;
 
-int GeometryQueryTool::fire_ray(Body* body,
-                           const CubitVector ray_point,
-                           const CubitVector unit,
-                           DLIList<double>& ray_params,
-                           DLIList<RefEntity*> *entity_list)
-{
-  BodySM* bodysm = body->get_body_sm_ptr();
-  if (bodysm == NULL)
+  // Do this in a way to account for the case if they happen to be from
+  // different geometry engines (could easily occur with virtual geometry)
+
+  DLIList<TopologyEntity*> te_fire_at_list;
+  DLIList<TopologyEntity*> te_hit_entity_list;
+  DLIList<TopologyEntity*> *te_hit_entity_list_ptr = 0;
+  if( hit_entity_list_ptr )
+    te_hit_entity_list_ptr = &te_hit_entity_list;
+
+  GeometryQueryEngine *gqe = 0;
+  GeometryQueryEngine *gqe_last = 0;
+  RefEntity *ref_entity_ptr;
+  TopologyEntity *topo_ptr;
+
+  int loc_max_hits = max_hits;
+  CubitBoolean hits_limited = CUBIT_FALSE;
+  if( max_hits > 0 )
+    hits_limited = CUBIT_TRUE;
+
+  // Note we care about order
+  at_entity_list.reset();
+  for( i=at_entity_list.size(); i--; )
   {
-    PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n", body->id());
-    return 0;
+    ref_entity_ptr = at_entity_list.get_and_step();
+
+    topo_ptr = CAST_TO( ref_entity_ptr, TopologyEntity );
+    if( !topo_ptr )
+    {
+      PRINT_ERROR( "Couldnt get topo_ptr\n" );
+      continue;
+    }
+
+    gqe = topo_ptr->get_geometry_query_engine();
+    if( !gqe )
+    {
+      PRINT_ERROR( "Unable to find geometry engine associated with an entity!\n" );
+      return CUBIT_FAILURE;
+    }
+
+    if( !gqe_last ) gqe_last = gqe;
+    if( gqe != gqe_last )
+    {
+      if( hits_limited == CUBIT_TRUE )
+      {
+        loc_max_hits = max_hits - ray_params.size();
+        if( loc_max_hits <= 0 )
+          break;
+      }
+
+      if( fire_ray( origin, direction, te_fire_at_list, ray_params,
+        loc_max_hits, ray_radius, te_hit_entity_list_ptr ) == CUBIT_FAILURE )
+        return CUBIT_FAILURE;
+
+      // Reset
+      gqe_last = gqe;
+      te_fire_at_list.clean_out();
+    }
+
+    te_fire_at_list.append( topo_ptr );
   }
 
-  DLIList<GeometryEntity*>* geom_list = NULL;
-  if (entity_list)
-    geom_list = new DLIList<GeometryEntity*>;
+  // Do the last ray fire, if necessary
+  if( hits_limited == CUBIT_TRUE )
+    loc_max_hits = max_hits - ray_params.size();
+  if( hits_limited==CUBIT_FALSE || loc_max_hits>0 )
+    if( fire_ray( origin, direction, te_fire_at_list, ray_params,
+      loc_max_hits, ray_radius, te_hit_entity_list_ptr ) == CUBIT_FAILURE )
+      return CUBIT_FAILURE;
 
-  int rval = bodysm->get_geometry_query_engine()->
-    fire_ray(bodysm, ray_point, unit, ray_params, geom_list );
+  if( hit_entity_list_ptr )
+  {
+    // Find RefEntities from TopologyEntities
+    te_hit_entity_list.reset();
+    for( i=te_hit_entity_list.size(); i--; )
+    {
+      topo_ptr = te_hit_entity_list.get_and_step();
+      if( !topo_ptr )
+      {
+        hit_entity_list_ptr->append( 0 );
+        continue;
+      }
 
-  if (geom_list)
+      ref_entity_ptr = CAST_TO( topo_ptr, RefEntity );
+      hit_entity_list_ptr->append( ref_entity_ptr );
+    }
+  }
+
+  // Now, make sure we don't have more hits than asked for
+  if( hits_limited == CUBIT_TRUE )
   {
-    geom_list->reset();
-    for (int i = geom_list->size(); i--; )
+    if( ray_params.size() <= max_hits )
+      return CUBIT_SUCCESS;
+
+    for( i=ray_params.size()-max_hits; i--; )
     {
-      TopologyEntity* topo_ent = entity_from_bridge(geom_list->get_and_step());
-      RefEntity* ref_ent = dynamic_cast<RefEntity*>(topo_ent);
-      if (ref_ent)
-        entity_list->append(ref_ent);
+      ray_params.last();
+      ray_params.remove();
+      if( hit_entity_list_ptr )
+      {
+        hit_entity_list_ptr->last();
+        hit_entity_list_ptr->remove();
+      }
     }
-    delete geom_list;
   }
 
-  return rval ;
+  return CUBIT_SUCCESS;
 }
 
-CubitStatus GeometryQueryTool::import_temp_geom_file(FILE* file_ptr,
-						     const char* file_type )
+//-------------------------------------------------------------------------
+// Purpose       : Fire a ray at a list of entities and return the
+//                 parameters along the ray (distance from origin of ray)
+//                 where it hits the entities; optionally find the
+//                 corresponding entities it hit.
+//
+// Special Notes : All entities must be from the same geometry engine.
+//
+// Creator       : Steve Storm
+//
+// Creation Date : 5/19/2007
+//-------------------------------------------------------------------------
+CubitStatus GeometryQueryTool::fire_ray( CubitVector &origin,
+                                         CubitVector &direction,
+                                         DLIList<TopologyEntity*> &at_entity_list,
+                                         DLIList<double> &ray_params,
+                                         int max_hits,
+                                         double ray_radius,
+                                         DLIList<TopologyEntity*> *hit_entity_list_ptr )
 {
-    // reset the attribImporteds flags to facilitate attribute reporting
-//  CubitAttrib::clear_attrib_importeds();
+  if( !at_entity_list.size() )
+    return CUBIT_SUCCESS;
 
-    // Use the default MQE to import a list of ToplogyBridges from the file.
-  gqeList.reset();
-  DLIList<TopologyBridge*> bridge_list;
-  GeometryQueryEngine *gqe;
 
+  TopologyEntity *topo_ptr = at_entity_list.get();
+
+  GeometryQueryEngine *gqe = topo_ptr->get_geometry_query_engine();
+  if( !gqe )
+  {
+    PRINT_ERROR( "Unable to find geometry engine associated with an entity!\n" );
+    return CUBIT_FAILURE;
+  }
+
+
+  DLIList<TopologyBridge*> tb_list;
   int i;
-  CubitStatus status = CUBIT_FAILURE;
-  for(i=gqeList.size(); i--; )
+  at_entity_list.reset();
+  for( i=at_entity_list.size(); i--; )
   {
-    gqe = gqeList.get_and_step();
-    status = gqe->import_temp_geom_file( file_ptr, "dummy",file_type, bridge_list );
-    if( status == CUBIT_SUCCESS ) //done...get out
-      break;
+    topo_ptr = at_entity_list.get_and_step();
+    DLIList<TopologyBridge*> bridge_list;
+    topo_ptr->bridge_manager()->get_bridge_list( bridge_list );
+    bridge_list.reset();
+    tb_list.append( bridge_list.get() );
   }
 
-  if( bridge_list.size() == 0 )
-    return status;
+  // Setup temporary variables to pass
+  DLIList<double> tmp_ray_params;
 
+  DLIList<TopologyBridge*> tb_hit_list;
+  DLIList<TopologyBridge*> *tb_hit_list_ptr = NULL;
+  if( hit_entity_list_ptr )
+    tb_hit_list_ptr = &tb_hit_list;
 
-  for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
-    (*itor)->import_geometry(bridge_list);
+  // Do the ray fire.  Note we will sort the hits by distance and append to the output lists.
+  if( gqe->fire_ray( origin, direction, tb_list, tmp_ray_params,
+    max_hits, ray_radius, tb_hit_list_ptr ) == CUBIT_FAILURE )
+    return CUBIT_FAILURE;
 
-  DLIList<RefEntity*> dummy_list;
-  status = construct_refentities(bridge_list, &dummy_list);
+  tmp_ray_params.reset();
+  if( tb_hit_list_ptr) tb_hit_list_ptr->reset();
 
-    // report attribs imported
-//  CubitAttrib::report_attrib_importeds();
+  // Append to output lists
+  ray_params += tmp_ray_params;
 
-    // now return
-  return status;
+  // Get the TE's from the TopologyBridges
+  if( hit_entity_list_ptr )
+  {
+	  // First need to make sure that the entities hit are visible...entities hit
+	  // may be hidden under virtual entities....we need to get the visible
+	  // entities.
+	  DLIList<TopologyBridge*> vis_tb_hit_list;
+	  DLIList<CubitVector*> cv_list;
+
+	  CubitVector *loc_ptr;
+	  double param;
+	  tmp_ray_params.reset();
+	  for( i=tmp_ray_params.size(); i--; )
+	  {
+		  param = tmp_ray_params.get_and_step();
+
+		  loc_ptr = new CubitVector;
+		  origin.next_point( direction, param, *loc_ptr );
+		  cv_list.append( loc_ptr );
+	  }
+
+
+	  TopologyBridge *bridge_ptr;
+	  TopologyBridge *tb_owner = 0;
+	  for( i=0; i<tb_hit_list_ptr->size(); i++ )
+	  {
+		  bool added_entity = false;
+		  bridge_ptr = tb_hit_list_ptr->get_and_step();
+
+		  TopologyBridge *visible_tb = NULL;
+		  TBOwner* o2 = bridge_ptr->owner();
+
+		  bool broke_early = false;
+		  BridgeManager* bridge_manager2;
+		  while (!(bridge_manager2 = dynamic_cast<BridgeManager*>(o2)))
+		  {
+			  if (TopologyBridge* bridge2 = dynamic_cast<TopologyBridge*>(o2))
+			  {
+				  GeometryQueryEngine* gqe2 = bridge2->get_geometry_query_engine();
+
+				  //Let the VQE handle the work
+				  visible_tb = gqe2->get_visible_entity_at_point(bridge_ptr, cv_list[i]);
+				  if (visible_tb)
+					  o2 = visible_tb->owner();
+				  else
+					  o2 = bridge2->owner();
+			  }
+
+			  else if(TBOwnerSet* set = dynamic_cast<TBOwnerSet*>(o2))
+			  {
+				  DLIList<TopologyBridge*> list2;
+				  set->get_owners(list2);
+				  list2.reset();
+
+				  // This had better be the Virtual QE.
+				  GeometryQueryEngine* gqe2 = list2.get()->get_geometry_query_engine();
+
+				  //Let the VQE handle the work
+				  visible_tb = gqe2->get_visible_entity_at_point(bridge_ptr, cv_list[i]);
+				  if (visible_tb)
+					  o2 = visible_tb->owner();
+				  else
+				  {
+					  broke_early = true;
+					  break;
+				  }
+			  }
+			  else
+			  {
+				  broke_early = true;
+				  break;
+			  }
+		  }
+
+		  if (!broke_early)
+			  visible_tb = bridge_manager2->topology_bridge();
+
+
+		  if( visible_tb )
+		  {
+			  topo_ptr = visible_tb->topology_entity();
+			  hit_entity_list_ptr->append( topo_ptr );
+		  }
+		  else
+			  hit_entity_list_ptr->append( 0 );
+	  }
+
+
+	  // Free memory
+	  while( cv_list.size() ) delete cv_list.pop();
+  }
+
+  // Sort ray_params (low to high) and sort hit_entity_list_ptr 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)
+  std::map<double, TopologyEntity*> temp_map;
+  for (i=0; i<ray_params.size(); i++)
+	  temp_map.insert(std::map<double, 
+    TopologyEntity*>::value_type( ray_params.get_and_step(), 
+    hit_entity_list_ptr ? hit_entity_list_ptr->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_ptr) hit_entity_list_ptr->clean_out();
+
+  std::map<double, TopologyEntity*>::iterator iter;
+  for (iter=temp_map.begin(); iter != temp_map.end(); iter++)
+  {
+	  ray_params.append(iter->first);
+	  if( hit_entity_list_ptr) hit_entity_list_ptr->append(iter->second);
+  }
+
+	return CUBIT_SUCCESS;
 }
 
-
 //-------------------------------------------------------------------------
-// Purpose       : Reads in geometry in geometry and creates
-//                 the necessary Reference entities associated with the
-//                 input geometry. Has ability to read selectively read
-//                 in either bodies, free surfaces, free curves or free
-//                 vertices from the file.
+// Purpose       : Reads in geometry and creates the necessary Reference
+//                 entities associated with the input geometry. Has ability
+//                 to read selectively read in either bodies, free surfaces,
+//                 free curves or free vertices from the file.
 //
 //                 Valid file types are:
 //                       "ACIS_SAT"    --  ACIS ASCII (SAT) file format
@@ -630,6 +828,9 @@
     return CUBIT_FAILURE;
   }
 
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state();
+
     // reset the attribImporteds flags to facilitate attribute reporting
 //  CubitAttrib::clear_attrib_importeds();
 
@@ -648,8 +849,26 @@
     (*itor)->import_geometry(bridge_list);
 
   bridge_list.reset();
-  status = construct_refentities(bridge_list, imported_entities);
+  DLIList<RefEntity*> tmp_ent_list;
+  status = construct_refentities(bridge_list, &tmp_ent_list);
 
+  if( imported_entities )
+    (*imported_entities) += tmp_ent_list;
+
+  if( CubitUndo::get_undo_enabled() )
+  {
+    if( tmp_ent_list.size() && status == CUBIT_SUCCESS )
+      CubitUndo::note_result_entities( tmp_ent_list );
+    else
+      CubitUndo::remove_last_undo();
+  }
+
+  //clear out all attributes that were set to actuate
+  DLIList<RefEntity*> all_ents;
+  RefEntity::get_all_child_ref_entities( tmp_ent_list, all_ents );
+  all_ents += tmp_ent_list;
+  CubitAttribUser::clear_all_simple_attrib_set_to_actuate( all_ents );
+
     // report attribs imported
 //  CubitAttrib::report_attrib_importeds();
 
@@ -707,7 +926,8 @@
     }
     else if( (surface_ptr = dynamic_cast<Surface*>(bridge_ptr) ) != NULL )
     {
-      RefFace* face_ptr = make_free_RefFace( surface_ptr );
+      bool is_free_face = true;
+      RefFace* face_ptr = make_free_RefFace( surface_ptr, is_free_face );
       if( face_ptr )
       {
         face_list.append( face_ptr );
@@ -975,11 +1195,23 @@
     body->id(), timer.cpu_secs() );
 
   if( body_created )
+  {
     CubitObserver::notify_static_observers( body, VGI_BODY_CONSTRUCTED );
+    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, body);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
   else if( body_modified )
+  {
     body->notify_all_observers( TOPOLOGY_MODIFIED );
+    CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, body);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
   else if( vol_modified )
+  {
     body->notify_all_observers( GEOMETRY_MODIFIED );
+    CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, body);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
 
   PRINT_DEBUG_3("Updated graphics for Body %d in %f seconds.\n",
     body->id(), timer.cpu_secs() );
@@ -1072,7 +1304,11 @@
   if (volume->deactivated())
     volume_modified = false;
   else if(!volume_created && volume_modified )
+  {
     volume->notify_all_observers( TOPOLOGY_MODIFIED );
+    CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, volume);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
 
   return volume;
 }
@@ -1295,9 +1531,19 @@
     // Get/construct RefFace for surface.
   bool face_created = false;
   bool face_modified = false;
+  bool face_modified2 = false;
   RefFace* face = CAST_TO( surface_ptr->topology_entity(), RefFace );
   if( !face )
+  {
     face = dynamic_cast<RefFace*>(check_mergeable_refentity(surface_ptr));
+
+    //Including this call in here in case the surface a composite and
+    //hidden curves need to be removed in the graphics.
+    if( face )
+    {
+      face_modified2 = true;
+    }
+  }
   if( !face )
   {
     face = RefEntityFactory::instance()->construct_RefFace(surface_ptr);
@@ -1527,7 +1773,19 @@
   }
 
   if( !face_created && face_modified && !face->deactivated() )
+  {
     face->notify_all_observers( GEOMETRY_TOPOLOGY_MODIFIED );
+    CGMHistory::Event evt2(CGMHistory::TOPOLOGY_CHANGED, face);
+    const_cast<CGMHistory&>(mHistory).add_event(evt2);
+    CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, face);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
+  else if(face_modified2)
+  {
+    face->notify_all_observers(TOPOLOGY_MODIFIED);
+    CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, face);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
 
   if (merged)
     MergeTool::instance()->set_merge_occurance(CUBIT_TRUE);
@@ -1557,8 +1815,8 @@
   if (num_bridges < 2) // isn't merged
     return CUBIT_FAILURE;
 
-    // Get some other Surface in merged RefFace to compare
-    // topology with.
+  // Get some other Surface in merged RefFace to compare
+  // topology with.
   DLIList<TopologyBridge*> bridge_list(num_bridges);
   face->bridge_manager()->get_bridge_list(bridge_list);
   bridge_list.reset();
@@ -1694,6 +1952,8 @@
         assert(curves.size() == 1);
         if (curves.get()->owner() != curve->owner())
         {
+          merge->bridge_manager()->remove_bridge(merged_coedge);
+          assert(merge->get_parents());
           merge = 0;
         }
       }
@@ -1783,6 +2043,7 @@
   bool reversed = (CUBIT_REVERSED == curve_ptr->bridge_sense());
   bool merged = edge->bridge_manager()->number_of_bridges() > 1;
 
+
     // Construct RefVertices
   DLIList<Point*> points(2);
   curve_ptr->points( points );
@@ -1833,8 +2094,22 @@
     points.last();
     if( points.get()->topology_entity() != end_vertex )
       merged = false;
+
+    //perhaps the bridge sense just needs to be swapped 
+    if( merged == false )
+    {
+      points.reverse();
+      points.reset();
+      Point *point1 = points.get_and_step();
+      Point *point2 = points.get_and_step();
+      if( point1->topology_entity() == start_vertex &&
+          point2->topology_entity() == end_vertex )
+      {
+        merged = true;
+        curve_ptr->reverse_bridge_sense();
+      }
+    }
   }
-
     // Unmerge the curve, if necessary.
   if( !merged && edge->bridge_manager()->number_of_bridges() > 1 )
   {
@@ -1859,6 +2134,7 @@
 
       // Create new RefEdge for un-merged curve
     edge = RefEntityFactory::instance()->construct_RefEdge( curve_ptr );
+    PRINT_WARNING("Creating edge %d that was supposed to be merged\n", edge->id() );
     edge_created = true;
 
       // If we had swapped the vertex order because the curve
@@ -1943,7 +2219,13 @@
   }
 
   if( !edge_created && edge_modified && !edge->deactivated() )
+  {
     edge->notify_all_observers( GEOMETRY_TOPOLOGY_MODIFIED );
+    CGMHistory::Event evt2(CGMHistory::TOPOLOGY_CHANGED, edge);
+    const_cast<CGMHistory&>(mHistory).add_event(evt2);
+    CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, edge);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
+  }
 
   if (merged)
     MergeTool::instance()->set_merge_occurance(CUBIT_TRUE);
@@ -1972,19 +2254,29 @@
 
   RefEntity *re_ptr = NULL;
 
-  if (csa_ptr != NULL) {
-
+  if (csa_ptr != NULL)
+  {
       // from the csa, call CAMP to get the partner, if one exists
       // (and return it)
     csa_ptr->int_data_list()->reset();
     int merge_id = *(csa_ptr->int_data_list()->get());
+
+    bool unique_append = false;
+    if( GeometryQueryTool::trackMergedAwayEnts )
+      unique_append = GeometryQueryTool::uidsOfImportingEnts.append_unique( merge_id );
+
     ToolDataUser *tdu = TDUniqueId::find_td_unique_id(merge_id);
     TopologyEntity *te = dynamic_cast<TopologyEntity*>(tdu);
 
     CubitSense sense = CAMergePartner::get_bridge_sense( csa_ptr );
 
     //We found the merge partner.....
-    if (te != NULL) {
+    if (te != NULL)
+    {
+      //it's the first time you found this uid and you found an entity
+      //
+      if(GeometryQueryTool::trackMergedAwayEnts && unique_append )
+        GeometryQueryTool::entitiesMergedAway++;
 
         // assume this merge attrib will be actuated, so remove the csa
       bridge->remove_simple_attribute_virt(csa_ptr);
@@ -2135,7 +2427,6 @@
        // Create a RefVertex from this Point.
      vertex = RefEntityFactory::instance()->construct_RefVertex(point);
    }
-
    assert(vertex != NULL);
 
    return vertex;
@@ -2153,7 +2444,8 @@
 //
 // Creation Date : 3/27/99
 //-------------------------------------------------------------------------
-RefFace* GeometryQueryTool::make_free_RefFace(Surface *surface_ptr ) const
+RefFace* GeometryQueryTool::make_free_RefFace(Surface *surface_ptr,
+                                              bool is_free_face ) const
 {
    RefFace* ref_face_ptr = make_RefFace( surface_ptr );
    if( !ref_face_ptr )
@@ -2163,9 +2455,14 @@
      return 0;
    }
 
-
    // Add the new ref_face to the graphics
-   ref_face_ptr->notify_all_observers( FREE_REF_ENTITY_GENERATED );
+   if( is_free_face )
+   {
+     ref_face_ptr->notify_all_observers( FREE_REF_ENTITY_GENERATED );
+     
+     CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, ref_face_ptr);
+     const_cast<CGMHistory&>(mHistory).add_event(evt);
+   }
 
    return ref_face_ptr;
 }
@@ -2191,6 +2488,9 @@
    }
 
    ref_edge_ptr->notify_all_observers( FREE_REF_ENTITY_GENERATED );
+   
+   CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, ref_edge_ptr);
+   const_cast<CGMHistory&>(mHistory).add_event(evt);
 
    return ref_edge_ptr;
 }
@@ -2217,6 +2517,9 @@
 
    // Add the new ref_vertex to the graphics
    ref_vertex_ptr->notify_all_observers( FREE_REF_ENTITY_GENERATED );
+   
+   CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, ref_vertex_ptr);
+   const_cast<CGMHistory&>(mHistory).add_event(evt);
 
    return ref_vertex_ptr;
 }
@@ -2275,6 +2578,8 @@
 {
   BodySM* bodysm = body_ptr->get_body_sm_ptr();
   DLIList<RefEntity*> merged_children;
+  DLIList<RefFace*> faces_to_reverse;
+  DLIList<RefEdge*> edges_to_reverse;
   if (!bodysm)
   {
     PRINT_ERROR("Body %d is invalid -- no attached BodySM.\n",body_ptr->id());
@@ -2304,6 +2609,49 @@
       }
     }
 
+//    if( tmp_merged_children.size() )
+//      MergeTool::instance()->unmerge( body_ptr );
+
+    //fix up merged children -- some might need to be reversed
+    for(i=merged_children.size(); i--; )
+    {
+      RefEntity *merged_child = merged_children.get_and_step();
+      BasicTopologyEntity *bte = static_cast<BasicTopologyEntity*>(merged_child);
+
+      //get the first bridge of the entity
+      DLIList<TopologyBridge*> child_bridge_list;
+      bte->bridge_manager()->get_bridge_list( child_bridge_list );
+      child_bridge_list.reset();
+      TopologyBridge *first_bridge = child_bridge_list.get_and_step();
+
+      //if it is not the body we're deleting just continue
+      BodySM *owning_body = first_bridge->bodysm();
+      if( owning_body != bodysm )
+        continue;
+
+      RefFace *ref_face = CAST_TO( merged_child, RefFace );
+      if( ref_face )
+      {
+        faces_to_reverse.append( ref_face );
+        continue;
+      }
+      RefEdge *ref_edge = CAST_TO( merged_child, RefEdge );
+      if( ref_edge )
+      {
+        //get merged_child's first topology bridge
+        TopologyBridge *second_bridge = child_bridge_list.get_and_step();
+
+        Curve *first_curve = CAST_TO( first_bridge, Curve );
+        Curve *second_curve = CAST_TO( second_bridge, Curve );
+
+        CubitSense relative_sense = first_curve->relative_sense( second_curve );
+
+        if( relative_sense == CUBIT_REVERSED )
+          edges_to_reverse.append( ref_edge );
+        continue;
+      }
+    }
+
       // Ask owning model engine to delete the TopologyBridges
     GeometryQueryEngine* gqe = bodysm->get_geometry_query_engine();
     gqe->delete_solid_model_entities(bodysm);
@@ -2314,11 +2662,24 @@
       (*itor)->clean_out_deactivated_geometry();
   }
 
+  int i;
+  for( i=faces_to_reverse.size(); i--; )
+    faces_to_reverse.get_and_step()->reverse_normal();
+  for( i=edges_to_reverse.size(); i--; )
+    edges_to_reverse.get_and_step()->reverse_tangent();
+
     //regenerate graphics of merged entities
-  int i;
   for( i=merged_children.size(); i--; )
-    merged_children.get_and_step()->notify_all_observers( GEOMETRY_MODIFIED );
+  {
+    RefEntity* child = merged_children.get_and_step();
+    child->notify_all_observers( GEOMETRY_TOPOLOGY_MODIFIED );
+    CGMHistory::Event evt2(CGMHistory::TOPOLOGY_CHANGED, child);
+    const_cast<CGMHistory&>(mHistory).add_event(evt2);
+    CGMHistory::Event evt(CGMHistory::GEOMETRY_CHANGED, child);
+    const_cast<CGMHistory&>(mHistory).add_event(evt);
 
+  }
+
      // Check if body actually got deleted.
   return destroy_dead_entity( body_ptr );
 }
@@ -2685,7 +3046,12 @@
                                                   const CubitVector &vector2,
                                                   double tolerance_factor)
 {
-   return (vector1.within_tolerance( vector2, GEOMETRY_RESABS * tolerance_factor ));
+  double tol = GEOMETRY_RESABS * tolerance_factor;
+  tol *= tol;
+  double dist_sq = vector1.distance_between_squared(vector2);
+  return !(dist_sq > tol);
+  // within_tolerance() just checks coordinate aligned distances, not the actual distance.
+//   return (vector1.within_tolerance( vector2, GEOMETRY_RESABS * tolerance_factor ));
 }
 
 double GeometryQueryTool::geometric_angle(RefEdge* ref_edge_1,
@@ -2856,6 +3222,8 @@
 
 TopologyEntity* GeometryQueryTool::entity_from_bridge( TopologyBridge* bridge_ptr ) const
 {
+  if( !bridge_ptr )
+    return NULL;
   TBOwner* owner = bridge_ptr->owner();
   BridgeManager* bridge_manager;
   while (!(bridge_manager = dynamic_cast<BridgeManager*>(owner)))
@@ -3543,6 +3911,7 @@
                      " to\n       this unsuccessful deletion.\n",
                      bodyPtr->id() );
          assert( status != CUBIT_FAILURE) ;
+         break;
       }
    }
 
@@ -3572,6 +3941,7 @@
                      "due to\n       this unsuccessful deletion.\n",
                      refFacePtr->id());
          assert( status != CUBIT_FAILURE) ;
+         break;
       }
    }
 
@@ -3601,6 +3971,7 @@
                      "due to\n       this unsuccessful deletion.\n",
                      refEdgePtr->id());
          assert( status != CUBIT_FAILURE) ;
+         break;
       }
    }
 
@@ -3630,6 +4001,7 @@
                      "due to\n       this unsuccessful deletion.\n",
                      refVertexPtr->id());
          assert( status != CUBIT_FAILURE) ;
+         break;
       }
    }
 
@@ -3649,16 +4021,36 @@
 
 CubitBox GeometryQueryTool::model_bounding_box()
 {
+  int i;
+  CubitBox result;
   DLIList<Body*> bodies;
   this->bodies(bodies);
-  if (!bodies.size())
-    return CubitBox();
 
+  DLIList<RefEntity*> free_entity_list;
+  this->get_free_ref_entities(free_entity_list);
+  
+  if (!(bodies.size() + free_entity_list.size()))
+    return result;
+
   bodies.reset();
-  CubitBox result = bodies.get()->bounding_box();
-  for (int i = bodies.size() - 1; i--; )
-    result |= bodies.step_and_get()->bounding_box();
+  free_entity_list.reset();
+  
+  if( bodies.size() )
+  {
+    result = bodies.get_and_step()->bounding_box();
+    for ( i = bodies.size()-1; i--; )
+      result |= bodies.get_and_step()->bounding_box();
+    i = free_entity_list.size();
+  }
+  else
+  {
+    result = free_entity_list.get_and_step()->bounding_box();
+    i = free_entity_list.size()-1;
+  }
 
+  for ( i; i--; )
+    result |= free_entity_list.get_and_step()->bounding_box();
+
   return result;
 }
 
@@ -3692,6 +4084,18 @@
   RefEntityFactory::instance()->ref_vertices(ref_vertices);
 }
 
+#ifdef PROE
+void GeometryQueryTool::ref_parts (DLIList<RefPart*> &ref_parts)
+{
+	RefEntityFactory::instance()->ref_parts(ref_parts);
+}
+
+void GeometryQueryTool::ref_assemblies (DLIList<RefAssembly*> &ref_assemblies)
+{
+	RefEntityFactory::instance()->ref_assemblies(ref_assemblies);
+}
+#endif
+
 int GeometryQueryTool::num_bodies() const
 {
   return RefEntityFactory::instance()->num_bodies();
@@ -4534,6 +4938,12 @@
   return (CubitStatus)igeSet.insert(engine_ptr).second;
 }
 
+void GeometryQueryTool::unregister_intermediate_engine(
+  IntermediateGeomEngine* engine_ptr )
+{
+  (CubitStatus)igeSet.erase(engine_ptr);
+}
+
 void GeometryQueryTool::ige_export_geom( DLIList<TopologyBridge*> &geom_list )
 {
   for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
@@ -4547,6 +4957,13 @@
     (*itor)->push_imprint_attributes_before_modify(geom_list);
 }
 
+void GeometryQueryTool::ige_push_named_attributes_to_curves_and_points
+                                ( DLIList<TopologyBridge*> &tb_list, const char *name_in )
+{
+  for (IGESet::reverse_iterator itor = igeSet.rbegin(); itor != igeSet.rend(); ++itor)
+    (*itor)->push_named_attributes_to_curves_and_points(tb_list, name_in);
+}
+
 void GeometryQueryTool::ige_remove_imprint_attributes_after_modify
                                 ( DLIList<BodySM*> &old_sms,
                                   DLIList<BodySM*> &new_sms )
@@ -4567,6 +4984,21 @@
   }
   return ret;
 }
+
+bool GeometryQueryTool::ige_is_composite(TopologyBridge *bridge)
+{
+  bool ret = false;
+  for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end() && ret != true; ++itor)
+  {
+    if((*itor)->is_composite(bridge))
+    {
+      ret = true;
+    }
+  }
+  return ret;
+}
+
+
 bool GeometryQueryTool::ige_is_partition(TBOwner *bridge_owner)
 {
   bool ret = false;
@@ -4586,13 +5018,20 @@
     (*itor)->import_geometry(geom_list);
 }
 
+void GeometryQueryTool::get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                                            DLIList<TopologyBridge*> &tbs )
+{
+  for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
+    (*itor)->get_tbs_with_bridge_manager_as_owner( source_bridge, tbs );
+}
+
 void GeometryQueryTool::ige_attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
                                                     DLIList<TopologyBridge*> &att_tbs,
-                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<TopologyBridge*> &tb_list,
                                                         DLIList<Body*> &old_bodies)
 {
   for (IGESet::iterator itor = igeSet.begin(); itor != igeSet.end(); ++itor)
-    (*itor)->attribute_after_imprinting(new_tbs, att_tbs, new_sms, old_bodies);
+    (*itor)->attribute_after_imprinting(new_tbs, att_tbs, tb_list, old_bodies);
 }
 
 void GeometryQueryTool::ige_remove_attributes( DLIList<TopologyBridge*> &geom_list )
@@ -4707,7 +5146,11 @@
         // parent sense entity which this function will be called on and
         // that call will be the top-most one.
       if (top)
+      {
         CubitObserver::notify_static_observers( ob, TOP_LEVEL_ENTITY_DESTRUCTED );
+        CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, static_cast<RefEntity*>(ob));
+        const_cast<CGMHistory&>(mHistory).add_event(evt);
+      }
       ob->notify_all_observers( MODEL_ENTITY_DESTRUCTED );
     }
     else
@@ -4740,7 +5183,11 @@
             has_parents = true;
         }
         if (!has_parents)
+        {
           ob->notify_all_observers( FREE_REF_ENTITY_GENERATED );
+          CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, static_cast<RefEntity*>(ob));
+          const_cast<CGMHistory&>(mHistory).add_event(evt);
+        }
       }
     }
   }
@@ -4879,14 +5326,118 @@
   return CUBIT_TRUE;
 }
 
+void GeometryQueryTool::translate( DLIList<RefEntity*> &entities_to_transform,
+        double x, double y, double z, bool check_before_transforming,
+        DLIList<RefEntity*> &entities_transformed,
+        bool preview /*= false*/)
+{
+  CubitVector delta(x,y,z);
+
+  //translate free, merged-away entities first
+  DLIList<TopologyBridge*> free_ents; 
+  get_merged_away_free_entities( entities_to_transform, free_ents );
+
+  int i;
+  if (!preview)
+  {
+      for( i=free_ents.size(); i--; )
+      {
+          TopologyBridge *bridge = free_ents.get_and_step();
+          Curve *curve= CAST_TO( bridge, Curve );
+          Point *point = CAST_TO( bridge, Point );
+
+          if( curve || point )
+          {
+              GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
+              GeometryQueryEngine* engine = geom->get_geometry_query_engine();
+              CubitStatus result = engine->translate( geom, delta );
+          }
+      }
+  }
+
+  Body *tmp_body;
+  RefFace *tmp_face;
+  RefEdge *tmp_curve;
+  RefVertex *tmp_vertex;
+  CubitStatus result;
+
+  for(i = entities_to_transform.size(); i > 0; i--)
+  {
+    RefEntity *tmp_ent = entities_to_transform.get_and_step();
+
+    if( ( tmp_body = CAST_TO( tmp_ent, Body ) ) != NULL )
+    {
+      result = translate( tmp_body, CubitVector(x, y, z),
+                          check_before_transforming, preview );
+    }
+    else if( ( tmp_face = CAST_TO( tmp_ent, RefFace ) ) != NULL )
+    {
+        // only allow translating RefFaces if preview is on
+        if (!preview)
+            continue;
+        
+        result = translate(tmp_face, CubitVector( x, y, z ),
+                         check_before_transforming, preview );
+    }
+    else if( ( tmp_curve = CAST_TO( tmp_ent, RefEdge ) ) != NULL )
+    {
+      result = translate(tmp_curve, CubitVector( x, y, z ),
+                         check_before_transforming, preview );
+    }
+    else if( ( tmp_vertex = CAST_TO( tmp_ent, RefVertex ) ) != NULL )
+    {
+     CubitVector vec(x, y, z);
+      result = translate( tmp_vertex, vec, check_before_transforming, preview);
+      if( result )
+      {
+        PRINT_INFO("Vertex %d moved %g %g %g\n", tmp_vertex->id(), x, y, z);
+      }
+      else
+        PRINT_ERROR("Unable to move Vertex %d\n", tmp_vertex->id());
+    }
+
+    if(result)
+      entities_transformed.append( tmp_ent );
+  }
+}
+
+
+
 CubitStatus GeometryQueryTool::translate( Body* body,
                                           const CubitVector& delta,
-                                          bool check_to_transform )
+                                          bool check_to_transform,
+                                          bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( body ))
      return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    body->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV += delta;
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   BodySM* bodysm = body->get_body_sm_ptr();
   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
   CubitStatus result = engine->translate( bodysm, delta );
@@ -4903,15 +5454,126 @@
   return result;
 }
 
+CubitStatus GeometryQueryTool::rotate( DLIList<RefEntity*> &entities_to_transform,  
+                      const CubitVector& point,
+                      const CubitVector& direction,
+                      double angle,
+                      bool check_before_transforming,
+                      DLIList<RefEntity*> &entities_transformed,
+                      bool preview /*= false*/)
+{
+  //rotate free, merged-away entities first
+  DLIList<TopologyBridge*> free_ents; 
+  get_merged_away_free_entities( entities_to_transform, free_ents );
+  
+  int i;
+  if (!preview)
+  {
+      for( i=free_ents.size(); i--; )
+      {
+          TopologyBridge *bridge = free_ents.get_and_step();
+          Curve *curve= CAST_TO( bridge, Curve );
+          Point *tmp_point = CAST_TO( bridge, Point );
+
+          if( curve || tmp_point )
+          {
+              GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
+              GeometryQueryEngine* engine = geom->get_geometry_query_engine();
+              CubitStatus result = engine->translate( geom, -point ); 
+              result = engine->rotate( geom, direction, angle ); 
+              result = engine->translate( geom, point ); 
+
+          }
+      }
+  }
+
+  Body *tmp_body;
+  RefFace *tmp_face;
+  RefEdge *tmp_curve;
+  RefEntity *tmp_ent;
+  CubitStatus result;
+  for(i=entities_to_transform.size(); i > 0; i--)
+  {
+    tmp_ent = entities_to_transform.get_and_step();
+
+    //body
+    if( ( tmp_body = CAST_TO( tmp_ent, Body ) ) != NULL )
+      result = rotate( tmp_body, point, direction, angle,
+                       check_before_transforming, preview);
+    else if( (tmp_face = CAST_TO( tmp_ent, RefFace ) ) != NULL )
+    {
+        // only allow rotation of RefFaces if preview is on
+        if (!preview)
+            continue;
+        
+        result = rotate( tmp_face, direction, angle,
+                       check_before_transforming, preview);
+    }
+    //curve
+    else if( (tmp_curve = CAST_TO( tmp_ent, RefEdge ) ) != NULL )
+      result = rotate( tmp_curve, direction, angle,
+                       check_before_transforming, preview);
+
+    if( result == CUBIT_SUCCESS )
+      entities_transformed.append( tmp_ent );
+  }
+
+  return result;
+}
+
 CubitStatus GeometryQueryTool::rotate( Body* body,
                                        const CubitVector& axis,
                                        double angle,
-                                       bool check_to_transform )
+                                       bool check_to_transform,
+                                       bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( body ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    body->ref_edges(edges);
+    for (int j = 0; j < edges.size(); j++)
+    {
+      GMem poly, prev;
+      edges[j]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int k = 0; k < poly.point_list_size(); k++)
+      {
+        CubitVector q;
+        CubitVector tempAxis = axis;
+        CubitVector p(poly.point_list()[k].x, poly.point_list()[k].y, poly.point_list()[k].z);
+        double costheta = cos(angle*3.14159265358979323846/180);
+        double sintheta = sin(angle*3.14159265358979323846/180);
+        tempAxis.normalize();
+
+        q.x() += (costheta + (1 - costheta) * tempAxis.x() * tempAxis.x()) * p.x();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.y() - tempAxis.z() * sintheta) * p.y();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.z() + tempAxis.y() * sintheta) * p.z();
+
+        q.y() += ((1 - costheta) * tempAxis.x() * tempAxis.y() + tempAxis.z() * sintheta) * p.x();
+        q.y() += (costheta + (1 - costheta) * tempAxis.y() * tempAxis.y()) * p.y();
+        q.y() += ((1 - costheta) * tempAxis.y() * tempAxis.z() - tempAxis.x() * sintheta) * p.z();
+
+        q.z() += ((1 - costheta) * tempAxis.x() * tempAxis.z() - tempAxis.y() * sintheta) * p.x();
+        q.z() += ((1 - costheta) * tempAxis.y() * tempAxis.z() + tempAxis.x() * sintheta) * p.y();
+        q.z() += (costheta + (1 - costheta) * tempAxis.z() * tempAxis.z()) * p.z();
+
+        prev_points[k].x = q.x();
+        prev_points[k].y = q.y();
+        prev_points[k].z = q.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   BodySM* bodysm = body->get_body_sm_ptr();
   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
   CubitStatus result = engine->rotate( bodysm, axis, angle );
@@ -4934,12 +5596,66 @@
                                        const CubitVector& point,
                                        const CubitVector& direction,
                                        double degrees,
-                                       bool check_to_transform )
+                                       bool check_to_transform,
+                                       bool preview /*=false*/)
 {
   if( check_to_transform )
     if (!okay_to_transform( body ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    // define the axis
+    CubitVector axis(direction);
+    
+    DLIList<RefEdge*> edges;
+    body->ref_edges(edges);
+    for (int j = 0; j < edges.size(); j++)
+    {
+      GMem poly, prev;
+      edges[j]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int k = 0; k < poly.point_list_size(); k++)
+      {
+        CubitVector q;
+
+        // first translate to the rotation axis
+        CubitVector p(poly.point_list()[k].x, poly.point_list()[k].y, poly.point_list()[k].z);
+        p -= point;
+
+        CubitVector tempAxis = axis;
+        double costheta = cos(degrees*3.14159265358979323846/180);
+        double sintheta = sin(degrees*3.14159265358979323846/180);
+        tempAxis.normalize();
+
+        q.x() += (costheta + (1 - costheta) * tempAxis.x() * tempAxis.x()) * p.x();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.y() - tempAxis.z() * sintheta) * p.y();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.z() + tempAxis.y() * sintheta) * p.z();
+
+        q.y() += ((1 - costheta) * tempAxis.x() * tempAxis.y() + tempAxis.z() * sintheta) * p.x();
+        q.y() += (costheta + (1 - costheta) * tempAxis.y() * tempAxis.y()) * p.y();
+        q.y() += ((1 - costheta) * tempAxis.y() * tempAxis.z() - tempAxis.x() * sintheta) * p.z();
+
+        q.z() += ((1 - costheta) * tempAxis.x() * tempAxis.z() - tempAxis.y() * sintheta) * p.x();
+        q.z() += ((1 - costheta) * tempAxis.y() * tempAxis.z() + tempAxis.x() * sintheta) * p.y();
+        q.z() += (costheta + (1 - costheta) * tempAxis.z() * tempAxis.z()) * p.z();
+
+        // move back into position
+        q += point;
+        
+        prev_points[k].x = q.x();
+        prev_points[k].y = q.y();
+        prev_points[k].z = q.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   BodySM* bodysm = body->get_body_sm_ptr();
   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
   CubitTransformMatrix xform;
@@ -4983,12 +5699,110 @@
   return result;
 }
 
-CubitStatus GeometryQueryTool::scale( Body* body, double factor, bool check_to_transform )
+void GeometryQueryTool::scale( DLIList<RefEntity*> &entities_to_transform, 
+                                      double scale_x, double scale_y, double scale_z, 
+                                      bool check_before_transforming, 
+                                      DLIList<RefEntity*> &entities_scaled,
+                                      bool preview /*= false*/)
 {
+  CubitVector factors(scale_x, scale_y, scale_z);
+
+  //scale free, merged-away entities first
+  DLIList<TopologyBridge*> free_ents; 
+  get_merged_away_free_entities( entities_to_transform, free_ents );
+  int i;
+  if (!preview)
+  {
+      for( i=free_ents.size(); i--; )
+      {
+          TopologyBridge *bridge = free_ents.get_and_step();
+          Curve *curve= CAST_TO( bridge, Curve );
+          Point *point = CAST_TO( bridge, Point );
+
+          if( curve || point )
+          {
+              GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
+              GeometryQueryEngine* engine = geom->get_geometry_query_engine();
+              CubitStatus result = engine->scale( geom, factors );
+          }
+      }
+  }
+  
+  CubitStatus result;
+  for(i=entities_to_transform.size(); i--; )
+  {
+    RefEntity *tmp_ent = entities_to_transform.get_and_step();
+    Body *tmp_body;
+    RefFace* tmp_face;
+    RefEdge *tmp_curve;
+    if( ( tmp_body = CAST_TO( tmp_ent, Body ) ) != NULL )
+    {
+      //non-uniform scaling
+      if( scale_x != scale_y ||
+          scale_x != scale_z ||
+          scale_y != scale_z )
+      {
+        // use GMT version for non-uniform scaling b/c it updates topology if it changes
+        result = GeometryModifyTool::instance()->scale(tmp_body, factors, 
+                                                  check_before_transforming, preview);
+        tmp_ent = tmp_body;
+      }
+      else
+        result = scale( tmp_body, CubitVector(scale_x, scale_y, scale_z),
+                 check_before_transforming, preview);
+    }
+    else if( ( tmp_face = CAST_TO( tmp_ent, RefFace ) ) != NULL )
+    {
+     // only allow scaling of RefFaces if preview is on
+     if (!preview)
+         continue;
+     result = scale( tmp_face, CubitVector(scale_x, scale_y, scale_z),
+                check_before_transforming, preview);
+    }
+    else if( ( tmp_curve = CAST_TO( tmp_ent, RefEdge ) ) != NULL )
+    {
+     result = scale( tmp_curve, CubitVector(scale_x, scale_y, scale_z),
+                check_before_transforming, preview);
+    }
+    if(result)
+      entities_scaled.append( tmp_ent );
+  } 
+  
+}
+
+
+CubitStatus GeometryQueryTool::scale( Body* body, double factor, bool check_to_transform, bool preview )
+{
   if( check_to_transform )
     if (!okay_to_transform( body ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    body->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV *= factor;
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   BodySM* bodysm = body->get_body_sm_ptr();
   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
   CubitStatus result = engine->scale( bodysm, factor );
@@ -5007,12 +5821,41 @@
 
 CubitStatus GeometryQueryTool::scale( Body *body,
                                       const CubitVector& factors,
-                                      bool check_to_transform )
+                                      bool check_to_transform,
+                                      bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( body ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    body->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV.x(tempV.x()*factors.x());
+        tempV.y(tempV.y()*factors.y());
+        tempV.z(tempV.z()*factors.z());
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   BodySM* bodysm = body->get_body_sm_ptr();
   GeometryQueryEngine* engine = bodysm->get_geometry_query_engine();
   CubitStatus result = engine->scale( bodysm, factors );
@@ -5030,11 +5873,129 @@
   return result;
 }
 
+void GeometryQueryTool::reflect( DLIList<RefEntity*> &entities_to_transform,
+                            double x, double y, double z, 
+                            bool check_before_transforming,
+                            DLIList<RefEntity*> &entities_transformed,
+                            bool preview /*= false*/)
+{
+  CubitVector axis( x,y,z);
+
+  //reflect free, merged-away entities
+  DLIList<TopologyBridge*> free_ents; 
+  get_merged_away_free_entities( entities_to_transform, free_ents );
+  
+  int i;
+  if (!preview)
+  {
+      for( i=free_ents.size(); i--; )
+      {
+          TopologyBridge *bridge = free_ents.get_and_step();
+          Curve *curve= CAST_TO( bridge, Curve );
+          Point *tmp_point = CAST_TO( bridge, Point );
+
+          if( curve || tmp_point )
+          {
+              GeometryEntity *geom = CAST_TO( bridge, GeometryEntity );
+              GeometryQueryEngine* engine = geom->get_geometry_query_engine();
+              CubitStatus result = engine->reflect( geom, axis ); 
+          }
+      }
+  }
+
+  DLIList<Body*> body_list;
+  DLIList<RefEdge*> curve_list;
+  DLIList<RefFace*> face_list;
+  CubitStatus result;
+  CAST_LIST(entities_to_transform, body_list, Body);
+  if( body_list.size() != entities_to_transform.size() )
+  {
+    CAST_LIST(entities_to_transform, curve_list, RefEdge);
+    CAST_LIST(entities_to_transform, face_list, RefFace);
+  }
+
+  if( body_list.size() )
+  {
+    result = GeometryQueryTool::instance()->reflect( body_list, CubitVector( x, y, z ), preview );
+    if ( result ) 
+    {
+      while(body_list.size())
+        entities_transformed.append(body_list.pop());
+    }
+  }
+  if( face_list.size() )
+  {
+    int i;
+    for(i = face_list.size(); i > 0; i--)
+    {
+      // only allow reflection of RefFaces if preview is on
+      if (!preview)
+          continue;
+
+      RefFace *tmp_face = face_list.get_and_step();
+      result = reflect( tmp_face, axis, 
+                        check_before_transforming, preview );
+      if ( result ) 
+        entities_transformed.append( tmp_face ); 
+    }
+  }
+  if( curve_list.size() )
+  {
+    int i;
+    for(i = curve_list.size(); i > 0; i--)
+    {
+      RefEdge *tmp_edge = curve_list.get_and_step();
+      result = reflect( tmp_edge, axis, 
+                        check_before_transforming, preview );
+      if ( result ) 
+        entities_transformed.append( tmp_edge ); 
+    }
+  }
+
+}
+
+
+
 CubitStatus GeometryQueryTool::reflect( DLIList<Body*> bodies,
-                                        const CubitVector& axis )
+                                        const CubitVector& axis,
+                                        bool preview)
 {
   Body *tmp_body;
   CubitStatus result = CUBIT_FAILURE;
+
+  if (preview)
+  {
+    for (int i = 0; i < bodies.size(); i++)
+    {
+      DLIList<RefEdge*> edges;
+      bodies[i]->ref_edges(edges);
+      for (int j = 0; j < edges.size(); j++)
+      {
+        GMem poly, prev;
+        edges[j]->get_graphics(poly);
+        GPoint *prev_points = NULL;
+        prev_points = new GPoint[poly.point_list_size()];
+        for (int k = 0; k < poly.point_list_size(); k++)
+        {
+          CubitVector tempAxis = axis;
+          CubitVector tempV(poly.point_list()[k].x, poly.point_list()[k].y, poly.point_list()[k].z);
+          CubitVector b = tempV - CubitVector(0,0,0);
+          double dist = (tempAxis % b) / tempAxis.length();
+          tempAxis.length(dist);
+          CubitVector refl = tempV - tempAxis;
+          refl = refl - tempV + refl;
+          prev_points[k].x = refl.x();
+          prev_points[k].y = refl.y();
+          prev_points[k].z = refl.z();
+        }
+        GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+        delete [] prev_points;
+        prev_points = NULL;
+      }
+      GfxPreview::flush();
+    }
+    return CUBIT_SUCCESS;
+  }
   //first, reflect the underlying geometry
   int i;
   for( i=bodies.size(); i--;)
@@ -5058,6 +6019,11 @@
     CubitTransformMatrix xform;
     xform.reflect( axis );
     notify_intermediate_of_transform( tmp_body, xform );
+  }
+
+  for( i=bodies.size(); i--;)
+  {
+    tmp_body = bodies.get_and_step();
     make_Body( tmp_body->get_body_sm_ptr() );
     notify_observers_of_transform( tmp_body );
   }
@@ -5078,6 +6044,10 @@
                                         RefEntity* ref_entity ) const
 {
   ref_entity->notify_sub_all_observers( GEOMETRY_MODIFIED );
+  
+  CGMHistory::Event evt(CGMHistory::GEOMETRY_TRANSFORMED, ref_entity);
+  const_cast<CGMHistory&>(mHistory).add_event(evt);
+
   return CUBIT_SUCCESS;
 }
 
@@ -5105,12 +6075,50 @@
 
 CubitStatus GeometryQueryTool::translate( BasicTopologyEntity* bte,
                                           const CubitVector& delta,
-                                          bool check_to_transform )
+                                          bool check_to_transform,
+                                          bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( bte ))
      return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    bte->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV += delta;
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    if (edges.size() == 0)
+    {
+      DLIList<RefVertex*> points;
+      bte->ref_vertices(points);
+      for (int i = 0; i < points.size(); i++)
+      {
+        CubitVector temp(points[i]->center_point());
+        temp += delta;
+        GfxPreview::draw_point(temp, CUBIT_BLUE);
+      }
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   GeometryEntity* geom = bte->get_geometry_entity_ptr();
   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
   CubitStatus result = engine->translate( geom, delta );
@@ -5130,12 +6138,87 @@
 CubitStatus GeometryQueryTool::rotate( BasicTopologyEntity* bte,
                                        const CubitVector& axis,
                                        double angle,
-                                       bool check_to_transform )
+                                       bool check_to_transform,
+                                       bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( bte ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    bte->ref_edges(edges);
+
+    for (int j = 0; j < edges.size(); j++)
+    {
+      GMem poly, prev;
+      edges[j]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int k = 0; k < poly.point_list_size(); k++)
+      {
+        CubitVector q;
+        CubitVector tempAxis = axis;
+        CubitVector p(poly.point_list()[k].x, poly.point_list()[k].y, poly.point_list()[k].z);
+        double costheta = cos(angle*3.14159265358979323846/180);
+        double sintheta = sin(angle*3.14159265358979323846/180);
+        tempAxis.normalize();
+
+        q.x() += (costheta + (1 - costheta) * tempAxis.x() * tempAxis.x()) * p.x();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.y() - tempAxis.z() * sintheta) * p.y();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.z() + tempAxis.y() * sintheta) * p.z();
+
+        q.y() += ((1 - costheta) * tempAxis.x() * tempAxis.y() + tempAxis.z() * sintheta) * p.x();
+        q.y() += (costheta + (1 - costheta) * tempAxis.y() * tempAxis.y()) * p.y();
+        q.y() += ((1 - costheta) * tempAxis.y() * tempAxis.z() - tempAxis.x() * sintheta) * p.z();
+
+        q.z() += ((1 - costheta) * tempAxis.x() * tempAxis.z() - tempAxis.y() * sintheta) * p.x();
+        q.z() += ((1 - costheta) * tempAxis.y() * tempAxis.z() + tempAxis.x() * sintheta) * p.y();
+        q.z() += (costheta + (1 - costheta) * tempAxis.z() * tempAxis.z()) * p.z();
+
+        prev_points[k].x = q.x();
+        prev_points[k].y = q.y();
+        prev_points[k].z = q.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    if (edges.size() == 0)
+    {
+      DLIList<RefVertex*> points;
+      bte->ref_vertices(points);
+      for (int i = 0; i < points.size(); i++)
+      {
+        CubitVector tempAxis = axis;
+        CubitVector p(points[i]->center_point());
+        double costheta = cos(angle*3.14159265358979323846/180);
+        double sintheta = sin(angle*3.14159265358979323846/180);
+        tempAxis.normalize();
+
+        CubitVector q;
+        
+        q.x() += (costheta + (1 - costheta) * tempAxis.x() * tempAxis.x()) * p.x();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.y() - tempAxis.z() * sintheta) * p.y();
+        q.x() += ((1 - costheta) * tempAxis.x() * tempAxis.z() + tempAxis.y() * sintheta) * p.z();
+
+        q.y() += ((1 - costheta) * tempAxis.x() * tempAxis.y() + tempAxis.z() * sintheta) * p.x();
+        q.y() += (costheta + (1 - costheta) * tempAxis.y() * tempAxis.y()) * p.y();
+        q.y() += ((1 - costheta) * tempAxis.y() * tempAxis.z() - tempAxis.x() * sintheta) * p.z();
+
+        q.z() += ((1 - costheta) * tempAxis.x() * tempAxis.z() - tempAxis.y() * sintheta) * p.x();
+        q.z() += ((1 - costheta) * tempAxis.y() * tempAxis.z() + tempAxis.x() * sintheta) * p.y();
+        q.z() += (costheta + (1 - costheta) * tempAxis.z() * tempAxis.z()) * p.z();
+
+        GfxPreview::draw_point(q, CUBIT_BLUE);
+      }
+    }
+
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   GeometryEntity* geom = bte->get_geometry_entity_ptr();
   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
   CubitStatus result = engine->rotate( geom, axis, angle );
@@ -5153,12 +6236,38 @@
 }
 
 CubitStatus GeometryQueryTool::scale( BasicTopologyEntity* bte, double factor,
-                                      bool check_to_transform )
+                                      bool check_to_transform, bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( bte ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    bte->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV *= factor;
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   GeometryEntity* geom = bte->get_geometry_entity_ptr();
   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
   CubitStatus result = engine->scale( geom, factor );
@@ -5178,12 +6287,41 @@
 
 CubitStatus GeometryQueryTool::scale( BasicTopologyEntity* bte,
                                       const CubitVector& factors,
-                                      bool check_to_transform )
+                                      bool check_to_transform,
+                                      bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( bte ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    bte->ref_edges(edges);
+    for (int i = 0; i < edges.size(); i++)
+    {
+      GMem poly, prev;
+      edges[i]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int j = 0; j < poly.point_list_size(); j++)
+      {
+        CubitVector tempV(poly.point_list()[j].x, poly.point_list()[j].y, poly.point_list()[j].z);
+        tempV.x(tempV.x()*factors.x());
+        tempV.y(tempV.y()*factors.y());
+        tempV.z(tempV.z()*factors.z());
+        prev_points[j].x = tempV.x();
+        prev_points[j].y = tempV.y();
+        prev_points[j].z = tempV.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   GeometryEntity* geom = bte->get_geometry_entity_ptr();
   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
   CubitStatus result = engine->scale( geom, factors );
@@ -5202,12 +6340,44 @@
 
 CubitStatus GeometryQueryTool::reflect( BasicTopologyEntity* bte,
                                         const CubitVector& axis,
-                                        bool check_to_transform )
+                                        bool check_to_transform,
+                                        bool preview )
 {
   if( check_to_transform )
     if (!okay_to_transform( bte ))
       return CUBIT_FAILURE;
 
+  if (preview)
+  {
+    DLIList<RefEdge*> edges;
+    bte->ref_edges(edges);
+    for (int j = 0; j < edges.size(); j++)
+    {
+      GMem poly, prev;
+      edges[j]->get_graphics(poly);
+      GPoint *prev_points = NULL;
+      prev_points = new GPoint[poly.point_list_size()];
+      for (int k = 0; k < poly.point_list_size(); k++)
+      {
+        CubitVector tempAxis = axis;
+        CubitVector tempV(poly.point_list()[k].x, poly.point_list()[k].y, poly.point_list()[k].z);
+        CubitVector b = tempV - CubitVector(0,0,0);
+        double dist = (tempAxis % b) / tempAxis.length();
+        tempAxis.length(dist);
+        CubitVector refl = tempV - tempAxis;
+        refl = refl - tempV + refl;
+        prev_points[k].x = refl.x();
+        prev_points[k].y = refl.y();
+        prev_points[k].z = refl.z();
+      }
+      GfxPreview::draw_polyline(prev_points, poly.point_list_size(), CUBIT_BLUE);
+      delete [] prev_points;
+      prev_points = NULL;
+    }
+    GfxPreview::flush();
+    return CUBIT_SUCCESS;
+  }
+
   GeometryEntity* geom = bte->get_geometry_entity_ptr();
   GeometryQueryEngine* engine = geom->get_geometry_query_engine();
   CubitStatus result = engine->reflect( geom, axis );
@@ -5230,20 +6400,22 @@
   return result;
 }
 
-void GeometryQueryTool::ige_remove_modified(DLIList<TopologyBridge*>& geometry_list)
+void GeometryQueryTool::ige_remove_modified(DLIList<Surface*> &all_surfs,
+                                            DLIList<Curve*> &all_curves,
+                                            DLIList<Point*> &all_points)
 {
   IGESet::iterator itor;
 
   for (itor = igeSet.begin(); itor != igeSet.end(); ++itor)
-    (*itor)->remove_modified(geometry_list);
+    (*itor)->remove_modified(all_surfs, all_curves, all_points);
 
   for (itor = igeSet.begin(); itor != igeSet.end(); ++itor)
     (*itor)->clean_out_deactivated_geometry();
 }
+
 CubitBoolean GeometryQueryTool::bodies_overlap( Body *body_ptr_1,
                                                 Body *body_ptr_2 )
 {
-
   BodySM *body1 = body_ptr_1->get_body_sm_ptr();
   BodySM *body2 = body_ptr_2->get_body_sm_ptr();
 
@@ -5261,3 +6433,376 @@
   else
     return body_ptr_1->get_geometry_query_engine()->bodies_overlap( body1, body2 );
 }
+
+CubitBoolean GeometryQueryTool::volumes_overlap( RefVolume *volume_1,
+                                                 RefVolume *volume_2 )
+{
+  Lump *lump1 = volume_1->get_lump_ptr();
+  Lump *lump2 = volume_2->get_lump_ptr();
+
+  if( is_intermediate_geometry( volume_1 ) )
+    return volume_1->get_geometry_query_engine()->volumes_overlap( lump1, lump2 );
+  else if( is_intermediate_geometry( volume_2 ) )
+    return volume_2->get_geometry_query_engine()->volumes_overlap( lump2, lump1 );
+  else if( volume_1->get_geometry_query_engine() !=
+           volume_2->get_geometry_query_engine() )
+  {
+    PRINT_ERROR("Volumes must be of the same type (ACIS, SolidWorks, etc) to\n"
+                "find if they overlap.\n");
+    return CUBIT_FALSE;
+  }
+  else
+    return volume_1->get_geometry_query_engine()->volumes_overlap( lump1, lump2 );
+}
+
+void GeometryQueryTool::find_nonmanifold_curves(DLIList<RefVolume*> &vol_list,
+                                                DLIList<RefEdge*> &curve_list)
+{
+  int i;
+  for(i=vol_list.size(); i>0; i--)
+  {
+    RefVolume *vol = vol_list.get_and_step();
+    DLIList<RefEdge*> vol_curves;
+    vol->ref_edges(vol_curves);
+    int j;
+    for(j=vol_curves.size(); j>0; j--)
+    {
+      RefEdge *cur_curve = vol_curves.get_and_step();
+      if(cur_curve->is_merged())
+      {
+        DLIList<RefFace*> curve_faces;
+        cur_curve->ref_faces(curve_faces);
+        bool merged_face_exists = false;
+        while(curve_faces.size() && !merged_face_exists)
+        {
+          RefFace *cur_face = curve_faces.pop();
+          if(cur_face->is_merged())
+            merged_face_exists = true;
+        }
+        if(!merged_face_exists)
+          curve_list.append(cur_curve);
+      }
+    }
+  }
+  curve_list.uniquify_ordered();
+}
+
+double GeometryQueryTool::estimate_merge_tolerance(DLIList<RefVolume*> &vol_list,
+                                                    bool accurate_in,
+                                                    bool report_in,
+                                                    double lo_val_in, 
+                                                    double hi_val_in,
+                                                    int num_calculations_in,
+                                                    bool return_calculations_in,
+                                                    DLIList<double> *merge_tols,
+                                                    DLIList<int> *num_proximities)
+{
+  double return_merge_tol = -1.0;  // return value of < 0.0 will mean failure
+                                   // to find a merge tolerance
+
+  DLIList<double> local_merge_tols;
+  DLIList<int> local_num_proximities;
+  bool accurate = accurate_in;
+  bool report = report_in;
+  double lo_val = 0.0;
+  double hi_val = get_geometry_factor()*GEOMETRY_RESABS*10.0;  // 10 * merge tol -- arbitrary
+  int num_calculations = num_calculations_in;
+  bool return_calculations = return_calculations_in;
+
+  if(lo_val_in != -1.0)
+    lo_val = lo_val_in;
+  if(hi_val_in != -1.0)
+    hi_val = hi_val_in;
+
+  if(hi_val > lo_val)
+  {
+    double cur_val = lo_val;
+    double step = (hi_val - lo_val)/(double)num_calculations;
+    int i;
+    if(report)
+    {
+      PRINT_INFO("\n\nLooking for merge toleance...\n\n");
+      PRINT_INFO("  Possible range: %lf, %lf\n", lo_val, hi_val);
+      PRINT_INFO("  Number of steps: %d\n\n", num_calculations+1);
+    }
+
+    std::map <RefVertex*, DLIList<dist_vert_struct*>*> vert_dist_map;
+    GeomMeasureTool::find_near_coincident_vertices_unique(vol_list, hi_val, vert_dist_map);
+
+    int total_num_proximities = 0;
+    for(i=0; i<=num_calculations; i++)
+    {
+      int cur_num_proximities = 0;
+      local_merge_tols.append(cur_val);
+
+      std::map <RefVertex*, DLIList<dist_vert_struct*>*>::iterator iter;
+      for(iter=vert_dist_map.begin(); iter != vert_dist_map.end(); iter++ )
+      {
+        RefVertex *vert = iter->first;
+        DLIList<dist_vert_struct*> *struct_list = iter->second;
+        int m;
+        for(m=struct_list->size(); m>0; m--)
+        {
+          dist_vert_struct *dvs = struct_list->get();
+          if(dvs->dist <= cur_val)
+          {
+  //          PRINT_INFO("Vertices %d and %d, distance: %.10lf\n", vert->id(), dvs->v2->id(), dvs->dist);
+            struct_list->change_to(NULL);
+            delete dvs;
+            cur_num_proximities++;
+          }
+          struct_list->step();
+        }
+        struct_list->remove_all_with_value(NULL);
+      }
+
+      total_num_proximities += cur_num_proximities;
+      local_num_proximities.append(total_num_proximities);
+
+      if(report)
+      {
+        PRINT_INFO("  At merge tolerance = %lf number of proximities = %d.\n", cur_val, total_num_proximities);
+      }
+
+      cur_val += step;
+    }
+
+    std::map <RefVertex*, DLIList<dist_vert_struct*>*>::iterator iter;
+    for(iter=vert_dist_map.begin(); iter != vert_dist_map.end(); iter++ )
+    {
+      DLIList<dist_vert_struct*> *struct_list = iter->second;
+      // I think all of the items in the lists should be gone
+      // by now but just in case...
+      while(struct_list->size())
+        delete struct_list->pop();
+      delete struct_list;
+    }
+
+    local_num_proximities.reset();
+    local_merge_tols.reset();
+    int num_total = local_merge_tols.size();
+    if(num_total > 2)
+    {
+      int num_triplets = num_total - 2;
+      int h, min_index, min_diff;
+      DLIList<int> diffs;
+      for(h=0; h<num_triplets; h++)
+      {
+        int num_begin = local_num_proximities.get();
+        local_num_proximities.step(2);
+        int num_end = local_num_proximities.get();
+        local_num_proximities.back();
+        int cur_diff = num_end - num_begin;
+        if(h==0)
+        {
+          min_index = h;
+          min_diff = cur_diff;
+        }
+        else
+        {
+          if(cur_diff < min_diff)
+          {
+            min_diff = cur_diff;
+            min_index = h;
+          }
+        }
+      }
+      local_merge_tols.step(min_index+1);
+      return_merge_tol = local_merge_tols.get();
+    }
+    else
+      PRINT_ERROR("Unable to estimate merge tolerance.\n");
+
+/*
+    // Pick off a merge tolerance.
+    local_num_proximities.reset();
+    local_merge_tols.reset();
+    DLIList<int> unique_num_proximities;
+    DLIList<int> unique_counts;
+    DLIList<double> tmp_merge_tol_list;
+    int tmp_num_proximities;
+    double tmp_merge_tol;
+
+    double cur_merge_tol = local_merge_tols.get_and_step();
+    int cur_num_prox = local_num_proximities.get_and_step();
+    int cur_unique_counts = 1;
+    // Loop over the whole size even though we have processed the 
+    // first entry because we need to record the results after the
+    // last entry.
+    for(i=local_num_proximities.size(); i>0; i--)
+    {
+      if(i>1)
+      {
+        tmp_num_proximities = local_num_proximities.get_and_step();
+        tmp_merge_tol = local_merge_tols.get_and_step();
+      }
+      else 
+      {
+        // On the last time in just give it a dummy value so we
+        // can record the results from the last real entry.
+        tmp_num_proximities = -1;
+      }
+      if(cur_num_prox == tmp_num_proximities)
+      {
+        cur_unique_counts++;
+      }
+      else
+      {
+        tmp_merge_tol_list.append(cur_merge_tol);
+        unique_counts.append(cur_unique_counts);
+        unique_num_proximities.append(cur_num_prox);
+        cur_unique_counts = 1;
+        cur_num_prox = tmp_num_proximities;
+        cur_merge_tol = tmp_merge_tol;
+      }
+    }
+
+    int max_index = -1;
+    int cur_max_num_counts = 0;
+    unique_counts.reset();
+    unique_num_proximities.reset();
+    tmp_merge_tol_list.reset();
+    for(i=unique_counts.size(); i>0; i--)
+    {
+      int cur_num_counts = unique_counts.get();
+      if(cur_num_counts > cur_max_num_counts)
+      {
+        cur_max_num_counts = cur_num_counts;
+        max_index = unique_counts.get_index();
+      }
+      unique_counts.step();
+    }
+
+    if(max_index > -1)
+    {
+      tmp_merge_tol_list.step(max_index);
+      return_merge_tol = tmp_merge_tol_list.get();
+    }
+    else
+    {
+      PRINT_ERROR("Unable to estimate merge tolerance.\n");
+    }
+    */
+
+    if(report)
+      PRINT_INFO("\nEstimated merge tolerance: %lf\n", return_merge_tol);
+  }
+  else
+    PRINT_ERROR("Range low value is larger than range high value.\n");
+
+  return return_merge_tol;
+}
+
+void GeometryQueryTool::find_floating_volumes(DLIList<RefVolume*> &vol_list,
+                                              DLIList<RefVolume*> &floating_list)
+{
+  int i;
+  for(i=vol_list.size(); i>0; i--)
+  {
+    bool floating = true;
+    RefVolume *vol = vol_list.get_and_step();
+    DLIList<RefEdge*> vol_curves;
+    DLIList<RefVertex*> vol_verts;
+    DLIList<RefFace*> vol_surfs;
+    vol->ref_edges(vol_curves);
+    vol->ref_faces(vol_surfs);
+    vol->ref_vertices(vol_verts);
+    int j;
+    for(j=vol_surfs.size(); j>0 && floating; j--)
+    {
+      RefFace *cur_surf = vol_surfs.get_and_step();
+      if(cur_surf->is_merged())
+        floating = false;
+    }
+    for(j=vol_curves.size(); j>0 && floating; j--)
+    {
+      RefEdge *cur_curve = vol_curves.get_and_step();
+      if(cur_curve->is_merged())
+        floating = false;
+    }
+    for(j=vol_verts.size(); j>0 && floating; j--)
+    {
+      RefVertex *cur_vert = vol_verts.get_and_step();
+      if(cur_vert->is_merged())
+        floating = false;
+    }
+    if(floating)
+      floating_list.append(vol);
+  }
+  floating_list.uniquify_ordered();
+}
+
+void GeometryQueryTool::find_nonmanifold_vertices(DLIList<RefVolume*> &vol_list,
+                                                DLIList<RefVertex*> &vertex_list)
+{
+  int i;
+  for(i=vol_list.size(); i>0; i--)
+  {
+    RefVolume *vol = vol_list.get_and_step();
+    DLIList<RefVertex*> vol_verts;
+    vol->ref_vertices(vol_verts);
+    int j;
+    for(j=vol_verts.size(); j>0; j--)
+    {
+      RefVertex *cur_vert = vol_verts.get_and_step();
+      if(cur_vert->is_merged())
+      {
+        DLIList<RefEdge*> vert_edges;
+        cur_vert->ref_edges(vert_edges);
+        bool merged_edge_exists = false;
+        while(vert_edges.size() && !merged_edge_exists)
+        {
+          RefEdge *cur_edge = vert_edges.pop();
+          if(cur_edge->is_merged())
+            merged_edge_exists = true;
+        }
+        if(!merged_edge_exists)
+          vertex_list.append(cur_vert);
+      }
+    }
+  }
+  vertex_list.uniquify_ordered();
+}
+
+CGMHistory& GeometryQueryTool::history()
+{
+  return mHistory;
+}
+
+void GeometryQueryTool::get_merged_away_free_entities( DLIList<RefEntity*> &ref_ents,
+                                                       DLIList<TopologyBridge*> &free_ents )
+{
+  //determine if you have any free entities that were merged away 
+  DLIList<RefEntity*> merged_ref_ents;
+  MergeTool::instance()->contains_merged_entities( ref_ents, &merged_ref_ents );
+  int i;
+  for( i=merged_ref_ents.size(); i--; )
+  {
+    RefEntity *tmp_ent = merged_ref_ents.get_and_step();
+    DLIList<TopologyBridge*> bridge_list;
+    TopologyEntity *te = CAST_TO(tmp_ent, TopologyEntity );
+    te->bridge_manager()->get_bridge_list( bridge_list );
+    //bridge_list.reset();
+    //bridge_list.step(); //don't want to first bridge...that's the real thing
+    
+    //check for free entities...
+    int j;
+    for( j=0; j<bridge_list.size(); j++ )
+    {
+      TopologyBridge *tmp_bridge = bridge_list.get_and_step();
+
+      //ignore the representation bridge if it's a free vertex
+      if( j==0 )
+        if( tmp_ent->num_parent_ref_entities() == 0 )
+          continue;
+
+      DLIList<TopologyBridge*> parents;
+      tmp_bridge->get_parents( parents );
+      if( parents.size() == 0 ) 
+        free_ents.append( tmp_bridge );
+    }
+  }
+}
+
+
+

Modified: cgm/branches/cubit/geom/GeometryQueryTool.hpp
===================================================================
--- cgm/branches/cubit/geom/GeometryQueryTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GeometryQueryTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -27,6 +27,7 @@
 #include "DLIList.hpp"
 #include "GeometryQueryEngine.hpp"
 #include "IntermediateGeomEngine.hpp"
+#include "CGMHistory.hpp"
 
 class RefGroup;
 class Body;
@@ -74,6 +75,12 @@
 class CubitTransformMatrix;
 class TBOwner;
 
+#ifdef PROE
+class RefPart;
+class RefAssembly;
+#endif
+
+//! Interface class for querying geometry. 
 class CUBIT_GEOM_EXPORT GeometryQueryTool
 {
 public :
@@ -81,10 +88,13 @@
   friend class GeometryModifyTool;
    
   bool ige_is_composite(TBOwner *bridge_owner);
+  bool ige_is_composite(TopologyBridge *bridge);
   bool ige_is_partition(TBOwner *bridge_owner);
 
 
-  void ige_remove_modified(DLIList<TopologyBridge*>& geometry_list);
+  void ige_remove_modified(DLIList<Surface*> &all_surfs,
+                                            DLIList<Curve*> &all_curves,
+                                            DLIList<Point*> &all_points);
 
   static GeometryQueryTool* instance( GeometryQueryEngine* gqePtr = NULL);
   /**<
@@ -105,99 +115,205 @@
   ~GeometryQueryTool();
   ///<  Destructor.
 
+  static void delete_instance();
+  
+  //!
+  //! \brief Estimates a good merge tolerance for the volumes passed in.
+  //!
+  double estimate_merge_tolerance(DLIList<RefVolume*> &vol_list,
+                                                    bool accurate_in = false,
+                                                    bool report_in = false,
+                                                    double lo_val_in = -1.0, 
+                                                    double hi_val_in = -1.0,
+                                                    int num_calculations_in = 10,
+                                                    bool return_calculations_in = false,
+                                                    DLIList<double> *merge_tols = NULL,
+                                                    DLIList<int> *num_proximities = NULL);
 
+  //!
+  //! \brief Find all of the volumes that do not contain any merged entities.
+  //!
+  void find_floating_volumes(DLIList<RefVolume*> &vol_list,
+                             DLIList<RefVolume*> &floating_list);
+
+  //!
+  //! \brief Find the nonmanifold curves in the passed-in volumes based on what is merged.
+  //!
+  void find_nonmanifold_curves(DLIList<RefVolume*> &vol_list, DLIList<RefEdge*> &curve_list);
+
+  //!
+  //! \brief Find the nonmanifold vertices in the passed-in volumes based on what is merged.
+  //!
+  void find_nonmanifold_vertices(DLIList<RefVolume*> &vol_list, DLIList<RefVertex*> &vertex_list);
+
   CubitStatus register_intermediate_engine( IntermediateGeomEngine* engine );
+  void unregister_intermediate_engine( IntermediateGeomEngine* engine );
 
   void ige_remove_imprint_attributes_after_modify(DLIList<BodySM*> &old_sms,
                                               DLIList<BodySM*> &new_sms);
   void ige_push_imprint_attributes_before_modify
                                 ( DLIList<BodySM*> &geom_list );
+  void ige_push_named_attributes_to_curves_and_points
+                                ( DLIList<TopologyBridge*> &tb_list, const char *name_in );
   void ige_export_geom( DLIList<TopologyBridge*> &geom_list );
   void ige_import_geom( DLIList<TopologyBridge*> &geom_list );
   void ige_remove_attributes( DLIList<TopologyBridge*> &geom_list );
   void ige_attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
                                                     DLIList<TopologyBridge*> &att_tbs,
-                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<TopologyBridge*> &tb_list,
                                                         DLIList<Body*> &old_bodies);
   void ige_remove_attributes_from_unmodifed_virtual(DLIList<TopologyBridge*> &bridges);
+  
+  //Using the source_bridge, finds all bridges that actually have a BridgeManager the owner.
+  //This is for obtaining the real TopologyBridge when all you have is a  TopologyBridge 
+  //that is Partition Entity.
+  void get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                             DLIList<TopologyBridge*> &tbs );
 
   /*! <HR><H1> global-list-functions Global entity list functions </H1>*/
 
-  CubitStatus cubit_entity_list( const char* keyword,
-                                 DLIList<CubitEntity*> &entity_list,
-                                 const CubitBoolean print_errors = CUBIT_TRUE);
-  /**<  return ref entities in a generic cubit entity list (overwrites list).
-    *  returns CUBIT_FAILURE if keyword is not a ref entity name, and
-    *  optionally prints error message
-    */
+  //
+  // Returns ref entities in a generic cubit entity list (overwrites list).
+  // returns CUBIT_FAILURE if keyword is not a ref entity name, and
+  // optionally prints error message
+  //
+  //CubitStatus cubit_entity_list( const char* keyword,
+  //                               DLIList<CubitEntity*> &entity_list,
+  //                               const CubitBoolean print_errors = CUBIT_TRUE);
 
+  //!
+  //! \brief Return ref entities in entity_list (overwrites list).
+  //! returns CUBIT_FAILURE if keyword is not a ref entity name,
+  //! and optionally prints error message
+  //!  
+
   CubitStatus ref_entity_list( char const* keyword,
                                DLIList<RefEntity*> &entity_list,
                                const CubitBoolean print_errors = CUBIT_TRUE);
-  /**<  return ref entities in entity_list (overwrites list).
-    *  returns CUBIT_FAILURE if keyword is not a ref entity name,
-    *  and optionally prints error message
-    */
 
+  //! \brief Returns the bounding box of the model.  Include free entities.
   CubitBox model_bounding_box();
+
+  /*! Returns the bounding box of all bodies in the model. Excludes
+  free entities.*/
+  //! \brief Returns the bounding box of all bodies in the model. 
+  CubitBox bounding_box_of_bodies();
+
+
+  //! \brief Returns all the bodies in the current session. 
   void bodies (DLIList<Body*> &bodies);
+
+  //! \brief Returns all volumes in the current session. 
   void ref_volumes (DLIList<RefVolume*> &ref_volumes);
+
+  //! \brief Returns all groups in the current session. 
   void ref_groups (DLIList<RefGroup*> &ref_groups);
+
+  //! \brief Returns all surfaces in the current session. 
   void ref_faces (DLIList<RefFace*> &ref_faces);
+
+  //! \brief Returns all curves in the current session. 
   void ref_edges (DLIList<RefEdge*> &ref_edges);
+
+  //! \brief Returns all the vertices in the current session. 
   void ref_vertices (DLIList<RefVertex*> &ref_vertices);
+
+#ifdef PROE
+  void ref_parts (DLIList<RefPart*> &ref_parts);
+  void ref_assemblies (DLIList<RefAssembly*> &ref_assemblies);
+#endif //PROE
   ///< Append global lists to arguments
 
+  //! \brief Number of bodies in current session.
   int num_bodies() const;
+
+  //! \brief Number of volumes in current session.
   int num_ref_volumes() const;
+
+  //! \brief Number of groups in current session.
   int num_ref_groups() const;
+
+  //! \brief Number of surfaces in current session.
   int num_ref_faces() const;
+
+  //! \brief Number of curves in current session.
   int num_ref_edges() const;
+
+  //! \brief Number of vertices in current session.
   int num_ref_vertices() const;
-  ///< Return number of entities of the specified type
 
+  //! \brief Get RefEntity by type name and id.
   RefEntity *get_ref_entity (const char *type, int id);
+
+  //! \brief Get a RefEntity of the specified type and id.
   RefEntity *get_ref_entity (const type_info& type, int id);
-  ///< Get a ref entity of the specified type and id
 
+  //! \brief Get entity by id.
   Body *get_body ( int id );
+
+  //! \brief Get entity by id.
   RefVolume *get_ref_volume ( int id );
+
+  //! \brief Get entity by id.
   RefGroup *get_ref_group ( int id );
+
+  //! \brief Get entity by id.
   RefFace *get_ref_face ( int id );
+
+  //! \brief Get entity by id.
   RefEdge *get_ref_edge ( int id );
+
+  //! \brief Get entity by id.
   RefVertex *get_ref_vertex ( int id );
-  ///< Get an entity of the specified type and id
+  
 
+  //! \brief Get the first entity in the global list of the specified type
   Body *get_first_body ();
+  //! \brief Get the first entity in the global list of the specified type
   RefVolume *get_first_ref_volume ();
+  //! \brief Get the first entity in the global list of the specified type
   RefGroup *get_first_ref_group ();
+  //! \brief Get the first entity in the global list of the specified type
   RefFace *get_first_ref_face ();
+  //! \brief Get the first entity in the global list of the specified type
   RefEdge *get_first_ref_edge ();
+  //! \brief Get the first entity in the global list of the specified type
   RefVertex *get_first_ref_vertex ();
-  ///< Get the first entity in the global list of the specified type
 
+  //! \brief Get the next entity in the global list of the specified type
   Body *get_next_body ();
+  //! \brief Get the next entity in the global list of the specified type
   RefVolume *get_next_ref_volume ();
+  //! \brief Get the next entity in the global list of the specified type
   RefGroup *get_next_ref_group ();
+  //! \brief Get the next entity in the global list of the specified type
   RefFace *get_next_ref_face ();
+  //! \brief Get the next entity in the global list of the specified type
   RefEdge *get_next_ref_edge ();
+  //! \brief Get the next entity in the global list of the specified type
   RefVertex *get_next_ref_vertex ();
-  ///< Get the next entity in the global list of the specified type
 
+  ///! \brief Get the last entity in the global list of the specified type
   Body *get_last_body ();
+  ///! \brief Get the last entity in the global list of the specified type
   RefVolume *get_last_ref_volume ();
+  ///! \brief Get the last entity in the global list of the specified type
   RefGroup *get_last_ref_group ();
+  ///! \brief Get the last entity in the global list of the specified type
   RefFace *get_last_ref_face ();
+  ///! \brief Get the last entity in the global list of the specified type
   RefEdge *get_last_ref_edge ();
+  ///! \brief Get the last entity in the global list of the specified type
   RefVertex *get_last_ref_vertex ();
-  /**< Get the last entity in the global list of the specified type
-
-    <HR><H3>File operations (import, export)</H3>
-  */
-
+  
+  
+  //! \brief Get all free surfaces, curves, and vertices 
   CubitStatus get_free_ref_entities(DLIList<RefEntity*> &free_entities);
-    //- returns the list of free entities in the model
 
+  //! \brief Get the free entities connected to, but not necessarily
+  //! vertically related to, the entity.  - If merge_option, then take
+  //! into account the fact that the model may be merged (it's slower
+  //! that way).
   void get_connected_free_ref_entities(
     RefEntity *entity,
     const int merge_option,
@@ -205,71 +321,57 @@
     DLIList<RefFace*> &ref_face_list,
     DLIList<RefEdge*> &ref_edge_list,
     DLIList<RefVertex*> &ref_vertex_list );
-    //- get the free entities connected to, but not necessarily
-    //- vertically related to, the entity.  - If merge_option, then take
-    //- into account the fact that the model may be merged (it's slower
-    //- that way).
 
+  //! \brief Saves out a temporary geometry file containing specified entities
+  //! that are of the same geometry engine. 
   CubitStatus save_temp_geom_files( DLIList<RefEntity*>& ref_entity_list,
                                   const char* filename,
                                   const CubitString &cubit_version,
                                   std::list<CubitString> &files_written,
                                   std::list<CubitString> &types_written);
 
+
+  //!
+  //! * Export entities to a solid model file.
+  //!  *  \arg ref_entity_list
+  //!  *  A list of RefEntities to be exported or saved to a file.
+  //!  *  \arg file_name
+  //!  *  The name of the file to write to.
+  //!  *  \arg file_type
+  //!  *  An optional type of file.
+  //!  *  \arg logfile_name
+  //!  *  Optional - name of logfile.
+  //!  *   \return  CubitStatus - success/failure
+  //!  *
+  //!  *  Export the current CUBIT geometry (everything in the Model) to a
+  //!  *  solid model format. Valid file types are:
+  //!  *     "ACIS_SAT"    --  ACIS ASCII (SAT) file format
+  //!  *     "ACIS_SAB"    --  ACIS BINARY (SAB) file format
+  //!  *     "ACIS_DEBUG"  --  ACIS ASCII debug format
+  //!  *     "IGES"        --  IGES file
+  //!  *     "STEP"        --  STEP file
+  //!  No logfile gets created for SAB/SAT files, but for IGES and
+  //!  STEP file a logfile always gets created.  Default filenames
+  //!  are assigned if one is not given (iges_export.log, step_export.log).
+  //!  
+  //!  The function returns CUBIT_FAILURE if anything goes wrong with
+  //!  export - improper file type, inaccessible file, mismatch between
+  //!  the underlying representation and file type. It returns
+  //!  CUBIT_SUCCESS if everything goes well.
+  //!  
+  //!  NOTE: if the ref_entity_list is empty, GeometryQueryTool gets the list of
+  //!  all entities in the current model, including free ref entities
+  //! \brief Save a geometry file containing specified entities
+  //! that are of the same geometry engine. 
   CubitStatus export_solid_model( DLIList<RefEntity*>& ref_entity_list,
                                   const char* filename,
                                   const char * filetype,
                                   int &num_ents_exported,
                                   const CubitString &cubit_version,
                                   const char* logfile_name = NULL );
-  /**<
-   * Export entities to a solid model file.
-    *  \arg ref_entity_list
-    *  A list of RefEntities to be exported or saved to a file.
-    *  \arg file_name
-    *  The name of the file to write to.
-    *  \arg file_type
-    *  An optional type of file.
-    *  \arg logfile_name
-    *  Optional - name of logfile.
-    *   \return  CubitStatus - success/failure
-    *
-    *  Export the current CUBIT geometry (everything in the Model) to a
-    *  solid model format. Valid file types are:
-    *     "ACIS_SAT"    --  ACIS ASCII (SAT) file format
-    *     "ACIS_SAB"    --  ACIS BINARY (SAB) file format
-    *     "ACIS_DEBUG"  --  ACIS ASCII debug format
-    *     "IGES"        --  IGES file
-    *     "STEP"        --  STEP file
-    *  No logfile gets created for SAB/SAT files, but for IGES and
-    *  STEP file a logfile always gets created.  Default filenames
-    *  are assigned if one is not given (iges_export.log, step_export.log).
-    *
-    *  The function returns CUBIT_FAILURE if anything goes wrong with
-    *  export - improper file type, inaccessible file, mismatch between
-    *  the underlying representation and file type. It returns
-    *  CUBIT_SUCCESS if everything goes well.
-    *
-    *  NOTE: if the ref_entity_list is empty, GeometryQueryTool gets the list of
-    *  all entities in the current model, including free ref entities
-    *
-    */
 
-  CubitStatus import_temp_geom_file(FILE* file_ptr,
-                                    const char* file_type );
-
-  CubitStatus import_solid_model(const char* file_name,
-                                 const char* file_type,
-                                 const char* logfile_name = NULL,
-                                 CubitBoolean heal_step = CUBIT_TRUE,
-                                 CubitBoolean import_bodies = CUBIT_TRUE,
-                                 CubitBoolean import_surfaces = CUBIT_TRUE,
-                                 CubitBoolean import_curves = CUBIT_TRUE,
-                                 CubitBoolean import_vertices = CUBIT_TRUE,
-                                 CubitBoolean free_surfaces = CUBIT_TRUE,
-				 DLIList<RefEntity*> *imported_entities = NULL);
-  /**<
-   * Import all or specified entities in a solid model file.
+  /*!
+    Import all or specified entities in a solid model file.
     *  \arg file_ptr
     *  A pointer to the file to read (can be NULL for IGES and STEP files).
     *  \arg file_type
@@ -297,106 +399,120 @@
     *  the underlying representation and file type. It returns
     *  CUBIT_SUCCESS if everything goes well.
     */
+  //! \brief Import a geometry file. 
+  CubitStatus import_solid_model(const char* file_name,
+                                 const char* file_type,
+                                 const char* logfile_name = NULL,
+                                 CubitBoolean heal_step = CUBIT_TRUE,
+                                 CubitBoolean import_bodies = CUBIT_TRUE,
+                                 CubitBoolean import_surfaces = CUBIT_TRUE,
+                                 CubitBoolean import_curves = CUBIT_TRUE,
+                                 CubitBoolean import_vertices = CUBIT_TRUE,
+                                 CubitBoolean free_surfaces = CUBIT_TRUE,
+				 DLIList<RefEntity*> *imported_entities = NULL);
 
-  CubitStatus construct_refentities(DLIList<TopologyBridge*> &topology_bridges,
-                                    DLIList<RefEntity*> *imported_entities = NULL);
-    //- given a list of TB's, construct ref entities for them; if the 2nd list pointer is
-    //- non-NULL, pass back the list of ref entities in that list
-
-  CubitStatus read_geometry_file(char const* fileName,
-                                 char const* includePath = NULL,
-                                 char const* type = "ACIS_SAT");
-  /**<
-   * Read geometry from the specified file.
-    *  \arg filename
-    *  The name of the file to read.
-    *  \arg includePath
-    *  An optional path to be used to search for the file if the file
-    *  is not in the current directory.
-    *  \arg type
-    *  An optional type of file.
-    *   \return  CubitStatus - success/failure
+  /*!
+   * Fire a ray at entities, passing back distances of hits and entities hit
+    * \arg origin
+    * origin of ray
+    * \arg direction
+    * direction of ray
+    * \arg at_entity_list
+    * entities to fire ray at
+    * \arg ray_params
+    * returned array of parameters (distances) along ray at which entities were hit
+    * \arg max_hits
+    * maximum number of hits to return, 0 = unlimited (default)
+    * \arg ray_radius
+    * radius of ray to use for intersecting entities, 0 = use engine default
+    * \arg hit_entity_list (pointer)
+    * entities hit by ray (list length same as ray_params), default NULL
+    * \return - error flag
     *
-    *  Reads a geometry file (named fileName).  If the file cannot be found
-    *  in the current directory, and if includePath is not NULL, the include
-    *  path specified by includePath is added to the file name, and it is
-    *  searched in the given order. The file type specified in the "type"
-    *  argument determines what type of geometry file it is -- the default
-    *  is an ACIS SAT file.
-    *  Supported geometry file types are:
-    *     "ACIS_SAT"  --  ACIS SAT file format
-    *     "ACIS_SAB"  --  ACIS SAB file format (binary)
-    *  The function returns CUBIT_FAILURE if it cannot open the file, or
-    *  the "type" is not known. Otherwise it returns CUBIT_SUCCESS.
+    *  Fire a ray at specified entities, returning the parameters (distances)
+    *  along the ray and optionally the entities hit; return CUBIT_FAILURE if
+    *  error.  Returned lists are appended to.
     */
 
-  int fire_ray(Body* body,
-               const CubitVector ray_point,
-               const CubitVector unit,
-               DLIList<double>& ray_params,
-               DLIList<RefEntity*> *entity_list);
-  /**<
-   * Fire a ray at a body, passing back number and distances of hits.
-    *  \arg body
-    *  Body at which you are firing rays
-    *  \arg ray_point
-    *  beginning point of ray
-    *  \arg unit
-    *  direction of ray (unit vector)
-    * num_hit
-    *-number of bodies hit
-    * ray_params
-    * array of parameters along ray at which bodies were hit
-    * entity_list
-    * entities hit by ray
-    *  \return - error flag
+  //! \brief Fire a ray at entities, passing back distances of hits and entities hit
+  CubitStatus fire_ray( CubitVector &origin,
+                        CubitVector &direction,
+                        DLIList<RefEntity*> &at_entity_list,
+                        DLIList<double> &ray_params,
+                        int max_hits = 0,
+                        double ray_radius = 0.0,
+                        DLIList<RefEntity*> *hit_entity_list_ptr = 0 );
+
+  /*!
+   * Fire a ray at entities, passing back distances of hits and entities hit
+    * \arg origin
+    * origin of ray
+    * \arg direction
+    * direction of ray
+    * \arg at_entity_list
+    * entities to fire ray at
+    * \arg ray_params
+    * returned array of parameters (distances) along ray at which entities were hit
+    * \arg max_hits
+    * maximum number of hits to return, 0 = unlimited (default)
+    * \arg ray_radius
+    * radius of ray to use for intersecting entities, 0 = use engine default
+    * \arg hit_entity_list (pointer)
+    * entities hit by ray (list length same as ray_params), default NULL
+    * \return - error flag
     *
-    *  fire a ray at the specified body, returning the entities
-    *  hit and the parameters along the ray; return CUBIT_FAILURE
-    *  if error
+    *  Fire a ray at specified entities, returning the parameters (distances)
+    *  along the ray and optionally the entities hit; return CUBIT_FAILURE if
+    *  error.  Returned lists are appended to.  NOTE: ALL ENTITIES MUST BE FROM
+    *  THE SAME GEOMETRY ENGINE. 
     */
+  //! \brief Fire a ray at entities, passing back distances of hits and entities hit
+  CubitStatus fire_ray( CubitVector &origin,
+                        CubitVector &direction,
+                        DLIList<TopologyEntity*> &at_entity_list,
+                        DLIList<double> &ray_params,
+                        int max_hits = 0,
+                        double ray_radius = 0.0,
+                        DLIList<TopologyEntity*> *hit_entity_list_ptr = 0 );
+  
+  //! \brief Debugging function.
+  static void geom_debug( DLIList<TopologyEntity*> );
 
-  static void geom_debug( DLIList<TopologyEntity*> );
-  /**<  Temporary debug tool -- Steve Jankovich
-    */
+  //! \brief Set facet box flag
   static void set_facet_bbox( CubitBoolean pass_flag )
       {useFacetBBox = pass_flag;}
+
+  //! \brief Get facet box flag
   static CubitBoolean get_facet_bbox()
       {return useFacetBBox;}
-  /**< get and set the useFacetBBox flag. (compute our own bbox
-    * instead of relying on bad ACIS geometry)
-    */
 
-
+  //! \brief Calls engine version of the active geometry engine.
   CubitString get_engine_version_string();
-  /**<  Calls get_engine_version_string() function of underlying ModelingEngine.
-    */
 
+  //! \brief Set the major/minor version of the active geometry engine.
   CubitStatus set_export_allint_version(int version);
-  /**<  set the major/minor version of the geometry engine
-    */
 
+  //! \brief Get the major/minor version of the active geometry engine.
   int get_allint_version();
-  /**<  get the major/minor version of the geometry engine
-    */
 
+  //! \brief Returns a string with the versions of the active geometry engine.
   CubitStatus list_engine_versions(CubitString &versions);
-  /**<  returns a string with the engine version choices
-    */
 
+  //! \brief Gets solid modeler's resolution absolute tolerance
   double get_sme_resabs_tolerance();
+
+  //! \brief Sets solid modeler's resolution absolute tolerance
   double set_sme_resabs_tolerance( double new_resabs );
-  /**<  Gets/Sets solid modeler's resolution absolute tolerance
-    */
 
+  //! \brief Set solid modeler integer option.
   CubitStatus set_sme_int_option( const char* opt_name, int val );
+  //! \brief Set solid modeler double option.
   CubitStatus set_sme_dbl_option( const char* opt_name, double val );
+  //! \brief Set solid modeler string option.
   CubitStatus set_sme_str_option( const char* opt_name, const char* val );
-  /**<  Set solid modeler options
-    */
 
+
   ///< <HR><H3>Topology/geometry creation functions</H3>
-
   Body* make_Body(BodySM *bodysm_ptr) const;
   RefFace* make_RefFace(Surface* surface_ptr ) const;
   RefEdge* make_RefEdge(Curve* curve_ptr) const;
@@ -404,7 +520,7 @@
 
   static CubitSense relative_sense( Surface* surface1, Surface* surface2 );
 
-  RefFace* make_free_RefFace(Surface *surface_ptr ) const;
+  RefFace* make_free_RefFace(Surface *surface_ptr, bool is_free_surface) const;
   RefEdge* make_free_RefEdge(Curve *curve_ptr ) const;
   RefVertex* make_free_RefVertex(Point *point_ptr) const;
   /**<  These functions can be used to create free ref-entities
@@ -416,13 +532,12 @@
 
   ///<HR><H3>Topology and geometry deletion</H3>
 
+  /*! \brief  Deletes all Bodies in the input list from the model. Their
+    associated Solid Model entities are deleted as well, if they exist,
+    and if remove_solid_model_entities is CUBIT_TRUE.
+    */
   void delete_Body( DLIList<Body*>& body_list );
-  /**<  Deletes all Bodies in the input list from the model. Their
-    *  associated Solid Model entities are deleted as well, if they exist,
-    *  and if remove_solid_model_entities is CUBIT_TRUE.
-    */
 
-  CubitStatus delete_Body( Body* body_ptr );
   /**<  Deletes the input Body from the model.
     *  Its associated Solid Model entities are deleted as well, if
     *  they exist, and if remove_solid_model_entities is CUBIT_TRUE.
@@ -430,96 +545,106 @@
     *  as the Body itself has been deleted.
     *  Returns CUBIT_SUCCESS if all went well, otherwise, CUBIT_FAILURE.
     */
+  //! \brief Deletes a body.
+  CubitStatus delete_Body( Body* body_ptr );
 
-  CubitStatus delete_single_Body( Body* body_ptr );
-  /**< Behaves exactly as delete_Body, but in addition checks to see if
+  /*! Behaves exactly as delete_Body, but in addition checks to see if
     *  children of Body are merged.  In some cases, 2 entities can be
     *  forced-merged, where they are not spatially equal.  This regenerates
     *  the graphics on merged entities so they look correct after a partner
     *  has been deleted.
     */
+  //! \brief Deletes a body.
+  CubitStatus delete_single_Body( Body* body_ptr );
 
+  //! \brief Deletes free RefEnties
   CubitStatus delete_RefEntity( RefEntity* ref_entity_ptr );
+  
+  //! \brief Deletes the RefFace if it is free
   CubitStatus delete_RefFace( RefFace* ref_face_ptr );
+
+  //! \brief Deletes the RefEdge if it is free
   CubitStatus delete_RefEdge( RefEdge* ref_edge_ptr );
+
+  //! \brief Deletes the RefVertex if it is free
   CubitStatus delete_RefVertex( RefVertex* ref_vertex_ptr );
-  /**<  This function is used to delete free-floating RefFaces, RefEdges
-    *  or RefVertex'es.  All underlying VGI and solid model entities (if
-    *  any) are also deleted. The entities will *not* be deleted is
-    *  the input RefEntity has an owner (e.g., if the input RefEdge
-    *  is owned by a RefFace).
-    */
 
   void cleanout_deactivated_geometry();
   void cleanout_temporary_geometry ();
-
+  
+  //! \brief Deletes all geometry.
   void delete_geometry();
 
-  ///< <HR><H3>Miscellaneous geometry evaluation functions</H3>
-
+  
+  /*! \brief  Creates a list of vectors the length of the number_points that
+      interpolate between vector_1 and vector_2.  All of the points
+      will lie on the underlying equation of the refface.
+  */
   CubitStatus interpolate_along_surface( CubitVector *vector_1,
                                          CubitVector *vector_2,
                                          DLIList<CubitVector*> &vector_list,
                                          RefFace* ref_face_ptr,
                                          int number_points ) const;
-  /**<  Creates a list of vectors the length of the number_points that
-    *  interpolate between vector_1 and vector_2.  All of the points
-    *  will lie on the underlying equation of the refface.
+  /*!  \return  CubitBoolean
+    \return - CUBIT_TRUE/CUBIT_FALSE
+    \arg Vec1
+    A reference to the first vector.
+    \arg Vec2
+    A reference to the second vector.
+    \arg tolerance_factor
+    Factor by which the absolute internal tolerance shall be
+    multiplied.
+    *  Returns CUBIT_TRUE if the input Vec1 and Vec2 are spatially
+    equivalent within a tolerance.  The internal spatial tolerance
+    value is multiplied by tolerance_factor before the (spatial)
+    test is done. Else, returns CUBIT_FALSE.
     */
-
+  //! \brief Compares two positions for coincidence.
   CubitBoolean about_spatially_equal (const CubitVector& Vec1,
                                       const CubitVector& Vec2,
                                       double tolerance_factor = 1.0);
-  /**<  \return  CubitBoolean
-    *  \return - CUBIT_TRUE/CUBIT_FALSE
-    *  \arg Vec1
-    *  A reference to the first vector.
-    *  \arg Vec2
-    *  A reference to the second vector.
-    *  \arg tolerance_factor
-    *  Factor by which the absolute internal tolerance shall be
-    *  multiplied.
-    *
-    *  Returns CUBIT_TRUE if the input Vec1 and Vec2 are spatially
-    *  equivalent within a tolerance.  The internal spatial tolerance
-    *  value is multiplied by tolerance_factor before the (spatial)
-    *  test is done. Else, returns CUBIT_FALSE.
-    */
 
+  //! \brief Compares two vertices for coincidence.
   CubitBoolean about_spatially_equal (RefVertex* refVertex1,
                                       RefVertex* refVertex2,
                                       double tolerance_factor = 1.0);
 
+  /*! \brief Calculates internal surface angles given 2 refedges on the
+   * surface.  CoEdge version correctly handles curves in a surface
+   * twice. */
   double geometric_angle(RefEdge* ref_edge_1,
                          RefEdge* ref_edge_2,
                          RefFace* ref_face );
+
+  /*! \brief Calculates internal surface angles given 2 refedges on the
+   surface.  This version correctly handles curves in a surface twice. */
   double geometric_angle(CoEdge* co_edge_1,
                          CoEdge* co_edge_2 );
-  /**< calculates internal surface angles given 2 refedges on the
-   * surface.  CoEdge version correctly handles curves in a surface
-   * twice.
-   */
 
+  /*! \brief Calculate dihedral angle at curve between two surfaces of the
+    volume. */
   double surface_angle( RefFace *ref_face_1, RefFace *ref_face_2,
                         RefEdge *ref_edge = NULL,
                         RefVolume *ref_volume = NULL,
                         double frac = 0.5);
-    /**< Calculate dihedral angle at ref_edge between two faces of the
-     *   volume.
-     */
 
+  /*!  Finds the intersections between a curve and a line  If the bounded flag 
+    *  is true, it finds only those intersections within the parameter range
+    *  of the curve; otherwise it uses the extensions of the curve.  The
+    *  closest option is currently valid only if the curve is straight,
+    *  in which case it will return the 2 closest intersection locations,
+    *  if the straight lines don't actually intersect. The function allocates 
+    *  allocates the CubitVectors in the returned list, so be sure to free them.
+    */
+  //! \brief Finds the intersections of a straight line and a curve.  
   CubitStatus get_intersections( RefEdge* ref_edge1,
                                  CubitVector& point1,
                                  CubitVector& point2,
                                  DLIList<CubitVector*>& intersection_list,
                                  CubitBoolean bounded = CUBIT_FALSE,
                                  CubitBoolean closest = CUBIT_FALSE);
-
-  CubitStatus get_intersections( RefEdge* ref_edge1, RefEdge* ref_edge2,
-                                 DLIList<CubitVector*>& intersection_list,
-                                 CubitBoolean bounded = CUBIT_FALSE,
-                                 CubitBoolean closest = CUBIT_FALSE );
-  /**<  Finds the intersections of the two curves.  If the bounded flag is
+ 
+  /*!  Finds the intersections of the two curves.  If the bounded flag is
     *  true, it finds only those intersections within the parameter range
     *  of both curves; otherwise it uses the extensions of the curves.  The
     *  closest option is currently valid only if both curves are straight,
@@ -529,56 +654,83 @@
     *  curves, unless both curves are linear.  The function allocates the
     *  CubitVectors in the returned list, so be sure to free them.
     */
+  //! \brief Finds the intersections of two curves.  
+  CubitStatus get_intersections( RefEdge* ref_edge1, RefEdge* ref_edge2,
+                                 DLIList<CubitVector*>& intersection_list,
+                                 CubitBoolean bounded = CUBIT_FALSE,
+                                 CubitBoolean closest = CUBIT_FALSE );
 
+  /*! Finds the intersections of the curve and surface.  The curve is extended
+    * if the bounded flag is not false.  The function allocates the CubitVectors
+    * in the returned list, so be sure to free them.
+  */
+  //! \brief Finds the intersections of the curve and surface.  
   CubitStatus get_intersections( RefEdge* ref_edge, RefFace* ref_face,
                                  DLIList<CubitVector*>& intersection_list,
                                  CubitBoolean bounded = CUBIT_FALSE );
-  /**< Finds the intersections of the curve and surface.  The curve is extended
-    * if the bounded flag is not false.  The function allocates the CubitVectors
-    * in the returned list, so be sure to free them.
+
+  /*! Gets the extrema position along the first given direction. If there
+    * is more than one extrema position, the other directions will be used
+    * to determine a unique position.  Directions 2 and 3 can be NULL.
+    * Entities supported include bodies, volumes, surfaces, curves and
+    * vertices.  
     */
-
+  //! \brief Gets extrema position on an entity.
   CubitStatus entity_extrema( RefEntity *ref_entity_ptr,
                               const CubitVector *dir1,
                               const CubitVector *dir2,
                               const CubitVector *dir3,
                               CubitVector &extrema,
                               RefEntity *&extrema_entity_ptr );
+
+  /*! Gets the extrema position along the first given direction. If there
+    * is more than one extrema position, the other directions will be used
+    * to determine a unique position.  Directions 2 and 3 can be NULL.
+    * Entities supported include bodies, volumes, surfaces, curves and
+    * vertices.  The entity the extrema is found on is also returned.
+    */
+  //! \brief Gets extrema position on a list of entities.
   CubitStatus entity_extrema( DLIList<RefEntity*> &ref_entity_list,
                               const CubitVector *dir1,
                               const CubitVector *dir2,
                               const CubitVector *dir3,
                               CubitVector &extrema,
                               RefEntity *&extrema_entity_ptr );
-  /** Gets the extrema position along the first given direction. If there
-    * is more than one extrema position, the other directions will be used
-    * to determine a unique position.  Directions 2 and 3 can be NULL.
-    * Entities supported include bodies, volumes, surfaces, curves and
-    * vertices.  The entity the extrema is found on is also returned.
-    */
 
+  /*! Gets the minimum distance between two entities and the closest positions
+    * on those entities. Supports vertices, curves, surfaces, volumes and bodies.
+  */
+  //! \brief Get the minimum distance between two entities.
   CubitStatus entity_entity_distance( GeometryEntity *ge1,
-                                           GeometryEntity *ge2,
-                                           CubitVector &pos1, CubitVector &pos2,
-                                           double &distance );
+                                      GeometryEntity *ge2,
+                                      CubitVector &pos1, CubitVector &pos2,
+                                      double &distance );
+
+  /*! Gets the minimum distance between two entities and the closest positions
+    on those entities. Supports vertices, curves, surfaces, volumes and bodies.
+  */
+  //! \brief Get the minimum distance between two entities. (CGM internal use)
   CubitStatus entity_entity_distance( RefEntity *ref_entity_ptr1,
                                       RefEntity *ref_entity_ptr2,
                                       CubitVector &pos1, CubitVector &pos2,
                                       double &distance );
-  /** Gets the minimum distance between two entities and the closest positions
-    * on those entities. Supports vertices, curves, surfaces, volumes and bodies.
-    */
 
-  CubitBox bounding_box_of_bodies();
-  /**<  returns the bounding box of all bodies in the model
-    */
 
-  ///< <HR><H3>Merging functions.</H3>
+  //! \brief Resets geometry factor back to 500.0
+  static void reset_geometry_factor();
+  
+  //! \brief Sets geometry factor. 
+  static void set_geometry_factor( double fac );
 
-  static void set_geometry_factor( double fac );
+  //! \brief Gets geometry factor. 
   static double get_geometry_factor();
+
+  //! \brief Sets bboxMergeTest variable.
   static void set_merge_test_bbox(CubitBoolean tof);
+
+  //! \brief Gets bboxMergeTest variable.
   static CubitBoolean get_merge_test_bbox();
+
   static void set_merge_test_internal(int tof);
   static int get_merge_test_internal();
   static void set_sliver_curve_cleanup_tolerance( double tol );
@@ -586,22 +738,17 @@
   static double get_sliver_curve_cleanup_tolerance(); 
   static double get_sliver_surface_cleanup_tolerance(); 
 
-  //Initializes all settings of this class
+  //! \brief Initializes all settings of this class
   static void initialize_settings();
 
+  //! \brief Causes attributes hanging on entities to be applied.
   static CubitStatus import_actuate( DLIList<RefEntity*> &entity_list );
 
+  /*! \brief Returns CUBIT_TRUE if all the entities have the same geometric query engine and
+    if that is the same one as the default. */
   CubitBoolean same_query_engine(DLIList<TopologyEntity*> &topo_list) const;
-  /**<  Returns CUBIT_TRUE if all the entities have the same geometric query engine and
-    *  if that is the same one as the default.
-    */
 
-  GeometryQueryEngine* common_query_engine(
-    DLIList<TopologyEntity*>& topology_list,
-    DLIList<TopologyBridge*>& engine_bridges,
-    CubitBoolean allow_default_engine
-    = CUBIT_FALSE ) const;
-  /**<  \return GeometryQueryEngine*
+  /*!  \return GeometryQueryEngine*
     *   A GeometryQueryEngine common at least one
     *   TopologyBridge of each of the passed TopologyEntities, or
     *   NULL if no common geometry engine is found.
@@ -624,99 +771,174 @@
     *   if possible, otherwise with the first topology bridge attached
     *   to each of the passed TopologyEntities.
     */
+  //! \brief Gets geometry beloning to a common modeling engine. 
+  GeometryQueryEngine* common_query_engine(
+    DLIList<TopologyEntity*>& topology_list,
+    DLIList<TopologyBridge*>& engine_bridges,
+    CubitBoolean allow_default_engine
+    = CUBIT_FALSE ) const;
 
+  //! \brief Determine if any of the input entities contain the given query engine
   CubitBoolean does_geom_contain_query_engine(DLIList<TopologyEntity*> &topo_list,
                                               GeometryQueryEngine *engine) const;
-  /**<  \return CubitBoolean
-    *   Determine if any of the input entities contain the given query engine
-    */
 
+  //! \brief Determine if any of the input entities contain the given query engine
   CubitBoolean does_geom_contain_query_engine(DLIList<RefEntity*> &ref_entity_list,
                                               GeometryQueryEngine *engine,
                                               CubitBoolean children_too = CUBIT_FALSE) const;
-  /**<  \return CubitBoolean
-    *   Determine if any of the input entities contain the given query engine
-    */
 
+  //! \brief Retrieves the TopologyEntity from the underlying TopologyBridge
   TopologyEntity* entity_from_bridge( TopologyBridge* bridge_ptr ) const;
 
+  //! \brief Adds a geometry query engine to the list
   void add_gqe(GeometryQueryEngine *gqe_ptr);
-    /**< add a geometry query engine to the list
-     */
 
+  /*! \brief Removes a geometry query engine from the list. Returns CUBIT_FAILURE
+     if it wasn't in the list */
   CubitStatus remove_gqe(GeometryQueryEngine *gqe_ptr);
-    /**< remove a geometry query engine from the list; returns CUBIT_FAILURE
-     *   if it wasn't on the list
-     */
 
+  //! \brief Return the list of GeometryQureyEngines.
   void get_gqe_list(DLIList<GeometryQueryEngine*> &gqe_list);
-    /**< return the list of gqe's
-     */
 
+  //! \brief Returns the first gqe on the list.
   GeometryQueryEngine *get_gqe();
-    /**< return the first gqe on the list
-     */
 
+  //! \brief Set the default GeometryQueryEngine.
   CubitStatus set_default_gqe(GeometryQueryEngine* gqe);
-  /**< set the default GeometryQueryEngine
-   */
 
   bool contains_intermediate_geometry(RefEntity*) const;
   bool contains_intermediate_geometry(DLIList<RefEntity*>& ref_entitylist) const;
   bool is_intermediate_geometry(RefEntity*) const;
   bool is_intermediate_geometry(TopologyBridge*) const;
 
-//  GeometryQueryEngine *get_gqe(const EntityType gqe_type);
-    /**< return the gqe of the specified type
-     */
-
+  /*!- Remove this entity and any dead children where
+  a dead child a) has no parent entities and b) has no topology_bridges. */
   CubitStatus destroy_dead_entity( TopologyEntity* topo_ent, bool top = true ) const;
-    //- Remove this entity and any dead children where
-    //- a dead child a) has no parent entities and b)
-    //- has no topology_bridges.
 
-  //Translate
-  CubitStatus translate( Body* entity, const CubitVector& delta,
-                         bool check_to_transform = true);
-  CubitStatus translate( BasicTopologyEntity* entity, const CubitVector& delta,
-                         bool check_to_transform = true);
+  //! \brief Translate a Body some delta.
+  CubitStatus translate( Body* entity, const CubitVector& delta, bool check_to_transform = true,
+                         bool preview = false );
 
-  //Rotate
-  CubitStatus rotate   ( Body* entity, const CubitVector& axis, double degrees,
-                         bool check_to_transform = true);
-  CubitStatus rotate   ( Body* entity,
-                         const CubitVector& point,
-                         const CubitVector& direction,
-                         double degrees,
-                         bool check_to_transform = true);
-  CubitStatus rotate   ( BasicTopologyEntity* entity, const CubitVector& axis, double degrees,
-                         bool check_to_transform = true);
+  //! \brief Translate a BasicTopologyEntity some delta.
+  CubitStatus translate( BasicTopologyEntity* entity, const CubitVector& delta, bool check_to_transform = true,
+                         bool preview = false );
 
-  //Scale
-  CubitStatus scale    ( Body* entity, double factor, bool check_to_transform = true);
-  CubitStatus scale    ( Body* entity, const CubitVector& factors, bool check_to_transform = true);
-  CubitStatus scale    ( BasicTopologyEntity* entity, double factor, bool check_to_transform = true);
-  CubitStatus scale    ( BasicTopologyEntity* entity, const CubitVector& factors,
-                         bool check_to_transform = true);
+  void translate( DLIList<RefEntity*> &entities_to_transform,
+          double x, double y, double z, bool check_before_transforming,
+          DLIList<RefEntity*> &entities_transformed,
+          bool preview = false );
 
-  //Reflect
-  CubitStatus reflect  ( DLIList<Body*> bodies, const CubitVector& axis );
-  CubitStatus reflect  ( BasicTopologyEntity* entity, const CubitVector& axis,
-                         bool check_to_transform = true);
+
+  //! \brief Rotate a Body an angle about an axis. 
+  CubitStatus rotate( Body* entity, const CubitVector& axis, double degrees, bool check_to_transform = true,
+                      bool preview = false );
+
+  //! \brief Rotate a Body an angle about an axis, defined by a point and a 
+  //! direction.
+  CubitStatus rotate( Body* entity,
+                      const CubitVector& point,
+                      const CubitVector& direction,
+                      double degrees,
+                      bool check_to_transform = true,
+                      bool preview = false);
+
+  CubitStatus rotate( DLIList<RefEntity*> &entities_to_transform,  
+                      const CubitVector& point,
+                      const CubitVector& direction,
+                      double degrees,
+                      bool check_to_transform, 
+                      DLIList<RefEntity*> &entities_transformed,
+                      bool preview = false);
+
+  //! \brief Rotate a BacisTopologyEntity an angle about an axis.
+  CubitStatus rotate( BasicTopologyEntity* entity, 
+                      const CubitVector& axis, 
+                      double degrees,
+                      bool check_to_transform = true,
+                      bool preview = false);
+
+  //! \brief Scale a Body.
+  CubitStatus scale( Body* entity, double factor, bool check_to_transform = true, bool preview = false);
+
+  //! \brief Scale a Body different factors in x, y, and z.
+  CubitStatus scale( Body* entity, const CubitVector& factors, bool check_to_transform = true, bool preview = false);
+
+  //! \brief Scale a BasicTopologyEntity. 
+  CubitStatus scale( BasicTopologyEntity* entity, double factor, bool check_to_transform = true, bool preview = false);
+
+  //! \brief Scale a BasicTopologyEntity different factors in x, y, and z.
+  CubitStatus scale( BasicTopologyEntity* entity, const CubitVector& factors,bool check_to_transform = true,
+                     bool preview = false);
+
+  void scale( DLIList<RefEntity*> &entities_to_transform, 
+              double scale_x, double scale_y, double scale_z, 
+              bool check_to_transform, 
+              DLIList<RefEntity*> &entities_scaled,
+              bool preview = false);
+
+  //! \brief Reflect a list of bodies about a plane defined by an axis.
+  CubitStatus reflect( DLIList<Body*> bodies, const CubitVector& axis, bool preview = false );
+
+  //! \brief Reflect a BasicTopologyEntity about a plane defined by an axis.
+  CubitStatus reflect( BasicTopologyEntity* entity, 
+                       const CubitVector& axis,
+                       bool check_to_transform = true,
+                       bool preview = false);
+
+  void reflect( DLIList<RefEntity*> &entities_to_transform,
+                            double x, double y, double z, 
+                            bool check_before_transforming,
+                            DLIList<RefEntity*> &entities_transformed,
+                            bool preview = false);
+
+  //! \brief Need to deprecate.
   CubitStatus restore_transform( Body* body );
 
+  /*! Query to determine if volumes intersect, share common volume.
+  Returns CUBIT_TRUE if the two volumes overlap, CUBIT_FALSE if they don't
+  overlap.  If the volumes are touching the function should return CUBIT_FALSE.
+  volume_1, 
+  volume_2
+  The two volume pointers that are being tested for overlap.
+  The function uses the intersect call to test if the volumes 
+  are overlaping.  The full intersect Boolean is needed to see if
+  the volumes actually overlap and don't just touch. */
+  //! \brief Query to determine if volumes intersect, share common volume.
+  CubitBoolean volumes_overlap( RefVolume *volume_1, RefVolume *volume_2);
+
+  /*! Query to determine if bodies intersect, share common volume.
+  Returns CUBIT_TRUE if the two bodies overlap, CUBIT_FALSE if they don't
+  overlap.  If the bodies are touching the function should return CUBIT_FALSE.
+  body_ptr_1, body_ptr_2
+  The two body pointers that are being tested for overlap.
+  The function uses the intersect call to test if the bodies
+  are overlaping.  The full intersect Boolean is needed to see if
+  the bodies actually overlap and don't just touch. */
+  //! \brief Query to determine if bodies intersect, share common volume.
   CubitBoolean bodies_overlap( Body *body_ptr_1, Body *body_ptr_2 );
 
-    //R CubitBoolean
-    //R- CUBIT_TRUE if the two bodies overlap, CUBIT_FALSE if they don't
-    //R- overlap.  If the bodies are touching the function
-    //R- should return CUBIT_FALSE.
-    //I body_ptr_1, body_ptr_2
-    //I- The two body pointers that are being tested for overlap.
-    //-  The function uses the intersect call to test if the bodies
-    //-  are overlaping.  The full intersect Boolean is needed to see if
-    //-  the bodies actually overlap and don't just touch.
+  //! Given a list of TB's, construct ref entities for them; if the 2nd list pointer is
+  //! non-NULL, pass back the list of ref entities in that list
+  CubitStatus construct_refentities(DLIList<TopologyBridge*> &topology_bridges,
+                                    DLIList<RefEntity*> *imported_entities = NULL);
 
+  /*! When importing a cub file, embedded in the cub file is how many 
+      geometry entities it is supposed to restore.  If geometry that 
+      you are improrting is merged with geometry already in the session, 
+      you need to keep track of how many geometry entieies get 'merged-away' 
+      like this so that import does not fail.  Taking into account 
+      the 'merged-away' geometry allows CUBIT to successfully import 
+      when you have geometry that will merge-away. */
+  /*! \brief Variable needed when importing geometry that will be 
+    merged-away with already existing geometry in the session */
+  static CubitBoolean trackMergedAwayEnts;
+
+
+  static DLIList<int> uidsOfImportingEnts;
+  static int entitiesMergedAway; 
+
+  CGMHistory& history();
+
 protected :
 
   GeometryQueryTool(GeometryQueryEngine* GQEPtr);
@@ -750,6 +972,11 @@
     // check for mergeable sense entity, which is a child of the entity pointed
     // to by a merge attribute on bridge, which corresponds to re_ptr
 
+  
+  void get_merged_away_free_entities( DLIList<RefEntity*> &ref_ents,
+                                      DLIList<TopologyBridge*> &free_ents );
+
+
   CubitStatus straightline_intersections( RefEdge* ref_edge1,
                                  CubitVector & origin2,
                                  CubitVector & dir2,
@@ -757,18 +984,15 @@
                                  CubitBoolean bounded = CUBIT_FALSE,
                                  CubitBoolean closest = CUBIT_FALSE);
 
+  //! static pointer to the unique instance of this class.
   static GeometryQueryTool* instance_;
-  /**<  static pointer to the unique instance of this class.
-    */
 
+  //! For use in calculating a bounding box, you can do it based on
+  //! a set of facets, rather than what default modeling engine  uses.
   static CubitBoolean useFacetBBox;
-  /**< For use in calculating a bounding box, you can do it based on
-    *  a set of facets, rather than what default modeling engine  uses.
-    */
 
+  //! The list of geometry query engines
   DLIList<GeometryQueryEngine*> gqeList;
-  /**<  The list of geometry query engines
-    */
 
   struct IGEComp : public std::binary_function<IntermediateGeomEngine*,
                                               IntermediateGeomEngine*,
@@ -780,29 +1004,29 @@
   typedef std::set<IntermediateGeomEngine*,IGEComp> IGESet;
   IGESet igeSet;
 
+  //! \brief The default geometry query engine
   GeometryQueryEngine *default_gqe;
-  /**<  The default geometry query engine
-    */
 
+  //! After imprinting, an attempt at removing sliver curves is made.
+  //! Curves less than this tolerance will be removed.
   static double curveSliverCleanUpTolerance;
-  // After imprinting, an attempt at removing sliver curves is made.
-  // Curves less than this tolerance will be removed.
 
+  //! After imprinting, an attempt at removing sliver surfaces is made.
+  //! Removes sliver surfaces whose maximum gap distance among the long 
+  //! edges is smaller than the tolerance and who have at most three long edges. 
   static double surfaceSliverCleanUpTolerance;
-  // After imprinting, an attempt at removing sliver surfaces is made.
-  // Removes sliver surfaces whose maximum gap distance among the long 
-  // edges is smaller than the tolerance and who have at most three long edges. 
 
+  //!  This factor is the the multiplier for the ACIS resabs
+  //!  when comparingcurves.  ALWAYS when using a multiplier
+  //!  use this factor for consistancy.
   static double geometryToleranceFactor;
-  /**<  This factor is the the multiplier for the ACIS resabs
-    *  when comparingcurves.  ALWAYS when using a multiplier
-    *  use this factor for consistancy.
-    */
 
   static CubitBoolean bboxMergeTest;
-  static int internalSurfaceMergeTest; //0=off, 1=all, 2=splines only
-  ///<  Options for refface merging.
 
+  //! Options for refface merging.
+  //! 0=off, 1=all, 2=splines only
+  static int internalSurfaceMergeTest; 
+
   int maxPersistentBodyId;
   int maxPersistentRefVolumeId;
   int maxPersistentRefGroupId;
@@ -812,8 +1036,14 @@
 
   static const int CGM_MAJOR_VERSION;
   static const int CGM_MINOR_VERSION;
+
+  CGMHistory mHistory;
 };
 
+inline void GeometryQueryTool::reset_geometry_factor()
+{
+  geometryToleranceFactor = DEFAULT_GEOM_FACTOR;
+}
 
 inline void GeometryQueryTool::set_geometry_factor( double factor )
 {

Added: cgm/branches/cubit/geom/GfxPreview.cpp
===================================================================
--- cgm/branches/cubit/geom/GfxPreview.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/GfxPreview.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,293 @@
+
+
+#include "GfxPreview.hpp"
+#include "GMem.hpp"
+#include "CubitVector.hpp"
+#include "Curve.hpp"
+#include "Surface.hpp"
+#include "GeometryQueryEngine.hpp"
+#include "Point.hpp"
+#include <assert.h>
+
+GfxPreview* GfxPreview::mInstance = 0;
+
+GfxPreview::GfxPreview()
+{
+  if(mInstance)
+  {
+    assert(0);
+    // if you want a new instance in place of a previous one,
+    // delete the previous one first
+  }
+  mInstance = this;
+}
+
+GfxPreview::~GfxPreview()
+{
+  mInstance = 0;
+}
+
+
+// This clears preview data ONLY
+void GfxPreview::clear()
+{
+  if(!mInstance) return;
+  mInstance->p_clear();
+}
+
+// causes the current window to be redrawn
+void GfxPreview::flush()
+{
+  if(!mInstance) return;
+  mInstance->p_flush();
+}
+
+// Geometry Drawing Functions
+    
+void GfxPreview::draw_ref_entity(RefEntity* entity, int color, CubitTransformMatrix* mat)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_entity(entity, color, mat);
+}
+
+void GfxPreview::draw_ref_vertex(RefVertex* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_vertex(entity, color);
+}
+
+void GfxPreview::draw_ref_edge(RefEdge* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_edge(entity, color);
+}
+
+void GfxPreview::draw_ref_face(RefFace* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_face(entity, color);
+}
+
+void GfxPreview::draw_ref_face_edges(RefFace* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_face_edges(entity, color);
+}
+
+void GfxPreview::draw_ref_volume(RefVolume* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_volume(entity, color);
+}
+
+void GfxPreview::draw_ref_volume_edges(RefVolume* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_volume_edges(entity, color);
+}
+
+void GfxPreview::draw_ref_body(Body* entity, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_ref_body(entity, color);
+}
+
+// Generic Primitive Drawing Functions
+
+void GfxPreview::draw_box(CubitBox& box, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_box(box, color);
+}
+
+// draw point x,y,z of color
+void GfxPreview::draw_point(float x, float y, float z, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_point(x, y, z, color);
+}
+
+void GfxPreview::draw_point(const CubitVector& vector, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_point(vector, color);
+}
+
+void GfxPreview::draw_point(CubitVector* vector, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_point(*vector, color);
+}
+
+// draw line of points {x,y,z}, {x,y,z} of color
+void GfxPreview::draw_line(float x1, float y1, float z1, float x2, float y2, float z2, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_line(x1, y1, z1, x2, y2, z2, color);
+}
+
+void GfxPreview::draw_line(const CubitVector& x, const CubitVector& y, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_line(x, y, color);
+}
+
+// draw a polyline with a number of points of a color
+void GfxPreview::draw_polyline(const GPoint* points, int num_points, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_polyline(points, num_points, color);
+}
+
+// draw polygons given the coordinates and the connectivity.  Note that the
+// connectivity (face_list) is given as the number of points in the polygon 
+// followed by the point ids for that polygon.  So, the num_face_points is
+// the total number of data points in the face_list such that
+// num_face_points = number of points + number of polygons
+void GfxPreview::draw_polygons(int num_points, const float* xyzs, int num_face_points, 
+                               const int* face_list, int color )
+{
+  if (!mInstance) 
+    return;
+  mInstance->p_draw_polygons( num_points, xyzs, num_face_points, face_list, color);
+}
+
+// draw a polyline with a number of points of a color
+void GfxPreview::draw_polygon(const GPoint* points, int num_points, int color, int border_color, bool filled)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_polygon(points, num_points, color, border_color, filled);
+}
+
+// draw a quad of a color
+void GfxPreview::draw_quad(const GPoint* points, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_quad(points, color);
+}
+
+// draw a tri of a color
+void GfxPreview::draw_tri(const GPoint* points, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_tri(points, color);
+}
+
+void GfxPreview::draw_vector(const CubitVector& tail, const CubitVector& head, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_vector(tail, head, color);
+}
+
+void GfxPreview::draw_vector(const GPoint* tail, const GPoint* head, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_vector(CubitVector(tail->x, tail->y, tail->z), CubitVector(head->x, head->y, head->z), color);
+}
+
+// draw a label at position x,y,z of color
+void GfxPreview::draw_label(const char* label, float x, float y, float z, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_label(label, x, y, z, color);
+}
+void GfxPreview::draw_label(int label, float x, float y, float z, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_label(label, x, y, z, color);
+}
+
+void GfxPreview:: draw_cylinder(const CubitVector& axis, const CubitVector& origin, 
+                                 CubitBox& bounding_box, float radius, int color)
+{
+  if(!mInstance) return;
+  mInstance->p_draw_cylinder(axis, origin, bounding_box, radius, color);
+}
+
+void GfxPreview::draw_point(Point *pt, int color)
+{
+  CubitVector v = pt->coordinates();
+  draw_point(v, color);
+  flush();
+}
+
+void GfxPreview::draw_curve(Curve *curve, int color)
+{
+  int num_divs = 20;
+  double lo, hi;
+  curve->get_param_range(lo, hi);
+  double dv = (hi-lo)/(double)num_divs;
+  int i;
+  double param = lo;
+  for(i=0; i<num_divs; i++)
+  {
+    CubitVector p1, p2;
+    curve->position_from_u(param, p1);
+    param += dv;
+    curve->position_from_u(param, p2);
+    draw_line(p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z(), color);
+  }
+  flush();
+  DLIList<Point*> pts;
+  curve->points(pts);
+  for(i=pts.size(); i>0; i--)
+  {
+    Point *cur_pt = pts.get_and_step();
+    draw_point(cur_pt, color);
+  }
+}
+
+void GfxPreview::draw_surface(Surface *surf, int color)
+{
+  int num_divs = 20;
+  double ulo, uhi, vlo, vhi;
+  surf->get_param_range_U(ulo, uhi);
+  surf->get_param_range_V(vlo, vhi);
+  double du = (uhi-ulo)/(double)num_divs;
+  double dv = (vhi-vlo)/(double)num_divs;
+  int i, j;
+  double uparam, vparam;
+  uparam = ulo;
+  for(i=0; i<num_divs; i++)
+  {
+    vparam = vlo;
+    for(j=0; j<num_divs; j++)
+    {
+      CubitVector p1, p2;
+      p1 = surf->position_from_u_v(uparam, vparam);
+      vparam += dv;
+      p2 = surf->position_from_u_v(uparam, vparam);
+      draw_line(p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z(), color);
+    }
+    uparam += du;
+  }
+  vparam = vlo;
+  for(i=0; i<num_divs; i++)
+  {
+    uparam = ulo;
+    for(j=0; j<num_divs; j++)
+    {
+      CubitVector p1, p2;
+      p1 = surf->position_from_u_v(uparam, vparam);
+      uparam += du;
+      p2 = surf->position_from_u_v(uparam, vparam);
+      draw_line(p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z(), color);
+    }
+    vparam += dv;
+  }
+  flush();
+}
+
+void GfxPreview::draw_surface_facets_shaded(Surface *surf, int color)
+{
+  GMem g_mem;
+
+  surf->get_geometry_query_engine()->get_graphics(surf, &g_mem);
+
+  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);
+  flush();
+}
+

Added: cgm/branches/cubit/geom/GfxPreview.hpp
===================================================================
--- cgm/branches/cubit/geom/GfxPreview.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/GfxPreview.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,166 @@
+
+
+#ifndef GFX_PREVIEW_INTERFACE_HPP
+#define GFX_PREVIEW_INTERFACE_HPP
+
+// An interface for any tools, algorithms, etc... to draw preview objects.
+// NOTE: this is an "interface" in the sense that using it will not 
+// create additional depedencies in your code.  If a subclass of GfxPreview
+// is not instantiated, then this class acts as a stub with empty implementation.
+// CGM users may implement preview code by deriving from this class and implementing
+// graphics code in the pure virtual p_* methods.  Creating an instance of the
+// derived class will result in the correct methods being called by this interface.
+
+// PLEASE!!! use this interface to implement any graphical preview code in CGM.
+//           This will identify graphics code that must be maintained for end users.
+
+//
+// any graphics primitives drawn with this interface are temporary primitives and
+// not permanent ones.  All items are draw into a single drawing set owned by the 
+// 
+
+
+// We only have forward declarations and NO #includes !!! (except those already in the util folder)
+template <class X> class DLIList;
+class RefEntity;
+struct GPoint;
+class CubitVector;
+class RefEntity;
+class RefVertex;
+class RefEdge;
+class RefFace;
+class RefVolume;
+class Body;
+class CubitTransformMatrix;
+class CubitBox;
+class Curve;
+class Surface;
+class Point;
+
+#include "CubitColorConstants.hpp"
+#include "CubitGeomConfigure.h"
+
+class CUBIT_GEOM_EXPORT GfxPreview
+{
+  // the one instance of the Graphics Preview object
+  // creating a second instance will delete and replace the first instance.
+  static GfxPreview* mInstance;
+
+  public:
+    GfxPreview();
+    virtual ~GfxPreview();
+
+    // this will clear out all temporary data and delete any graphics windows created
+    // with this interface.  It'll restore the persistent geom/mesh model.
+    //static void reset();
+
+    // this will clear out any objects drawn using preview graphics.
+    // no other graphics will be affected so you can now do something like
+    //   draw vol 4
+    //   webcut vol all plane x preview
+    // and then clear the preview and you will still only have vol 4 displaye.
+    static void clear();  
+
+    // causes the window(s) to be redrawn
+    static void flush();
+
+  // Geometry Drawing Functions
+    static void draw_ref_entity(RefEntity* entity, int color = CUBIT_DEFAULT_COLOR,
+                                   CubitTransformMatrix* trans_mat = 0);
+    static void draw_ref_vertex(RefVertex* entity, int color = CUBIT_DEFAULT_COLOR);
+    static void draw_ref_edge(RefEdge* entity, int color = CUBIT_DEFAULT_COLOR);
+    static void draw_ref_face(RefFace* entity, int color = CUBIT_DEFAULT_COLOR);
+    static void draw_ref_face_edges(RefFace* entity, int color = CUBIT_DEFAULT_COLOR);
+    static void draw_ref_volume(RefVolume* entity, int color = CUBIT_DEFAULT_COLOR);
+    static void draw_ref_volume_edges(RefVolume* entity, int color = CUBIT_DEFAULT_COLOR);
+    static void draw_ref_body(Body* entity, int color = CUBIT_DEFAULT_COLOR);
+
+    static void draw_point(Point *pt, int color);
+    static void draw_curve(Curve *curve, int color);
+    static void draw_surface(Surface *surf, int color);
+    static void draw_surface_facets_shaded(Surface *surf, int color);
+
+  // Generic Primitive Drawing Functions
+    
+    static void draw_box(CubitBox& box, int color);
+    
+    // draw point x,y,z of color
+    static void draw_point(float x, float y, float z, int color);
+    static void draw_point(const CubitVector& vector, int color);
+    static void draw_point(CubitVector* vector, int color);
+
+    // draw line of points {x,y,z}, {x,y,z} of color
+    static void draw_line(float x1, float y1, float z1, 
+                          float x2, float y2, float z2, int color);
+    
+    static void draw_line(const CubitVector& x, const CubitVector& y, int color);
+
+    // draw a polyline with a number of points of a color
+    static void draw_polyline(const GPoint* points, int num_points, int color);
+
+    // draw a polygon with a number of points of a color and filled or not
+    static void draw_polygon(const GPoint* points, int num_points, int color, int border_color, bool filled = true);
+    // draw a list of polygons (much more efficent than drawing a single polygon multiple times.)
+    // pass in the coordinates and the connectivity
+    // the face_list is comprised of a list num_points_in_face, face_pt1, face_pt2, face_pt3, ...
+    static void draw_polygons(int num_points, const float* xyzs, int num_face_points, 
+                              const int* face_list, int color);
+
+    //! \brief draw a cylinder for previewing
+    //! \param axis - orientation of the length of the cylinder
+    //! \param origin - the center of the cylinder in x, y, and z
+    //! \param bounding_box - the bounding box of the cylinder
+    //! \param radius - radius of the cylinder
+    //! \param color - color of the cylinder
+    static void  draw_cylinder(const CubitVector& axis, const CubitVector& origin, 
+                               CubitBox& bounding_box, float radius, int color);
+    // draw a quad of a color
+    static void draw_quad(const GPoint* points, int color);
+
+    // draw a tri of a color
+    static void draw_tri(const GPoint* points, int color);
+
+    // draw a vector (tail -> head) of color
+    static void draw_vector(const GPoint* tail, const GPoint* head, int color);
+    static void draw_vector(const CubitVector& tail, const CubitVector& head, int color);
+
+    // draw a label at position x,y,z of color
+    static void draw_label(const char* label, float x, float y, float z, int color);
+    static void draw_label(int label, float x, float y, float z, int color);
+
+  protected:
+
+    // p is for protected in case you were wondering :)
+    
+    virtual void p_clear() = 0;
+    virtual void p_flush() = 0;
+
+    virtual void p_draw_ref_entity(RefEntity* entity, int color, CubitTransformMatrix* mat) = 0;
+    virtual void p_draw_ref_vertex(RefVertex* entity, int color) = 0;
+    virtual void p_draw_ref_edge(RefEdge* entity, int color) = 0;
+    virtual void p_draw_ref_face(RefFace* entity, int color) = 0;
+    virtual void p_draw_ref_face_edges(RefFace* entity, int color) = 0;
+    virtual void p_draw_ref_volume(RefVolume* entity, int color) = 0;
+    virtual void p_draw_ref_volume_edges(RefVolume* entity, int color) = 0;
+    virtual void p_draw_ref_body(Body* entity, int color) = 0;
+    virtual void p_draw_box(CubitBox& box, int color) = 0;
+    virtual void p_draw_point(float, float, float, int) = 0;
+    virtual void p_draw_point(const CubitVector& vector, int color) = 0;
+    virtual void p_draw_line(float, float, float, float, float, float, int) = 0;
+    virtual void p_draw_line(const CubitVector& x, const CubitVector& y, int color) = 0;
+    virtual void p_draw_polyline(const GPoint*, int, int) = 0;
+    virtual void p_draw_polygon(const GPoint* points, int num_points, int color, int border_color, bool filled) = 0;
+    virtual void p_draw_polygons(int num_points, const float* xyzs, int num_face_points, 
+                                 const int* face_list, int color) = 0;
+    virtual void p_draw_cylinder(const CubitVector& axis, const CubitVector& origin, 
+                               CubitBox& bounding_box, float radius, int color) = 0;
+    virtual void p_draw_quad(const GPoint*, int) = 0;
+    virtual void p_draw_tri(const GPoint*, int) = 0;
+    virtual void p_draw_vector(const CubitVector&, const CubitVector&, int) = 0;
+    virtual void p_draw_label(const char*, float, float, float, int) = 0;
+    virtual void p_draw_label(int, float, float, float, int) = 0;
+};
+
+#endif
+
+

Modified: cgm/branches/cubit/geom/GroupingEntity.cpp
===================================================================
--- cgm/branches/cubit/geom/GroupingEntity.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/GroupingEntity.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -196,7 +196,7 @@
          sense_entity->get_grouping_entity_ptr() != this )
       return CUBIT_FAILURE;
   }
-  
+
     // Special case for first entity in list.
   list.reset();
   SenseEntity* new_first = list.get_and_step();

Modified: cgm/branches/cubit/geom/IntermediateGeomEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/IntermediateGeomEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/IntermediateGeomEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -5,6 +5,9 @@
 class TopologyBridge;
 class CubitTransformMatrix;
 class Body;
+class Surface;
+class Curve;
+class Point;
 class BodySM;
 class TBOwner;
 
@@ -13,6 +16,7 @@
 
 public:
   virtual bool is_composite(TBOwner *bridge_owner) = 0;
+  virtual bool is_composite(TopologyBridge *bridge ) = 0;
   virtual bool is_partition(TBOwner *bridge_owner) = 0;
 
   virtual int level() const = 0;
@@ -22,6 +26,8 @@
                                   DLIList<BodySM*> &new_sms )=0;
   virtual void push_imprint_attributes_before_modify
                                 ( DLIList<BodySM*> &body_sms ) = 0;
+  virtual void push_named_attributes_to_curves_and_points
+                                ( DLIList<TopologyBridge*> &tb_list, const char *name_in ) = 0;
   virtual CubitStatus export_geometry( DLIList<TopologyBridge*>& geometry_list ) = 0;
   
   virtual CubitStatus import_geometry( DLIList<TopologyBridge*>& geometry_list ) = 0;
@@ -31,13 +37,18 @@
   virtual void remove_attributes( DLIList<TopologyBridge*> &bridge_list ) = 0;
   virtual void attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
                                                     DLIList<TopologyBridge*> &att_tbs,
-                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<TopologyBridge*> &tb_list,
                                                         DLIList<Body*> &old_bodies)=0;
   
   virtual void remove_attributes_from_unmodifed_virtual(DLIList<TopologyBridge*> &bridges) = 0;
-  virtual void remove_modified(DLIList<TopologyBridge*>& geometry_list) = 0;
+  virtual void remove_modified(DLIList<Surface*> &all_surfs,
+    DLIList<Curve*> &all_curves, DLIList<Point*> &all_pts) = 0;
   virtual CubitStatus notify_transform( TopologyBridge* entity,
                                         const CubitTransformMatrix& xform ) = 0;
+
+  virtual void get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                               DLIList<TopologyBridge*> &tbs ) = 0;
+
 };
 
 #endif

Modified: cgm/branches/cubit/geom/Loop.cpp
===================================================================
--- cgm/branches/cubit/geom/Loop.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Loop.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -89,6 +89,17 @@
    set_topology_bridge(OSMEPtr) ;
 }
 
+LoopType Loop::loop_type() const
+{
+    LoopSM* loop_sm = get_loop_sm_ptr();
+    if (loop_sm)
+    {
+        return loop_sm->loop_type();
+    }
+    assert(0);
+    return LOOP_TYPE_UNKNOWN;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Gets the angle metric for this Loop.
 //                 

Modified: cgm/branches/cubit/geom/Loop.hpp
===================================================================
--- cgm/branches/cubit/geom/Loop.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Loop.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -20,6 +20,7 @@
 
 // ********** BEGIN CUBIT INCLUDES         **********
 #include "CubitDefines.h"
+#include "GeometryDefines.h"
 #include "CubitBox.hpp"
 #include "GroupingEntity.hpp"
 // ********** END CUBIT INCLUDES           **********
@@ -45,11 +46,9 @@
 
   DagType dag_type() const { return DagType::loop_type(); }
   
-  CubitBoolean is_external() ;
-    //R CubitBoolean
-    //R- CUBIT_TRUE/CUBIT_FALSE
-    //- Returns CUBIT_TRUE if the Loop is an external Loop and CUBIT_FALSE
-    //- otherwise.
+  LoopType loop_type() const;
+    //R LoopType
+    //- Gets the type of this loop.  See LoopType enum for more details.
   
   CubitStatus get_angle_metric(double& angle_metric);
     //R CubitStatus

Modified: cgm/branches/cubit/geom/LoopSM.hpp
===================================================================
--- cgm/branches/cubit/geom/LoopSM.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/LoopSM.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -37,6 +37,7 @@
 // ********** BEGIN CUBIT INCLUDES         **********
 
 #include "CubitDefines.h"
+#include "GeometryDefines.h"
 
 #include "TopologyBridge.hpp"
 
@@ -54,6 +55,8 @@
   
   virtual ~LoopSM() ;
     //- The destructor
+
+  virtual LoopType loop_type() = 0;
   
   virtual const type_info& topology_entity_type_info() const;
   

Modified: cgm/branches/cubit/geom/Lump.hpp
===================================================================
--- cgm/branches/cubit/geom/Lump.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Lump.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -47,6 +47,10 @@
       //R- The enumerated type of the geometric representation
 
    virtual CubitStatus mass_properties( CubitVector &centroid, double &volume ) = 0;
+   virtual CubitStatus mass_properties( CubitVector principal_axes[3], 
+                                        CubitVector &principal_moments,
+                                        CubitVector &centroid, 
+                                        double &volume ) {return CUBIT_FAILURE;}
 
    protected: 
 

Modified: cgm/branches/cubit/geom/Makefile.am
===================================================================
--- cgm/branches/cubit/geom/Makefile.am	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Makefile.am	2010-01-06 19:22:14 UTC (rev 3423)
@@ -11,6 +11,7 @@
 if build_parallel
   SUBDIRS += parallel
 endif
+SUBDIRS += testing
 
 # Override default defines with the ones we want from the configure script
 DEFS = $(TEMPLATE_DEFS_INCLUDED) $(LITTLE_ENDIAN)
@@ -26,6 +27,7 @@
 libcubit_geom_la_SOURCES = \
     AllocMemManagersGeom.cpp \
     AnalyticGeometryTool.cpp \
+    AutoMidsurfaceTool.cpp \
     BasicTopologyEntity.cpp \
     Body.cpp \
     BodySM.cpp \
@@ -43,6 +45,7 @@
     CAUniqueId.cpp \
     CGMApp.cpp \
     CGMEngineDynamicLoader.cpp \
+    CGMHistory.cpp \
     Chain.cpp \
     CoEdge.cpp \
     CoEdgeSM.cpp \
@@ -73,6 +76,7 @@
     GeometryQueryTool.cpp \
     GeometryUtil.cpp \
     GeomMeasureTool.cpp \
+    GfxPreview.cpp \
     GroupingEntity.cpp \
     GSaveOpen.cpp \
     Loop.cpp \
@@ -88,6 +92,7 @@
     ModelQueryEngine.cpp \
     OffsetSplitTool.cpp \
     OldUnmergeCode.cpp \
+    PeriodicParamTool.cpp \
     Point.cpp \
     PointSM.cpp \
     RefCollection.cpp \
@@ -121,6 +126,7 @@
 # not be installed, move it to the _SOURCES list above.
 libcubit_geom_la_include_HEADERS = \
   AnalyticGeometryTool.hpp \
+  AutoMidsurfaceTool.hpp \
   BasicTopologyEntity.hpp \
   Body.hpp \
   BodySM.hpp \
@@ -139,6 +145,7 @@
   CAUniqueId.hpp \
   CGMApp.hpp \
   CGMEngineDynamicLoader.hpp \
+  CGMHistory.hpp \
   Chain.hpp \
   CoEdge.hpp \
   CoEdgeSM.hpp \
@@ -176,6 +183,7 @@
   GeometryQueryEngine.hpp \
   GeometryQueryTool.hpp \
   GeometryUtil.hpp \
+  GfxPreview.hpp \
   GroupingEntity.hpp \
   IntermediateGeomEngine.hpp \
   Loop.hpp \
@@ -191,6 +199,7 @@
   ModelQueryEngine.hpp \
   OffsetSplitTool.hpp \
   OldUnmergeCode.hpp \
+  PeriodicParamTool.hpp \
   Point.hpp \
   PointSM.hpp \
   RefCollection.hpp \

Modified: cgm/branches/cubit/geom/MergeTool.cpp
===================================================================
--- cgm/branches/cubit/geom/MergeTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/MergeTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -13,6 +13,10 @@
 #include "GeometryQueryTool.hpp"
 #include "GeometryQueryEngine.hpp"
 #include "ModelQueryEngine.hpp"
+#include "GeometryModifyTool.hpp"
+#include "SurfaceOverlapTool.hpp"
+#include "GeometryModifyEngine.hpp"
+#include "CGMHistory.hpp"
 
 #include "CubitObserver.hpp"
 #include "MergeEvent.hpp"
@@ -103,8 +107,82 @@
   instance_ = 0;
 }
 
+void MergeTool::merge_with_auto_imprint(RefFace *surf1, RefFace *surf2)
+{
+  DLIList<CubitString*> ds, cs, ps;
+  RefFace *local_surf1 = surf1;
+  RefFace *local_surf2 = surf2;
+  bool time_to_stop = false;
+  int cntr = 0;
+  bool first_time = true;
+  while(!time_to_stop && local_surf1 && 
+        local_surf2 && !local_surf1->is_merged() &&
+        !local_surf2->is_merged() )
+  {
+    int surf1_id = local_surf1->id();
+    int surf2_id = local_surf2->id();
+    if(first_time)
+    {
+      Body *b1 = local_surf1->body();
+      Body *b2 = local_surf2->body();
+      if(b1 && b2)
+      {
+        DLIList<Body*> body_list, new_bodies;
+        body_list.append(b1);
+        body_list.append(b2);
+        GeometryModifyTool::instance()->tolerant_imprint( body_list, new_bodies, true );
+        first_time = false;
+      }
+    }
+    else
+    {
+      this->imprint_merge_solutions_for_overlapping_surfaces(local_surf1,
+          local_surf2, true, ds, cs, ps);
+    }
+    RefFace *new_surf1 = RefEntityFactory::instance()->get_ref_face(surf1_id);
+    RefFace *new_surf2 = RefEntityFactory::instance()->get_ref_face(surf2_id);
+    if(new_surf1 && new_surf1->is_merged())
+      time_to_stop = true;
+    else if(new_surf2 && new_surf2->is_merged())
+      time_to_stop = true;
+    else
+    {
+      if(new_surf1 && new_surf2)
+      {
+        DLIList<RefFace*> current_face_list, out1, out2;
+        DLIList<RefEntity*> faces_to_draw;
+        current_face_list.append(new_surf1);
+        current_face_list.append(new_surf2);
+        SurfaceOverlapTool::instance()->find_overlapping_surfaces(current_face_list,
+                                                out1,
+                                                out2,
+                                                faces_to_draw,
+                                                CUBIT_FALSE,
+                                                CUBIT_TRUE);
+        if(out1.size() == 1 && out2.size() == 1 &&
+          (out1.get() == new_surf1 && out2.get() == new_surf2) ||
+          (out1.get() == new_surf2 && out2.get() == new_surf1))
+        {
+          local_surf1 = new_surf1;
+          local_surf2 = new_surf2;
+        }
+        else
+          time_to_stop = true;
+      }
+      else
+      {
+        time_to_stop = true;
+      }
+    }
+    cntr++;
+    if(cntr > 5)
+      time_to_stop = true;
+  }
+}
+
 //Public Functions:
-CubitBoolean MergeTool::contains_merged_entities( DLIList<RefEntity*> &ref_entities)
+CubitBoolean MergeTool::contains_merged_entities( DLIList<RefEntity*> &ref_entities,
+                                                  DLIList<RefEntity*> *merged_ref_ents )
 {
      //Loop through the entities and their children to find
      //merged entities.  For now, just do it quickly, so
@@ -121,9 +199,18 @@
   for (int i = all_entities.size(); i > 0; i--) {
     RefEntity *temp_entity = all_entities.get_and_step();
     if (entity_merged(CAST_TO(temp_entity, TopologyEntity)))
-      return CUBIT_TRUE;
+    {
+      if( NULL == merged_ref_ents )
+        return CUBIT_TRUE;
+      else
+        merged_ref_ents->append( temp_entity );
+    }
   }
   
+  if( merged_ref_ents )
+    if( merged_ref_ents->size() )
+      return CUBIT_TRUE;
+
   return CUBIT_FALSE;
 }
 
@@ -132,9 +219,8 @@
 {
   
   RefEntity *ref_ent = NULL;
-  ref_ent = CAST_TO(body, RefEntity);
   DLIList<RefEntity*> ref_ent_list;
-  ref_ent->get_all_child_ref_entities( ref_ent_list );
+  body->get_all_child_ref_entities( ref_ent_list );
   int i;
   for( i=ref_ent_list.size(); i--;)
   {
@@ -170,6 +256,18 @@
 
 CubitStatus MergeTool::merge_all_bodies()
 {
+   int number_volumes = GeometryQueryTool::instance()->num_ref_volumes();
+    
+   DLIList<RefEntity*> free_ref_ents;
+   int number_free_entities = 
+    GeometryQueryTool::instance()->get_free_ref_entities( free_ref_ents );
+    
+   if( number_volumes == 1 && free_ref_ents.size() == 0 )
+   {
+     PRINT_WARNING("Need more than 1 volume to merge anything\n");
+     return CUBIT_FAILURE;
+   }
+
    PRINT_INFO( "\n...Merging all features in the model\n" );
    set_merge_occurance( CUBIT_TRUE );
    
@@ -410,6 +508,16 @@
                                             GeometryQueryTool::instance()->get_merge_test_internal() );
       if( status == CUBIT_FALSE )
         continue;
+
+      //don't merge 2 surfaces of solid volumes if they have
+      //opposite sense..indicative that they overlap
+      if( refface_ptr->compare_alignment(compare_refface_ptr) == CUBIT_FORWARD )
+      {
+        //if they are both on solid volumes...bail
+        if( refface_ptr->body()->is_sheet_body() == CUBIT_FALSE && 
+            compare_refface_ptr->body()->is_sheet_body() == CUBIT_FALSE ) 
+        continue;
+      } 
       
         // If we are in this block, we want to merge the 
         // two entities. If they do not merge, there was
@@ -446,6 +554,14 @@
           if (print_info) PRINT_INFO( "Try changing the merge tolerance.\n" );
           continue;
       }
+   
+      /*
+      //don't merge 2 surfaces of solid volumes if they have 
+      //opposite sense..indicative that they overlap
+      if( refface_ptr->compare_alignment(compare_refface_ptr) == CUBIT_FORWARD )
+      {        
+        continue;
+      } */   
 
         // Always retain the entity with the lowest id.
       int nullify = j;
@@ -543,6 +659,8 @@
   
   if( destroyDeadGeometry )
     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
+
+  CubitObserver::notify_static_observers(NULL, MERGE_COMPLETED);
   
   PRINT_DEBUG_3( "cleanout time: %f secs\n", timer.cpu_secs() );
   if (print_info)
@@ -572,6 +690,7 @@
     else
       return CUBIT_SUCCESS;
   }
+
     // The basic algorithm is to step through the input list,
     // compare every entity with every entity within range of
     // its bounding box and merge the spatially equivellant entities.
@@ -677,6 +796,16 @@
                                             GeometryQueryTool::instance()->get_merge_test_internal() );
       if( status == CUBIT_FALSE )
         continue;
+
+      //don't merge 2 surfaces of solid volumes if they have
+      //opposite sense..indicative that they overlap
+      if( refface_ptr->compare_alignment(compare_refface_ptr) == CUBIT_FORWARD )
+      {
+        //if they are both on solid volumes...bail
+        if( refface_ptr->body()->is_sheet_body() == CUBIT_FALSE && 
+            compare_refface_ptr->body()->is_sheet_body() == CUBIT_FALSE ) 
+        continue;
+      } 
       
         // If we are in this block, we want to merge the 
         // two entities. If they do not merge, there was
@@ -1406,21 +1535,10 @@
   return CUBIT_SUCCESS;
 }
 
-CubitStatus MergeTool::find_only_mergeable_curves( DLIList<BodySM*> &body_list, 
+CubitStatus MergeTool::find_only_mergeable_curves( DLIList<Curve*> &all_curves, 
                   DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves )
 {
-  //collect all the curves from off the bodies
-  DLIList<Curve*> all_curves;
-  body_list.reset();
   int i;
-  for(i=body_list.size(); i--; )
-  {
-    BodySM* tmp_body = body_list.get_and_step();
-    DLIList<Curve*> tmp_curves;
-    tmp_body->curves( tmp_curves);
-    all_curves += tmp_curves;
-  }
- 
   double geom_factor = GeometryQueryTool::get_geometry_factor();
 
   //build up a tree for speed purposes
@@ -1436,6 +1554,8 @@
     Curve *curr_curve = all_curves.get_and_step();
     if( curr_curve == NULL )
       continue;
+
+    BodySM *cur_sm = curr_curve->bodysm();
     
     //get close curves
     DLIList<Curve*> close_curves;
@@ -1448,46 +1568,66 @@
       if( curr_curve == other_curve )
         continue;
   
-      CubitSense rel_sense;
-      CubitBoolean abs = about_spatially_equal( curr_curve, other_curve, rel_sense,
-                                             geom_factor ); 
-      if( abs )
+      BodySM *other_sm = other_curve->bodysm();
+
+      if(cur_sm != other_sm)
       {
-        //check to see if curves have already been inserted into lists
-        DLIList<Curve*> *curve1_list = NULL;
+        bool mergeable = false;
 
-        list_iter = curve_to_list_map.find( curr_curve );
-        if( list_iter != curve_to_list_map.end() )
-          curve1_list = list_iter->second;
-
-        if( curve1_list == NULL ) 
+        // If these curves are already merged add them to the list.
+        if(curr_curve->bridge_manager() &&
+          curr_curve->bridge_manager() == other_curve->bridge_manager())
         {
-          curve1_list = new DLIList<Curve*>;
-          curve1_list->append( curr_curve );
-          curve1_list->append( other_curve );
-          curve_to_list_map.insert( std::map<Curve*,
-                DLIList<Curve*>*>::value_type( curr_curve , curve1_list )); 
-          curve_to_list_map.insert( std::map<Curve*,
-                DLIList<Curve*>*>::value_type( other_curve, curve1_list )); 
-          lists_of_mergeable_curves.append( curve1_list );
+          mergeable = true;
         }
-        else 
+
+        if(!mergeable)
         {
-          curve1_list->append( other_curve );
-          curve_to_list_map.insert( std::map<Curve*,
-                DLIList<Curve*>*>::value_type( other_curve, curve1_list )); 
+          CubitSense rel_sense;
+          CubitBoolean abs = about_spatially_equal( curr_curve, other_curve, rel_sense,
+                                                geom_factor ); 
+          if(abs)
+            mergeable = true;
         }
-      
-        //remove mergeable curves from list and reset list
-        int item_index = all_curves.where_is_item( other_curve );
-        if( item_index > 0 ) 
+
+        if( mergeable )
         {
-          int curr_index = all_curves.get_index();
-          all_curves.reset();
-          all_curves.step( item_index );
-          all_curves.change_to( NULL );
-          all_curves.reset();
-          all_curves.step( curr_index );
+          //check to see if curves have already been inserted into lists
+          DLIList<Curve*> *curve1_list = NULL;
+
+          list_iter = curve_to_list_map.find( curr_curve );
+          if( list_iter != curve_to_list_map.end() )
+            curve1_list = list_iter->second;
+
+          if( curve1_list == NULL ) 
+          {
+            curve1_list = new DLIList<Curve*>;
+            curve1_list->append( curr_curve );
+            curve1_list->append( other_curve );
+            curve_to_list_map.insert( std::map<Curve*,
+                  DLIList<Curve*>*>::value_type( curr_curve , curve1_list )); 
+            curve_to_list_map.insert( std::map<Curve*,
+                  DLIList<Curve*>*>::value_type( other_curve, curve1_list )); 
+            lists_of_mergeable_curves.append( curve1_list );
+          }
+          else 
+          {
+            curve1_list->append( other_curve );
+            curve_to_list_map.insert( std::map<Curve*,
+                  DLIList<Curve*>*>::value_type( other_curve, curve1_list )); 
+          }
+        
+          //remove mergeable curves from list and reset list
+          int item_index = all_curves.where_is_item( other_curve );
+          if( item_index > 0 ) 
+          {
+            int curr_index = all_curves.get_index();
+            all_curves.reset();
+            all_curves.step( item_index );
+            all_curves.change_to( NULL );
+            all_curves.reset();
+            all_curves.step( curr_index );
+          }
         }
       }
     }
@@ -1495,6 +1635,43 @@
   return CUBIT_SUCCESS;
 }
 
+CubitStatus MergeTool::find_only_mergeable_curves( DLIList<Surface*> &surf_list, 
+                  DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves )
+{
+  //collect all the curves from off the bodies
+  DLIList<Curve*> all_curves;
+  surf_list.reset();
+  int i;
+  for(i=surf_list.size(); i--; )
+  {
+    Surface* tmp_surf = surf_list.get_and_step();
+    DLIList<Curve*> tmp_curves;
+    tmp_surf->curves(tmp_curves);
+    all_curves += tmp_curves;
+  }
+
+  return find_only_mergeable_curves(all_curves, lists_of_mergeable_curves);
+}
+
+CubitStatus MergeTool::find_only_mergeable_curves( DLIList<BodySM*> &body_list, 
+                  DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves )
+{
+  //collect all the curves from off the bodies
+  DLIList<Curve*> all_curves;
+  body_list.reset();
+  int i;
+  for(i=body_list.size(); i--; )
+  {
+    BodySM* tmp_body = body_list.get_and_step();
+    DLIList<Curve*> tmp_curves;
+    tmp_body->curves( tmp_curves);
+    all_curves += tmp_curves;
+  }
+
+  return find_only_mergeable_curves(all_curves, lists_of_mergeable_curves);
+ 
+}
+
 CubitStatus MergeTool::find_mergeable_refvertices( DLIList<RefEntity*> &entities,
                                                 DLIList< DLIList<RefVertex*>*> &lists_of_mergeable_ref_vertices,
                                                 bool clean_up_compare_data )
@@ -1771,6 +1948,20 @@
                        refedge_ptr->id(), compare_refedge_ptr->id() );
         continue;
       }
+     
+     /*
+      //refuse to merge free edges
+      if( refedge_ptr->ref_volume() == NULL )
+      {
+        PRINT_WARNING("Merging of free curves prohibited:  Curve %d\n", refedge_ptr->id() );         
+        continue;
+      }
+
+      if( compare_refedge_ptr->ref_volume() == NULL )
+      {
+        PRINT_WARNING("Merging of free curves prohibited:  Curve %d\n", compare_refedge_ptr->id() );         
+        continue;
+      } */
       
         // Always retain the entity with the lowest id.
       int nullify = compare_refedge_ptr->marked();
@@ -2049,7 +2240,20 @@
             std::swap(refedge_ptr, compare_refedge_ptr);
             nullify  = i;
          }
+/*
+         //refuse to merge free edges
+         if( refedge_ptr->ref_volume() == NULL )
+         {
+           PRINT_WARNING("Merging of free curves prohibited:  Curve %d\n", refedge_ptr->id() );         
+           continue;
+         }
 
+         if( compare_refedge_ptr->ref_volume() == NULL )
+         {
+           PRINT_WARNING("Merging of free curves prohibited:  Curve %d\n", compare_refedge_ptr->id() );         
+           continue;
+         } */
+
           // Now check if merge is okay with all assistants.
         CubitBoolean assistant_says_no = CUBIT_FALSE;
         for( int k = assistant_list_.size(); k > 0; k-- )
@@ -2138,7 +2342,12 @@
       PRINT_DEBUG_3( "cleanout time: %f secs\n",
                    timer.cpu_secs() );
    }
-   if (print_info) PRINT_INFO( "Consolidated %d curves\n", merge_count );
+
+   CubitObserver::notify_static_observers(NULL, MERGE_COMPLETED);
+
+   if(print_info) 
+     PRINT_INFO( "Consolidated %d curves\n", merge_count );
+
    if( CubitMessage::instance()->Interrupt() )
    {
      PRINT_WARNING("Curve merging aborted.\n");
@@ -2259,6 +2468,19 @@
                                                    CUBIT_TRUE );
       if( status == CUBIT_FALSE )
         continue;
+
+/*            //refuse to merge free edges
+      if( refvertex_ptr->ref_edge() == NULL )
+      {
+        PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", refvertex_ptr->id() );         
+        continue;
+      }
+
+      if( compare_refvertex_ptr->ref_edge() == NULL )
+      {
+        PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", compare_refvertex_ptr->id() );         
+        continue;
+      } */
          
       //Make sure we arn't merging two vertices on a
       //curve.
@@ -2511,7 +2733,20 @@
                                                    CUBIT_TRUE );
          if( status == CUBIT_FALSE )
              continue;
-         
+/*
+         //refuse to merge free edges
+         if( refvertex_ptr->ref_edge() == NULL )
+         {
+           PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", refvertex_ptr->id() );         
+           continue;
+         }
+
+         if( compare_refvertex_ptr->ref_edge() == NULL )
+         {
+           PRINT_WARNING("Merging of free vertices prohibited: Vertex %d\n", compare_refvertex_ptr->id() );         
+           continue;
+         }
+ */        
            //Make sure we arn't merging two vertices on a
            //curve.
          DLIList<RefEdge*> edges_1, edges_2;
@@ -2627,8 +2862,12 @@
     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
    PRINT_DEBUG_3( "cleanout time: %f secs\n",
                 timer.cpu_secs() );
+
+   CubitObserver::notify_static_observers(NULL, MERGE_COMPLETED);
    
-   if (print_info) PRINT_INFO( "Consolidated %d pairs of vertices\n", merge_count );
+   if(print_info) 
+     PRINT_INFO( "Consolidated %d pairs of vertices\n", merge_count );
+
    if( CubitMessage::instance()->Interrupt() )
    {
      PRINT_WARNING("Vertex merging aborted.\n");
@@ -2779,7 +3018,7 @@
   CubitBoolean top = start_unmerge();
   CubitStatus result = CUBIT_SUCCESS;
   int i;
-  
+
   DLIList<TopologyBridge*> bridge_list;
   face_ptr->bridge_manager()->get_bridge_list(bridge_list);
   if (bridge_list.size() < 2)
@@ -2922,7 +3161,11 @@
     if (parents.size() == 0)
     {
       if (new_list.insert(new_ptr).second)
+      {
         CubitObserver::notify_static_observers( new_ptr, FREE_REF_ENTITY_GENERATED );
+        CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, new_ptr);
+        GeometryQueryTool::instance()->history().add_event(evt);
+      }
     }
     
     while (parents.size())
@@ -2939,7 +3182,11 @@
   
   std::set<CubitObservable*>::iterator iter;
   for (iter = modified_list.begin(); iter != modified_list.end(); ++iter)
+  {
     (*iter)->notify_all_observers( TOPOLOGY_MODIFIED );
+    CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, static_cast<RefEntity*>(*iter));
+    GeometryQueryTool::instance()->history().add_event(evt);
+  }
 
   for( int a = assistant_list_.size(); a--; )
     assistant_list_.get_and_step()->finish_unmerge();
@@ -2968,7 +3215,11 @@
 {
   CubitStatus result = CUBIT_FAILURE;
   DLIList<ModelEntity*> query_results, query_results_2;
-  
+
+  // save to notify at end
+  DLIList<RefEntity*> dead_parents;
+  dead_entity->get_parent_ref_entities(dead_parents);
+
     // Make sure that the 2 BTE's are of the same type
   if( keeper_entity->dag_type() != dead_entity->dag_type() )
   {
@@ -3052,7 +3303,7 @@
                  "numbers of GroupingEntities.\n"
                  "  THIS IS A BUG - PLEASE REPORT IT!\n" );
     assert(0);
-  }
+  }  
   
     // Merge all child BTEs
   BasicTopologyEntity *bte_ptr_1, *bte_ptr_2;
@@ -3086,7 +3337,7 @@
         return CUBIT_FAILURE;
     }
   }
-      
+
     // If RefFace or RefEdge, adjust sense of parent sense entities,
     // if necessary.  This was previously handled by the 
     // switch_child_notify() callback in DAGNode/ModelEntity.
@@ -3096,6 +3347,7 @@
     // compare_alignment() does not need to be called for every
     // SenseEntitiy merge.  We only need to call it once.
   CubitBoolean switch_sense = CUBIT_FALSE;
+
   if(CAST_TO( keeper_entity, RefFace ) )
   {
     RefFace* keep_face = CAST_TO(keeper_entity,RefFace);
@@ -3104,7 +3356,7 @@
     {
       switch_sense = CUBIT_TRUE;
     }
-    warn_about_refface_sense( keep_face, dead_face, switch_sense );
+    //warn_about_refface_sense( keep_face, dead_face, switch_sense );
   }
   else if( CAST_TO( keeper_entity, RefEdge ) )
   {
@@ -3191,10 +3443,14 @@
     // Merge the name(s) of dead_entity to those of keeper_entity
   keeper_entity->merge_entity_names( dead_entity );
  
-  bool is_free_entity = false;
+  bool is_dead_entity_free_entity = false;
   if( dead_entity->num_parent_ref_entities() == 0 )
-    is_free_entity = true;
+    is_dead_entity_free_entity = true;
 
+  bool is_keeper_entity_free_entity = false;
+  if( keeper_entity->num_parent_ref_entities() == 0 )
+    is_keeper_entity_free_entity = true;
+
     // Next, merge the links of these two BTEs
   SenseEntity* co_edge_ptr;
   result = CUBIT_SUCCESS;
@@ -3236,8 +3492,12 @@
   dead_entity->notify_all_observers( MergeEvent(dead_entity, keeper_entity) );
 
   dead_entity->notify_all_observers( MODEL_ENTITY_DESTRUCTED );
-  if( is_free_entity ) //is free entity...top level
+  if( is_dead_entity_free_entity ) //is free entity...top level
+  {
     dead_entity->notify_all_observers( TOP_LEVEL_ENTITY_DESTRUCTED );
+    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, dead_entity);
+    GeometryQueryTool::instance()->history().add_event(evt);
+  }
 
   dead_entity->deactivated(CUBIT_TRUE);
   
@@ -3267,7 +3527,22 @@
   MergeEvent merge_event(dead_entity, keeper_entity);
   merge_event.set_event_type(ENTITY_SURVIVED_MERGE);
   CubitObserver::notify_static_observers(keeper_entity, merge_event);
-  
+
+  if( is_keeper_entity_free_entity && !is_dead_entity_free_entity ) //is free entity...top level
+  {
+    keeper_entity->notify_all_observers( TOP_LEVEL_ENTITY_DESTRUCTED );
+    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_DELETED, keeper_entity);
+    GeometryQueryTool::instance()->history().add_event(evt);
+  }
+
+
+  for(int i=0; i<dead_parents.size(); i++)
+  {
+    dead_parents[i]->notify_all_observers(TOPOLOGY_MODIFIED);
+    CGMHistory::Event evt(CGMHistory::TOPOLOGY_CHANGED, dead_parents[i]);
+    GeometryQueryTool::instance()->history().add_event(evt);
+  }
+    
   return CUBIT_SUCCESS;
 }
 
@@ -3941,6 +4216,8 @@
   
   if (destroyDeadGeometry)
     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
+
+   CubitObserver::notify_static_observers(NULL, MERGE_COMPLETED);
   
   return vtx1;
 }
@@ -4033,6 +4310,9 @@
   remove_compare_data();
   if (destroyDeadGeometry)
     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
+
+  CubitObserver::notify_static_observers(NULL, MERGE_COMPLETED);
+
   return edge1;
 }
 
@@ -4248,6 +4528,9 @@
   remove_compare_data();
   if (destroyDeadGeometry)
     GeometryQueryTool::instance()->cleanout_deactivated_geometry();
+
+  CubitObserver::notify_static_observers(NULL, MERGE_COMPLETED);
+
   return face1;
 }
 
@@ -4654,6 +4937,7 @@
   surfaces.step( j );
     // Create new face
   RefFace* new_face = RefEntityFactory::instance()->construct_RefFace( surfaces.get() );
+
   for (i = surfaces.size(); i > 1; i-- )
     new_face->bridge_manager()->add_bridge( surfaces.step_and_get() );
   
@@ -4792,6 +5076,7 @@
       
         // Find the curve(s) in the just-unmerged refface
       bridge_list.reset();
+      DLIList<Curve*> other_curves_to_unmerge;
       for (j = bridge_list.size(); j--; )
       {
         TopologyBridge* bridge = bridge_list.get_and_step();
@@ -4799,6 +5084,7 @@
         bridge->get_parents( bridge_parents );
         bridge_parents.reset();
         bool in_old = false, in_new = false;
+
         while (bridge_parents.size())
         {
           CoEdge* coedge = dynamic_cast<CoEdge*>(bridge_parents.pop()->topology_entity());
@@ -4817,7 +5103,28 @@
         else if(in_new)
         {
           curve_list.append( dynamic_cast<Curve*>(bridge) );
+          continue;
         }
+
+        //Some other curves might be merge candidates now..
+        //If both surfaces on either side of the curve have been unmerged,
+        //then this curve can be unmerged too.
+        bool unmerge_curve = true;
+        bridge_parents.clean_out();
+        bridge->get_parents( bridge_parents );
+        while (bridge_parents.size())
+        {
+          CoEdge* coedge = dynamic_cast<CoEdge*>(bridge_parents.pop()->topology_entity());
+          if( coedge->bridge_manager()->number_of_bridges() != 1 )
+          {
+            unmerge_curve = false;
+            break;
+          }
+        }
+
+        if( unmerge_curve == true )
+          other_curves_to_unmerge.append_unique( dynamic_cast<Curve*>(bridge) );
+
       } // for( j in bridge_list )
       
         // Find curve(s) that must remain merged.
@@ -4851,6 +5158,10 @@
       {
         separate_edge( curve_list, true );
       }
+      
+      if( other_curves_to_unmerge.size() )
+        separate_edge( other_curves_to_unmerge, true );
+
     } // for (i in edge_list)
   } // if (unmerge_curves)
   
@@ -4878,6 +5189,10 @@
   RefEdge* old_edge = dynamic_cast<RefEdge*>( can_separate( bridge_list, true ) );
   if (!old_edge)
     return 0;
+
+  bool old_edge_free_before = true;
+  if( old_edge->num_parent_ref_entities() ) 
+    old_edge_free_before = false;
     
   CubitBoolean top = start_unmerge();
      
@@ -4895,6 +5210,7 @@
   curves.step( j );
     // Create new edge
   RefEdge* new_edge = RefEntityFactory::instance()->construct_RefEdge( curves.get() );
+  
   for (i = curves.size(); i > 1; i-- )
     new_edge->bridge_manager()->add_bridge( curves.step_and_get() );
   
@@ -4987,10 +5303,11 @@
         point_list.append( point );
       }
       
-      point_list.reset();
       for (j = 0; j < point_list.size(); j++)
       {
-        Point* point = point_list.get_and_step();
+        point_list.reset();
+        point_list.step(j);
+        Point* point = point_list.get();
         parent_curves.clean_out();
         point->get_parents( parent_curves );
         
@@ -5001,7 +5318,7 @@
           BridgeManager* bm = curve->bridge_manager();
           bridge_list.clean_out();
           bm->get_bridge_list( bridge_list );
-          
+      
           bridge_list.reset();
           for (int l = bridge_list.size(); l--; )
           {
@@ -5015,10 +5332,17 @@
           }
         }
       }
- 
       separate_vertex( point_list );
     }
   }
+
+  if( !old_edge_free_before && old_edge->num_parent_ref_entities() == 0 )
+  {
+    CubitObserver::notify_static_observers( old_edge, FREE_REF_ENTITY_GENERATED );
+    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, old_edge );
+    GeometryQueryTool::instance()->history().add_event(evt);
+  }
+
   
   end_unmerge(top);  
   return new_edge;
@@ -5038,16 +5362,18 @@
 RefVertex* MergeTool::separate_vertex( DLIList<Point*>& points )
 {
   int i, j;
-  
   DLIList<TopologyBridge*> bridge_list( points.size() );
   CAST_LIST_TO_PARENT( points, bridge_list );
   RefVertex* old_vtx = dynamic_cast<RefVertex*>( can_separate( bridge_list, true ) );
   if (!old_vtx)
     return 0;
+
+  bool old_vtx_free_before = true;
+  if( old_vtx->num_parent_ref_entities() ) 
+    old_vtx_free_before = false;
   
   CubitBoolean top = start_unmerge();
   
-  
     // Split the RefVertex
   
     // Remove points from old vertex
@@ -5092,6 +5418,14 @@
   for (i = assistant_list_.size(); i--; )
     assistant_list_.get_and_step()->unmerged( old_vtx, new_vtx, false );
 
+  if( !old_vtx_free_before && old_vtx->num_parent_ref_entities() == 0 )
+  {
+    CubitObserver::notify_static_observers( old_vtx, FREE_REF_ENTITY_GENERATED );
+    CGMHistory::Event evt(CGMHistory::TOP_LEVEL_ENTITY_CREATED, old_vtx );
+    GeometryQueryTool::instance()->history().add_event(evt);
+  }
+
+
   end_unmerge(top);
   return new_vtx;
 }
@@ -5128,7 +5462,14 @@
   }
   
   if (smallest)
-    bte->set_id(smallest);
+  {
+    //make sure this id isn't in use already
+    RefEntity *tmp_ent = 
+      RefEntityFactory::instance()->get_ref_entity( bte->entity_type_info(), smallest ); 
+    
+    if( tmp_ent == NULL )
+      bte->set_id(smallest);
+  }
   
   return CUBIT_SUCCESS;
 }
@@ -5426,4 +5767,1139 @@
    return CUBIT_TRUE;
 }
 
+void MergeTool::imprint_merge_solutions_for_overlapping_surfaces(
+                                          RefFace *face1,
+                                          RefFace *face2,
+                                          bool execute,
+                                          DLIList<CubitString*> &display_strings,
+                                          DLIList<CubitString*> &command_strings,
+                                          DLIList<CubitString*> &preview_strings )
+{
+  //collect all the unmerged curves between the 2 surfaces
+  DLIList<RefEdge*> edges1, edges2, tmp_list;
+  face1->ref_edges( edges1 );
+  face2->ref_edges( edges2 );
+  tmp_list += edges1;
+  tmp_list.intersect_unordered( edges2 );
+  
+  //remove all the common edges from both lists
+  edges1 -= tmp_list;
+  edges2 -= tmp_list;
+  
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
 
+  CubitString *preview_string;
+  
+  if(!execute)
+  {
+    preview_string = new CubitString("draw surface ");
+    *preview_string += face1->id();
+    *preview_string += " "; 
+    *preview_string += face2->id();
+    *preview_string += " overlap"; 
+  }
+
+  //if all curves of both surfaces are merged, suggest 'force merge'
+  if( edges1.size() == 0 && edges2.size() == 0 )
+  {
+    //quick check to make sure that centerpoints are nearly coincident
+    CubitVector center1 = face1->center_point();
+    CubitVector center2 = face2->center_point();
+
+    if( center1.distance_between( center2 ) <= (tolerance*5) )
+    {
+      if(execute)
+      {
+        MergeTool::instance()->force_merge(face1, face2);
+      }
+      else
+      {
+        //display strings
+        CubitString *display_string = new CubitString("Force merge Surface ");
+        *display_string += face1->id();
+        *display_string += " "; 
+        *display_string += face2->id();
+        display_strings.append( display_string );
+
+        CubitString *command_string = new CubitString("merge surface ");
+        *command_string += face1->id();
+        *command_string += " ";
+        *command_string += face2->id();
+        *command_string += " force";
+        command_strings.append( command_string );
+
+        preview_strings.append( preview_string );
+      }
+      
+      return;
+    }
+  }
+
+  //get all the vertices 
+  DLIList<RefVertex*> verts1, verts2, merged_vertices;
+  face1->ref_vertices( verts1 );
+  face2->ref_vertices( verts2 );
+  merged_vertices += verts1;
+  merged_vertices.intersect_unordered( verts2 );
+  
+  //remove all the merged vertices from both lists
+  verts1 -= merged_vertices;
+  verts2 -= merged_vertices;
+
+  int i,j,k;
+  //another force merge case...all vertices are merged, but some 
+  //coincident curves remain unmerged still.
+  if( verts1.size() == 0 && verts2.size() == 0 )
+  {
+    DLIList<RefEdge*> tmp_edges1( edges1 );
+    DLIList<RefEdge*> tmp_edges2( edges2 );
+
+    //find edges that are close to one another
+    for( i=tmp_edges1.size(); i--; )
+    {
+      RefEdge *edge1 = tmp_edges1.get_and_step();
+
+      //get some random point on curve edge1
+      CubitVector position_on_edge1;
+      edge1->position_from_fraction( 0.634, position_on_edge1 );
+
+      bool found_pair = false;
+      for( j=tmp_edges2.size(); j--; )
+      {
+        RefEdge *edge2 = tmp_edges2.get_and_step();
+
+        if( edge2 == NULL )
+          continue;
+
+        //make sure that they have the same vertices
+        if( (edge1->start_vertex() == edge2->start_vertex() ||
+             edge1->start_vertex() == edge2->end_vertex() ) &&
+            (edge1->end_vertex() == edge2->end_vertex() ||
+             edge1->end_vertex() == edge2->start_vertex() ) )
+        {
+          //find the closest point 
+          CubitVector close_pt;
+          edge2->closest_point_trimmed( position_on_edge1, close_pt ); 
+          
+          //adjust tolerance to be larger possibly, a thousandanth of the curve's length
+          double tmp_tolerance = edge2->measure()*0.01;
+          if( tolerance > tmp_tolerance )
+            tmp_tolerance = tolerance;
+
+          if( close_pt.distance_between( position_on_edge1 ) < tmp_tolerance )
+          {
+              //remove both from the list
+            tmp_edges2.back();
+            tmp_edges2.change_to( NULL );
+            found_pair = true;
+            break;
+          }
+        }
+      }
+      if( found_pair == true )
+      {
+        tmp_edges1.back();
+        tmp_edges1.change_to( NULL );
+        tmp_edges1.step();
+      }
+    }
+
+    tmp_edges1.remove_all_with_value( NULL );
+    tmp_edges2.remove_all_with_value( NULL );
+    
+    if( tmp_edges1.size() == 0 && tmp_edges2.size() == 0 )
+    {
+      if(execute)
+      {
+        MergeTool::instance()->force_merge(face1, face2);
+      }
+      else
+      {
+        //display strings
+        CubitString *display_string = new CubitString("Force merge Surface ");
+        *display_string += face1->id();
+        *display_string += " "; 
+        *display_string += face2->id();
+        display_strings.append( display_string );
+
+        CubitString *command_string = new CubitString("merge surface ");
+        *command_string += face1->id();
+        *command_string += " ";
+        *command_string += face2->id();
+        *command_string += " force";
+        command_strings.append( command_string );
+
+        preview_strings.append( preview_string );
+      }
+      return;
+    }
+  }
+
+  //Look for near-coincident vertices between surfaces.
+  //If any vertices are less than merge_tolerance*5 apart, 
+  //merge all the vertices
+  verts1.clean_out();
+  verts2.clean_out();
+  face1->ref_vertices( verts1 );
+  face2->ref_vertices( verts2 );
+  double tmp_tol = tolerance * 5; 
+  double recommended_tol = -1;
+  RefVertex *near_coincident_verts[2];
+  
+  for( i=verts1.size(); i--; )
+  {
+    RefVertex *vert1 = verts1.get_and_step();
+    CubitVector pos1 = vert1->coordinates();
+
+    for( j=verts2.size(); j--; )
+    {
+      RefVertex *vert2 = verts2.get_and_step();
+      if( vert2 == vert1 )//already merged case
+        continue;
+      CubitVector pos2 = vert2->coordinates();
+
+      double tmp_dist = pos1.distance_between( pos2 );
+      if( tmp_dist < tmp_tol )
+      {
+        if( tmp_dist > recommended_tol )
+        {
+          recommended_tol = tmp_dist;
+          near_coincident_verts[0] = vert1;
+          near_coincident_verts[1] = vert2;
+        }
+      }
+    }
+  }
+
+  if( recommended_tol > 0 )
+  {
+    double merge_tol = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+    if(execute)
+    {
+      double old_merge_tol = -1;
+      if( recommended_tol > merge_tol )
+      {
+        old_merge_tol = GeometryQueryTool::get_geometry_factor();
+        GeometryQueryTool::set_geometry_factor(recommended_tol);
+      }
+      DLIList<RefVertex*> merge_vert_list;
+      face1->ref_vertices(merge_vert_list);
+      face2->ref_vertices(merge_vert_list);
+      MergeTool::instance()->merge_refvertices( merge_vert_list );
+      if( old_merge_tol != -1 )
+        GeometryQueryTool::set_geometry_factor( old_merge_tol );
+    }
+    else
+    {
+      CubitString *display_string = new CubitString("Merge vertices of surface ");
+      *display_string += face1->id(); 
+      *display_string += " ";  
+      *display_string += face2->id(); 
+      if( recommended_tol > merge_tol )
+      {
+        recommended_tol *= 1.1;
+        *display_string += " tolerance ";
+        *display_string += CubitString( recommended_tol, 0, 7 ); 
+      }
+      display_strings.append( display_string );
+
+      CubitString *command_string = new CubitString("merge vertex in surface ");
+      *command_string += face1->id(); 
+      *command_string += " ";  
+      *command_string += face2->id(); 
+      if( recommended_tol > merge_tol )
+      {
+        *command_string += " tolerance ";
+        *command_string += CubitString( recommended_tol, 0, 7 ); 
+      }
+      command_strings.append( command_string );
+
+      preview_strings.append( preview_string );
+    }
+    return;
+  }
+
+  DLIList<CubitVector*> positions_to_imprint_onto_face1;
+  DLIList<CubitVector*> positions_to_imprint_onto_face2;
+
+  double possible_slivers_on_face1 = 0;
+  double possible_slivers_on_face2 = 0;
+  
+  double dist1, dist2, dist3;
+
+  //if you have overlapping curves, suggest imprinting owning volume with vertex
+  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > facet_map;
+  
+  DLIList<RefEdge*> overlapping_edges2;
+
+  for( i=edges1.size(); i--; )
+  {
+    RefEdge *edge1 = edges1.get_and_step();
+
+    DLIList<RefVertex*> verts1;
+    edge1->ref_vertices( verts1 ); 
+    RefVertex *s_vert1 = verts1.get_and_step(); 
+    RefVertex *e_vert1 = verts1.get(); 
+    
+    bool overlaps_with_another_curve = false;
+    double edge1_length = edge1->measure();
+    double curve_overlap_tolerance = 0.005;
+
+    for( j=edges2.size(); j--; )
+    {
+      RefEdge *edge2 = edges2.get_and_step();
+
+      if( edge2 == NULL )
+        continue;
+      
+      if( SurfaceOverlapTool::instance()->check_overlap( edge1, edge2, 
+                                                         &facet_map, 
+                                                         &curve_overlap_tolerance ))
+      {
+        overlapping_edges2.append_unique( edge2 );
+        overlaps_with_another_curve = true;
+
+        DLIList<RefVertex*> verts2; 
+        edge2->ref_vertices( verts2 ); 
+        RefVertex *s_vert2 = verts2.get_and_step(); 
+        RefVertex *e_vert2 = verts2.get(); 
+
+        CubitVector close_pt;
+        edge1->closest_point_trimmed( s_vert2->coordinates(), close_pt );
+        
+        double edge2_length = edge2->measure();
+        
+        double tmp_tolerance = edge2_length;
+        if( edge1_length < edge2_length )
+          tmp_tolerance = edge1_length;
+        
+        //For a vertex of curve A to be imprinted on curve B, that vertex of A
+        //must be a distance greater than 1/2 a percent of the lenght of  
+        //whichever curve is smaller (A or B)
+        tmp_tolerance *= 0.005;
+        double sliver_tolerance = tmp_tolerance * 2;
+
+        if( tolerance < tmp_tolerance )
+          tolerance = tmp_tolerance;
+
+        dist1 = close_pt.distance_between( s_vert2->coordinates() );
+        dist2 = close_pt.distance_between( s_vert1->coordinates() ); 
+        dist3 = close_pt.distance_between( e_vert1->coordinates() ); 
+
+        //decide what vertex needs to be imprinted where
+        if( dist1 < tolerance && 
+            dist2 > tolerance &&
+            dist3 > tolerance )
+        {
+
+          //make sure this position doesn't already exist
+          bool add_position = true;
+          for( k=positions_to_imprint_onto_face1.size(); k--; )
+          {
+            CubitVector *tmp_vec = positions_to_imprint_onto_face1.get_and_step();
+
+            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            {
+              add_position = false;
+              break;
+            }
+          }
+          
+          if( add_position )
+          {
+            //imprint body of edge1 with vertex at this location
+            CubitVector *tmp_vec = new CubitVector( close_pt );
+            positions_to_imprint_onto_face1.append( tmp_vec );
+            
+            //watch for possible sliver creation
+            if( dist2 < sliver_tolerance || dist3 < sliver_tolerance )
+              possible_slivers_on_face1++;
+          }
+        }
+
+        edge1->closest_point_trimmed( e_vert2->coordinates(), close_pt );
+
+        dist1 = close_pt.distance_between( e_vert2->coordinates() );
+        dist2 = close_pt.distance_between( s_vert1->coordinates() ); 
+        dist3 = close_pt.distance_between( e_vert1->coordinates() ); 
+
+        if( dist1 < tolerance && 
+            dist2 > tolerance &&
+            dist3 > tolerance )
+        {
+          //make sure this position doesn't already exist
+          bool add_position = true;
+          for( k=positions_to_imprint_onto_face1.size(); k--; )
+          {
+            CubitVector *tmp_vec = positions_to_imprint_onto_face1.get_and_step();
+
+            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            {
+              add_position = false;
+              break;
+            }
+          }
+          
+          if( add_position )
+          {
+            //imprint body of edge1 with vertex at this location
+            CubitVector *tmp_vec = new CubitVector( close_pt );
+            positions_to_imprint_onto_face1.append( tmp_vec );
+            
+            //watch for possible sliver creation
+            if( dist2 < sliver_tolerance || dist3 < sliver_tolerance )
+              possible_slivers_on_face1++;
+          }
+        }
+
+        edge2->closest_point_trimmed( s_vert1->coordinates(), close_pt );
+
+        dist1 = close_pt.distance_between( s_vert1->coordinates() );
+        dist2 = close_pt.distance_between( s_vert2->coordinates() ); 
+        dist3 = close_pt.distance_between( e_vert2->coordinates() ); 
+
+        if( dist1 < tolerance &&
+            dist2 > tolerance &&
+            dist3 > tolerance )
+        {
+          //make sure this position doesn't already exist
+          bool add_position = true;
+          for( k=positions_to_imprint_onto_face2.size(); k--; )
+          {
+            CubitVector *tmp_vec = positions_to_imprint_onto_face2.get_and_step();
+
+            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            {
+              add_position = false;
+              break;
+            }
+          }
+          
+          if( add_position )
+          {
+            //imprint body of edge1 with vertex at this location
+            CubitVector *tmp_vec = new CubitVector( close_pt );
+            positions_to_imprint_onto_face2.append( tmp_vec );
+            
+            //watch for possible sliver creation
+            if( dist2 < sliver_tolerance || dist3 < sliver_tolerance )
+              possible_slivers_on_face2++;
+          }
+        }
+
+        edge2->closest_point_trimmed( e_vert1->coordinates(), close_pt );
+
+        dist1 = close_pt.distance_between( e_vert1->coordinates() );
+        dist2 = close_pt.distance_between( s_vert2->coordinates() ); 
+        dist3 = close_pt.distance_between( e_vert2->coordinates() ); 
+
+        if( dist1 < tolerance &&
+            dist2 > tolerance && 
+            dist3 > tolerance )
+        {
+          //make sure this position doesn't already exist
+          bool add_position = true;
+          for( k=positions_to_imprint_onto_face2.size(); k--; )
+          {
+            CubitVector *tmp_vec = positions_to_imprint_onto_face2.get_and_step();
+
+            if( close_pt.distance_between( *tmp_vec ) < tolerance )
+            {
+              add_position = false;
+              break;
+            }
+          }
+          
+          if( add_position )
+          {
+            //imprint body of edge1 with vertex at this location
+            CubitVector *tmp_vec = new CubitVector( close_pt );
+            positions_to_imprint_onto_face2.append( tmp_vec );
+            
+            //watch for possible sliver creation
+            if( dist2 < sliver_tolerance || dist3 < sliver_tolerance )
+              possible_slivers_on_face2++;
+          }
+        }
+      }
+    }
+
+    //remove this curve if it really overlaps
+    if( overlaps_with_another_curve == true )
+    {
+      edges1.back();
+      edges1.change_to( NULL );
+      edges1.step();
+    }
+  }
+  
+  //clean up facets
+  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator facet_iter;
+  facet_iter=facet_map.begin(); 
+  for(; facet_iter != facet_map.end(); facet_iter++ )
+  {
+    DLIList<CurveOverlapFacet*> *co_facet_list = facet_iter->second;
+
+    //delete all the facets in the list
+    for( i=co_facet_list->size(); i--; )
+      delete co_facet_list->get_and_step();
+    delete co_facet_list;
+  }
+  
+  //reset tolerance
+  tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  //after this you should only be left with unmerged, non-overlapping edges 
+  edges1.remove_all_with_value( NULL );
+  edges2 -= overlapping_edges2;
+
+  //if all the curves are either merged or overlapping and 
+  //no vertices of any curve will imprint onto any other curve... 
+  //suggest force merging the 2 surfaces
+  if( edges1.size() == 0 && edges2.size() == 0 &&  
+      positions_to_imprint_onto_face1.size() == 0 &&  
+      positions_to_imprint_onto_face2.size() == 0 )
+  {
+    
+    //make sure the 2 surfaces have same number of curves and vertices
+    if( face1->num_ref_vertices() == face2->num_ref_vertices() &&
+        face1->num_ref_edges() == face2->num_ref_edges() )
+    {
+      if(execute)
+      {
+        MergeTool::instance()->force_merge(face1, face2);
+      }
+      else
+      {
+        CubitString *display_string = new CubitString("Force merge Surface ");
+        *display_string += face1->id();
+        *display_string += " "; 
+        *display_string += face2->id();
+        display_strings.append( display_string );
+     
+        CubitString *command_string = new CubitString("merge surface ");
+        *command_string += face1->id();
+        *command_string += " ";
+        *command_string += face2->id();
+        *command_string += " force";
+        command_strings.append( command_string );
+        
+        preview_strings.append( preview_string );
+      }
+      return;
+    }
+  }
+
+  //try to suggest some curves you can imprint onto a surface 
+  if( edges1.size() || edges2.size() )
+  {
+    DLIList<RefFace*> face_list(1);
+    face_list.append( face2 );
+   
+    //see what edges in edges1 will imprint onto face2
+    DLIList<RefEdge*> edges_to_imprint_onto_face2;
+    for( i=edges1.size(); i--; )
+    {
+      RefEdge *edge1 = edges1.get_and_step();
+
+      //project
+      DLIList<RefEdge*> edge_list(1);
+      DLIList<RefEdge*> new_edges; 
+      edge_list.append( edge1);
+      bool print_error = false;
+
+      DLIList<Surface*> surface_list(1);
+      DLIList<Curve*> curves_to_project(1), projected_curves;
+      GeometryModifyEngine* gme = GeometryModifyTool::instance()->common_modify_engine( 
+                                                        face_list,
+                                                        edge_list,
+                                                        surface_list,
+                                                        curves_to_project);
+      CubitStatus status = gme->
+         project_edges( surface_list, curves_to_project, projected_curves);
+      
+      if( projected_curves.size() == 0 )
+        continue;
+
+      Curve *projected_curve = projected_curves.get(); 
+
+      //if midpoint of projected curve is far from original curve, continue 
+      CubitVector original_curve_mid_point = edge1->center_point(); 
+      if( original_curve_mid_point.distance_between( projected_curve->center_point() ) > tolerance )
+      {
+        gme->get_gqe()->delete_solid_model_entities( projected_curve );
+        continue;
+      }
+
+      bool is_curve_on_surface = false;
+      //do a surface-curve intersection to see if the curve lies on the surface
+      DLIList<Curve*> intersection_curves;
+      status = gme->curve_surface_intersection( surface_list.get(), 
+                                                projected_curve,
+                                                intersection_curves); 
+  
+      if( status == CUBIT_SUCCESS && intersection_curves.size() )
+      {
+        //remove any sliver curves
+        for( j=intersection_curves.size(); j--; )
+        {
+          Curve *tmp_curve = intersection_curves.get_and_step();
+          if( tmp_curve->measure() < tolerance )
+          {
+            gme->get_gqe()->delete_solid_model_entities( tmp_curve );
+            intersection_curves.back();
+            intersection_curves.change_to( NULL );
+            intersection_curves.step();
+          }
+        }
+
+        intersection_curves.remove_all_with_value( NULL );
+        
+        if( intersection_curves.size() ) 
+          is_curve_on_surface = true;
+
+        //delete the intersection curves
+        for( j=intersection_curves.size(); j--; )
+          gme->get_gqe()->delete_solid_model_entities( intersection_curves.get_and_step() );
+      }
+
+      //maybe the surface-curve intersection method above didn't work...do 
+      //this more primitive method instead
+      if( is_curve_on_surface == false ) 
+      {
+        double distances_on_curves[3];
+        distances_on_curves[0] = .235;
+        distances_on_curves[1] = .468;
+        distances_on_curves[2] = .894;
+
+        for( j=0; j<3; j++ )
+        {
+          CubitVector position_on_curve;
+          projected_curve->position_from_fraction( distances_on_curves[j],
+                                                   position_on_curve );
+
+          CubitVector closest_point_on_surface;
+          face2->find_closest_point_trimmed( position_on_curve, 
+                                             closest_point_on_surface );
+          
+          if( position_on_curve.distance_between( closest_point_on_surface ) < tolerance )
+          {
+            is_curve_on_surface = true;
+            break;
+          }
+        }
+      }
+
+      //delete the projected curve
+      gme->get_gqe()->delete_solid_model_entities( projected_curve );
+
+      if( is_curve_on_surface == false )
+        continue;
+
+      edges_to_imprint_onto_face2.append( edge1 );
+    }
+
+    //a possible force merge situation???
+    if( edges_to_imprint_onto_face2.size() )
+    {
+      //are the number of vertices on both faces the same?
+      if( face1->num_ref_vertices() == face2->num_ref_vertices() &&
+          face1->num_ref_edges() == face2->num_ref_edges() )
+      {
+        double overlapping_area = 0;
+        SurfaceOverlapTool::instance()->check_overlap(
+               face1, face2, CUBIT_FALSE, CUBIT_FALSE, &overlapping_area );
+        double face1_area = face1->area();
+        double face2_area = face2->area();
+       
+        //make sure overlapping area is more than 99% of both surface areas
+        double area_diff1 = fabs( overlapping_area - face1_area );
+        double area_diff2 = fabs( overlapping_area - face2_area );
+       
+        if( area_diff1 < (face1_area*0.01) &&
+            area_diff2 < (face2_area*0.01) )
+        {
+          if(execute)
+          {
+            MergeTool::instance()->force_merge(face1, face2);
+          }
+          else
+          {
+            CubitString *display_string = new CubitString("Force merge Surface ");
+            *display_string += face1->id();
+            *display_string += " "; 
+            *display_string += face2->id();
+            display_strings.append( display_string );
+
+            CubitString *command_string = new CubitString("merge surface ");
+            *command_string += face1->id();
+            *command_string += " ";
+            *command_string += face2->id();
+            *command_string += " force";
+            command_strings.append( command_string );
+            
+            preview_strings.append( preview_string );
+          }
+          return;
+        }
+      }
+    }
+
+    face_list.clean_out();
+    face_list.append( face1 );
+
+    DLIList<RefEdge*> edges_to_imprint_onto_face1;
+    //see what edges in edges2 will imprint onto face1
+    for( i=edges2.size(); i--; )
+    {
+      RefEdge *edge2 = edges2.get_and_step();
+
+      //project
+      DLIList<RefEdge*> edge_list(1);
+      DLIList<RefEdge*> new_edges; 
+      edge_list.append( edge2);
+      bool print_error = false;
+
+      DLIList<Surface*> surface_list(1);
+      DLIList<Curve*> curves_to_project(1), projected_curves;
+      GeometryModifyEngine* gme = GeometryModifyTool::instance()->common_modify_engine( 
+                                                        face_list,
+                                                        edge_list,
+                                                        surface_list,
+                                                        curves_to_project);
+      CubitStatus status = gme->
+         project_edges( surface_list, curves_to_project, projected_curves);
+      
+      if( projected_curves.size() == 0 )
+        continue;
+    
+      Curve *projected_curve = projected_curves.get(); 
+
+      //if midpoint of projected curve is far from original curve, continue 
+      CubitVector original_curve_mid_point = edge2->center_point(); 
+      if( original_curve_mid_point.distance_between( projected_curve->center_point() ) > tolerance )
+      {
+        gme->get_gqe()->delete_solid_model_entities( projected_curve );
+        continue;
+      }
+
+      bool is_curve_on_surface = false;
+      //do a surface-curve intersection to see if the curve lies on the surface
+      DLIList<Curve*> intersection_curves;
+      status = gme->curve_surface_intersection( surface_list.get(), 
+                                                projected_curve,
+                                                intersection_curves); 
+  
+      if( status == CUBIT_SUCCESS && intersection_curves.size() )
+      {
+        //remove any sliver curves
+        for( j=intersection_curves.size(); j--; )
+        {
+          Curve *tmp_curve = intersection_curves.get_and_step();
+          if( tmp_curve->measure() < tolerance )
+          {
+            gme->get_gqe()->delete_solid_model_entities( tmp_curve );
+            intersection_curves.back();
+            intersection_curves.change_to( NULL );
+            intersection_curves.step();
+          }
+        }
+
+        intersection_curves.remove_all_with_value( NULL );
+        
+        if( intersection_curves.size() ) 
+          is_curve_on_surface = true;
+
+        //delete the intersection curves
+        for( j=intersection_curves.size(); j--; )
+          gme->get_gqe()->delete_solid_model_entities( intersection_curves.get_and_step() );
+      }
+
+      //maybe the surface-curve intersection method above didn't work...do 
+      //this more primitive method instead
+      if( is_curve_on_surface == false ) 
+      {
+        double distances_on_curves[3];
+        distances_on_curves[0] = .235;
+        distances_on_curves[1] = .468;
+        distances_on_curves[2] = .894;
+
+        for( j=0; j<3; j++ )
+        {
+          CubitVector position_on_curve;
+          projected_curve->position_from_fraction( distances_on_curves[j],
+                                                   position_on_curve );
+
+          CubitVector closest_point_on_surface;
+          face1->find_closest_point_trimmed( position_on_curve, 
+                                             closest_point_on_surface );
+          
+          if( position_on_curve.distance_between( closest_point_on_surface ) < tolerance )
+          {
+            is_curve_on_surface = true;
+            break;
+          }
+        }
+      }
+
+      //delete the projected curve
+      gme->get_gqe()->delete_solid_model_entities( projected_curve );
+
+      if( is_curve_on_surface == false )
+        continue;
+
+      edges_to_imprint_onto_face1.append( edge2 ); 
+    }
+
+    //a possible force merge situation???
+    if( edges_to_imprint_onto_face1.size() )
+    {
+      //are the number of vertices on both faces the same?
+      if( face1->num_ref_vertices() == face2->num_ref_vertices() &&
+          face1->num_ref_edges() == face2->num_ref_edges() )
+      {
+        double overlapping_area = 0;
+        SurfaceOverlapTool::instance()->check_overlap(
+               face1, face2, CUBIT_FALSE, CUBIT_FALSE, &overlapping_area );
+        double face1_area = face1->area();
+        double face2_area = face2->area();
+       
+        //make sure overlapping area is less than 1% of both surface areas
+        double area_diff1 = fabs( overlapping_area - face1_area );
+        double area_diff2 = fabs( overlapping_area - face2_area );
+       
+        if( area_diff1 < (face1_area*0.01) &&
+            area_diff2 < (face2_area*0.01) )
+        {
+          if(execute)
+          {
+            MergeTool::instance()->force_merge(face1, face2);
+          }
+          else
+          {
+            CubitString *display_string = new CubitString("Force merge Surface ");
+            *display_string += face1->id();
+            *display_string += " "; 
+            *display_string += face2->id();
+            display_strings.append( display_string );
+
+            CubitString *command_string = new CubitString("merge surface ");
+            *command_string += face1->id();
+            *command_string += " ";
+            *command_string += face2->id();
+            *command_string += " force";
+            command_strings.append( command_string );
+            
+            preview_strings.append( preview_string );
+          }
+          return;
+        }
+      }
+    }
+
+    //imprint all the edges onto both surfaces in a single command
+    if( edges_to_imprint_onto_face1.size() && 
+        edges_to_imprint_onto_face2.size() ) 
+    {
+      if(execute)
+      {
+        DLIList<RefFace*> ref_face_list;
+        ref_face_list.append(face1);
+        ref_face_list.append(face2);
+        DLIList<RefEdge*> ref_edge_list;
+        for( i=edges_to_imprint_onto_face2.size(); i--; )
+          ref_edge_list.append(edges_to_imprint_onto_face2.get_and_step());
+        for( i=edges_to_imprint_onto_face1.size(); i--; )
+          ref_edge_list.append(edges_to_imprint_onto_face1.get_and_step());
+        DLIList<Body*> tmp_new_bodies; 
+        GeometryModifyTool::instance()->tolerant_imprint( ref_face_list,
+                                                          ref_edge_list, 
+                                                          tmp_new_bodies, true );
+        return;
+      }
+      else
+      {
+        CubitString *command_string = new CubitString("Imprint tolerant surface ");
+        *command_string += face1->id();
+        *command_string += " ";
+        *command_string += face2->id();
+        *command_string += " with curve ";
+        
+        CubitString *display_string = new CubitString("Imprint with curves ");
+
+        CubitString curve_ids;
+        for( i=edges_to_imprint_onto_face2.size(); i--; )
+        {
+          RefEdge *tmp_edge = edges_to_imprint_onto_face2.get_and_step();
+          curve_ids += tmp_edge->id();
+          curve_ids += " "; 
+        }
+        for( i=edges_to_imprint_onto_face1.size(); i--; )
+        {
+          RefEdge *tmp_edge = edges_to_imprint_onto_face1.get_and_step();
+          curve_ids += tmp_edge->id();
+          curve_ids += " "; 
+        }
+
+        *display_string += curve_ids;
+        *command_string += curve_ids;
+        *command_string += "merge";
+        
+        *preview_string += " &&& highlight curve ";
+        *preview_string += curve_ids;
+
+        display_strings.append( display_string );
+        command_strings.append( command_string );
+        preview_strings.append( preview_string );
+      }
+    }
+    //imprint edges onto a single surface  
+    else if( edges_to_imprint_onto_face2.size() )
+    {
+      if(execute)
+      {
+        DLIList<RefFace*> ref_face_list;
+        ref_face_list.append(face2);
+        DLIList<Body*> tmp_new_bodies; 
+        GeometryModifyTool::instance()->tolerant_imprint( ref_face_list,
+                                                          edges_to_imprint_onto_face2, 
+                                                          tmp_new_bodies, true );
+        return;
+      }
+      else
+      {
+        CubitString *command_string = new CubitString("Imprint tolerant surface ");
+        *command_string += face2->id();
+        *command_string += " with curve ";
+        
+        CubitString *display_string = new CubitString("Imprint with curves ");
+        *preview_string += " &&& highlight curve ";
+      
+        CubitString curve_ids;
+        for( i=edges_to_imprint_onto_face2.size(); i--; )
+        {
+          RefEdge *tmp_edge = edges_to_imprint_onto_face2.get_and_step();
+          curve_ids += tmp_edge->id();
+          curve_ids += " "; 
+        }
+
+        *command_string += curve_ids; 
+        *display_string += curve_ids; 
+        *preview_string += curve_ids; 
+
+        *command_string += " merge";
+
+        display_strings.append( display_string );
+        command_strings.append( command_string );
+        preview_strings.append( preview_string );
+      }
+    }
+    //imprint edges onto a single surface  
+    else if( edges_to_imprint_onto_face1.size() )
+    {
+      if(execute)
+      {
+        DLIList<RefFace*> ref_face_list;
+        ref_face_list.append(face1);
+        DLIList<Body*> tmp_new_bodies; 
+        GeometryModifyTool::instance()->tolerant_imprint( ref_face_list,
+                                                          edges_to_imprint_onto_face1, 
+                                                          tmp_new_bodies, true );
+        return;
+      }
+      else
+      {
+        CubitString *command_string = new CubitString("Imprint tolerant surface ");
+        *command_string += face1->id();
+        *command_string += " with curve ";
+
+        CubitString *display_string = new CubitString("Imprint with curves ");
+        *preview_string += " &&& highlight curve ";
+       
+        CubitString curve_ids;
+        for( i=edges_to_imprint_onto_face1.size(); i--; )
+        {
+          RefEdge *tmp_edge = edges_to_imprint_onto_face1.get_and_step();
+          curve_ids += tmp_edge->id();
+          curve_ids += " "; 
+        }
+
+        *command_string += curve_ids; 
+        *display_string += curve_ids; 
+        *preview_string += curve_ids; 
+
+        *command_string += " merge";
+
+        display_strings.append( display_string );
+        command_strings.append( command_string );
+        preview_strings.append( preview_string );
+      }
+    }
+
+    //if we came up with some solutions, get out
+    if( display_strings.size() )
+      return;
+  }
+
+  //just suggest some vertex imprints
+  if( positions_to_imprint_onto_face1.size() ||
+      positions_to_imprint_onto_face2.size() )
+  {
+    //Are you possibly generating sliver curves?  
+    //Offer a merge force merge instead if topology is identical 
+    if( face1->num_ref_vertices() == face2->num_ref_vertices() &&
+        face1->num_ref_edges() == face2->num_ref_edges() )
+    {
+      if((positions_to_imprint_onto_face1.size() &&
+          positions_to_imprint_onto_face1.size() == possible_slivers_on_face1 ) ||
+         (positions_to_imprint_onto_face2.size() &&
+          positions_to_imprint_onto_face2.size() == possible_slivers_on_face2 )) 
+      {
+        if(execute)
+        {
+          MergeTool::instance()->force_merge(face1, face2);
+        }
+        else
+        {
+          CubitString *display_string = new CubitString("Force merge Surface ");
+          *display_string += face1->id();
+          *display_string += " "; 
+          *display_string += face2->id();
+          display_strings.append( display_string );
+       
+          CubitString *command_string = new CubitString("merge surface ");
+          *command_string += face1->id();
+          *command_string += " ";
+          *command_string += face2->id();
+          *command_string += " force";
+          command_strings.append( command_string );
+        }
+     
+        return;
+      }
+    }
+
+    CubitString *command_string = NULL;
+  //  CubitString *preview_string = NULL;
+    if( positions_to_imprint_onto_face1.size() )
+    {
+      if(execute)
+      {
+        Body *b = face1->body();
+        if(b)
+        {
+          DLIList<Body*> body_list;
+          body_list.append(b);
+          DLIList<Body*> new_bodies;
+          GeometryModifyTool::instance()->imprint( body_list, positions_to_imprint_onto_face1,
+                                                        new_bodies, false, true );
+          while(positions_to_imprint_onto_face1.size())
+            delete positions_to_imprint_onto_face1.pop();
+        }
+      }
+      else
+      {
+        command_string = new CubitString("Imprint volume ");
+        RefVolume *volume1 = face1->ref_volume();
+        *command_string += volume1->id();
+        *command_string += " with";
+        *preview_string += " &&& highlight"; 
+        for( i=positions_to_imprint_onto_face1.size(); i--; )
+        {
+          //construct the command string
+          *command_string += " position {";
+          CubitVector *tmp_pos = positions_to_imprint_onto_face1.get_and_step();
+          *command_string += CubitString( tmp_pos->x(), 0, 7 ); 
+          *command_string += "} {"; 
+          *command_string += CubitString( tmp_pos->y(), 0, 7 ); 
+          *command_string += "} {"; 
+          *command_string += CubitString( tmp_pos->z(), 0, 7 ); 
+          *command_string += "}"; 
+
+          //construct the preview string
+          *preview_string += " location ";
+          *preview_string += CubitString( tmp_pos->x(), 0, 7 ); 
+          *preview_string += " ";
+          *preview_string += CubitString( tmp_pos->y(), 0, 7 ); 
+          *preview_string += " ";
+          *preview_string += CubitString( tmp_pos->z(), 0, 7 ); 
+          *preview_string += " ";
+
+          delete tmp_pos;
+        }
+        *command_string += " merge";
+      }
+    }
+
+    if( positions_to_imprint_onto_face2.size() )
+    {
+      if(execute)
+      {
+        Body *b = face2->body();
+        if(b)
+        {
+          DLIList<Body*> body_list;
+          body_list.append(b);
+          DLIList<Body*> new_bodies;
+          GeometryModifyTool::instance()->imprint( body_list, positions_to_imprint_onto_face2,
+                                                        new_bodies, false, true );
+          while(positions_to_imprint_onto_face2.size())
+            delete positions_to_imprint_onto_face2.pop();
+        }
+      }
+      else
+      {
+        if( command_string == NULL )
+          command_string = new CubitString("Imprint volume ");
+        else
+          *command_string += " &&& Imprint volume ";
+
+        if( positions_to_imprint_onto_face1.size() == 0 ) 
+          *preview_string += " &&& highlight"; 
+
+        RefVolume *volume2 = face2->ref_volume();
+        *command_string += volume2->id();
+        *command_string += " with";
+        for( i=positions_to_imprint_onto_face2.size(); i--; )
+        {
+          *command_string += " position {";
+          CubitVector *tmp_pos = positions_to_imprint_onto_face2.get_and_step();
+          
+          *command_string += CubitString( tmp_pos->x(), 0, 7 ); 
+          *command_string += "} {"; 
+          *command_string += CubitString( tmp_pos->y(), 0, 7 ); 
+          *command_string += "} {"; 
+          *command_string += CubitString( tmp_pos->z(), 0, 7 ); 
+          *command_string += "}"; 
+
+          //construct the preview string
+          *preview_string += " location ";
+          *preview_string += CubitString( tmp_pos->x(), 0, 7 ); 
+          *preview_string += " ";
+          *preview_string += CubitString( tmp_pos->y(), 0, 7 ); 
+          *preview_string += " ";
+          *preview_string += CubitString( tmp_pos->z(), 0, 7 ); 
+          *preview_string += " ";
+
+          delete tmp_pos;
+        }
+        *command_string += " merge";
+      }
+    }
+
+    if(!execute)
+    {
+      command_strings.append( command_string );
+      preview_strings.append( preview_string );
+
+      //create the display string
+      CubitString *display_string = new CubitString("Imprint with positions" ); 
+      display_strings.append( display_string );
+    }
+  }
+
+  return;
+}
+
+

Modified: cgm/branches/cubit/geom/MergeTool.hpp
===================================================================
--- cgm/branches/cubit/geom/MergeTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/MergeTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -71,284 +71,350 @@
    
    ~MergeTool();
      //- Destructor.
+   
+    static void delete_instance() {if(instance_) delete instance_; }
      
-   CubitBoolean contains_merged_entities( DLIList<Body*> &bodies );
-     //- Tests the entities in the list of bodies to see if they 
-     //- have been merged with other entities and result in
-     //- of multiple volumes.  This returns CUBIT_TRUE at the first
-     //- lower entity that shares two volumes.
-   
+    void imprint_merge_solutions_for_overlapping_surfaces(
+                                          RefFace *face1,
+                                          RefFace *face2,
+                                          bool execute,
+                                          DLIList<CubitString*> &display_strings,
+                                          DLIList<CubitString*> &command_strings,
+                                          DLIList<CubitString*> &preview_strings );
+
+   void merge_with_auto_imprint(RefFace *surf1, RefFace *surf2);
+
+  //! Tests the entities in the list of bodies to see if they 
+  //! have been merged with other entities and result in
+  //! of multiple volumes.  This returns CUBIT_TRUE at the first
+  //! lower entity that shares two volumes.
+  CubitBoolean contains_merged_entities( DLIList<Body*> &bodies );
+  
+  //! Determines if the specified body conatins child entities that are merged.
   CubitBoolean contains_merged_children( Body *body,
                                          DLIList<RefEntity*> &merged_children );
 
-
-  CubitBoolean contains_merged_entities( DLIList<RefEntity*> &ref_entities);
-     //- Tests the entities in the list to see if they or their descendents
-     //- have been merged with other entities
+  //! Tests the entities in the list to see if they or their descendents
+  //! have been merged with other entities
+  //! If merged_ref_ents is not NULL, fill it will all the merged ref entities. 
+  CubitBoolean contains_merged_entities( DLIList<RefEntity*> &ref_entities, 
+                                         DLIList<RefEntity*> *merged_ref_ents = NULL );
   
+  //! Tests the entities in the list to see if their ANY children of ancestors 
+  //! have been merged with other entities
   CubitBoolean parents_contain_merged_entities( DLIList<RefEntity*> &ref_entities);
-     //- Tests the entities in the list to see if their ANY children of ancestors 
-     //- have been merged with other entities
    
-   CubitBoolean entity_merged( TopologyEntity *entity );
-     //- Takes a RefEntity, makes sure it is not a volume, and
-     //- checks to see if it has more than one volume.
+  //! Takes a RefEntity, makes sure it is not a volume, and
+  //! checks to see if it has more than one volume.
+  CubitBoolean entity_merged( TopologyEntity *entity );
    
-   CubitStatus merge_all_bodies();
-     //- Compare all RefFaces, RefEdges, and RefVertices in the
-     //- model and merge the matches
+  //! Compare all RefFaces, RefEdges, and RefVertices in the
+  //! model and merge the matches
+  CubitStatus merge_all_bodies();
    
-   CubitStatus merge_bodies( DLIList<Body*>& refbody_list );
-     //- Compare all RefFaces, RefEdges, and RefVertices in 
-     //- refbody_list and merge the matches
+  //! Compare all RefFaces, RefEdges, and RefVertices in 
+  //! refbody_list and merge the matches
+  CubitStatus merge_bodies( DLIList<Body*>& refbody_list );
    
-   CubitStatus merge_volumes( DLIList<RefVolume*>& vol_list,
-                              CubitBoolean print_info = CUBIT_TRUE );
-     //- Compare all RefFaces, RefEdges, and RefVertices in 
-     //- vol_list and merge the matches
+  //! Compare all RefFaces, RefEdges, and RefVertices in 
+  //! vol_list and merge the matches
+  CubitStatus merge_volumes( DLIList<RefVolume*>& vol_list,
+                             CubitBoolean print_info = CUBIT_TRUE );
    
-   CubitStatus merge_all_reffaces    ();
-     //- Compare all RefFaces in the model and merge the matches
+  //! Compare all RefFaces in the model and merge the matches.
+  CubitStatus merge_all_reffaces();
    
-   CubitStatus merge_reffaces_old( DLIList<RefFace*>& refface_list,
+  //! Compare all input RefFaces and merge the matches.
+  CubitStatus merge_reffaces_old( DLIList<RefFace*>& refface_list,
                                CubitBoolean print_info = CUBIT_TRUE);
-     //- Compare all input RefFaces and merge the matches
    
-   CubitStatus merge_reffaces( DLIList<RefFace*>& refface_list,
+  //! Compare all input RefFaces and merge the matches.
+  //! Uses AbstractTree rather than O(nlogn) comparisons.
+  CubitStatus merge_reffaces( DLIList<RefFace*>& refface_list,
                                CubitBoolean print_info = CUBIT_TRUE);
-     //- Compare all input RefFaces and merge the matches
-     //- Uses AbstractTree rather than O(nlogn) comparisons.
 
-   CubitStatus merge_all_refedges();
-     //- Compare all RefEdges in the model and merge the matches
-   
-   CubitStatus old_merge_refedges( DLIList<RefEdge*>& refedge_list,
+  //! Compare all RefEdges in the model and merge the matches.
+  CubitStatus merge_all_refedges();
+  
+  //! Merges specified curves.  List should contains max 20 curves.
+  CubitStatus old_merge_refedges( DLIList<RefEdge*>& refedge_list,
                                CubitBoolean should_clean_out = CUBIT_TRUE,
                                CubitBoolean print_info = CUBIT_TRUE);
-   CubitStatus merge_refedges( DLIList<RefEdge*>& refedge_list,
+
+  //! Compare all input RefEdges and merge the matches
+  //! BE CAREFUL with the should_clean_out flag.  If you set
+  //! it to false, then YOU (the caller) are responsible for
+  //! cleaning out the deactivated geometry.
+  //! Merges specified curves.  If list contains < 20 curves, use old_merge_ref_edges.
+  CubitStatus merge_refedges( DLIList<RefEdge*>& refedge_list,
                                CubitBoolean should_clean_out = CUBIT_TRUE,
                                CubitBoolean print_info = CUBIT_TRUE);
-     //- Compare all input RefEdges and merge the matches
-     //- BE CAREFUL with the should_clean_out flag.  If you set
-     //- it to false, then YOU (the caller) are responsible for
-     //- cleaning out the deactivated geometry.
    
-   CubitStatus merge_all_refvertices();
-     //- Compare all RefVertices in the model and merge the matches
+  //! Compare all RefVertices in the model and merge the matches
+  CubitStatus merge_all_refvertices();
+  
+  //! Compare all input RefVertices and merge the matches. For lists < 20
+  CubitStatus old_merge_refvertices( DLIList<RefVertex*>& refvertex_list,
+                                     CubitBoolean print_info = CUBIT_TRUE );
+
+  //! Compare all input RefVertices and merge the matches.
+  CubitStatus merge_refvertices( DLIList<RefVertex*>& refvertex_list,
+                                 CubitBoolean print_info = CUBIT_TRUE );
    
-   CubitStatus old_merge_refvertices( DLIList<RefVertex*>& refvertex_list,
-                                  CubitBoolean print_info = CUBIT_TRUE );
-   CubitStatus merge_refvertices( DLIList<RefVertex*>& refvertex_list,
-                                  CubitBoolean print_info = CUBIT_TRUE );
-     //- Compare all input RefVertices and merge the matches
-   
-   CubitStatus merge_entities( DLIList<RefEntity*>& entity_list,
+  //! merge the entities in list; asserts if they're not all the same type
+  CubitStatus merge_entities( DLIList<RefEntity*>& entity_list,
                                CubitBoolean should_clean_out = CUBIT_TRUE,
                                CubitBoolean print_info = CUBIT_TRUE);
-     //- merge the entities in list; asserts if they're not all the same type
    
-   CubitStatus unmerge_all();
-     //- Unmerge everything.
+  //! Unmerge everything.
+  CubitStatus unmerge_all();
    
-   CubitStatus 
-   unmerge( DLIList<RefEntity*>& entity_list, CubitBoolean descend = CUBIT_TRUE );
-     //- Unmerge entities in list.
-     //- If decend is true, will decend topology graph, unmerging child topology
-     //- of the passed topology.  If decend is false, a.) passing bodies or volumes
-     //- in entity list will have no effect and b.) when a surface is unmerged
-     //- its child curves will not be unmerged, and the child vertices will not be 
-     //- unmerged when an edge is unmerged.
+  //! Unmerge entities in list.
+  //! If decend is true, will decend topology graph, unmerging child topology
+  //! of the passed topology.  If decend is false, a.) passing bodies or volumes
+  //! in entity list will have no effect and b.) when a surface is unmerged
+  //! its child curves will not be unmerged, and the child vertices will not be 
+  //! unmerged when an edge is unmerged.
+  CubitStatus unmerge( DLIList<RefEntity*>& entity_list, CubitBoolean descend = CUBIT_TRUE );
+   
+  //@{
+  //! Unmerge the passed entity.  All parents must already be
+  //! unmerged.  
+  //! If decend is true, will decend topology graph, unmerging child topology
+  //! of the passed topology.  If decend is false, a.) passing bodies or volumes
+  //! in entity list will have no effect and b.) when a surface is unmerged
+  //! its child curves will not be unmerged, and the child vertices will not be 
+  //! unmerged when an edge is unmerged.
+  CubitStatus unmerge( RefEntity* entity_ptr, CubitBoolean descend = CUBIT_TRUE );
+  CubitStatus unmerge( RefFace*   face_ptr,   CubitBoolean descend = CUBIT_TRUE );
+  CubitStatus unmerge( RefEdge*   edge_ptr,   CubitBoolean descend = CUBIT_TRUE );
+  CubitStatus unmerge( Body*      body_ptr   );
+  CubitStatus unmerge( RefVolume* vol_ptr    );
+  CubitStatus unmerge( RefVertex* vertex_ptr );
+  //@}
      
-   CubitStatus unmerge( RefEntity* entity_ptr, CubitBoolean descend = CUBIT_TRUE );
-   CubitStatus unmerge( RefFace*   face_ptr,   CubitBoolean descend = CUBIT_TRUE );
-   CubitStatus unmerge( RefEdge*   edge_ptr,   CubitBoolean descend = CUBIT_TRUE );
-   CubitStatus unmerge( Body*      body_ptr   );
-   CubitStatus unmerge( RefVolume* vol_ptr    );
-   CubitStatus unmerge( RefVertex* vertex_ptr );
-     //- Unmerge the passed entity.  All parents must already be
-     //- unmerged.  
-     //- If decend is true, will decend topology graph, unmerging child topology
-     //- of the passed topology.  If decend is false, a.) passing bodies or volumes
-     //- in entity list will have no effect and b.) when a surface is unmerged
-     //- its child curves will not be unmerged, and the child vertices will not be 
-     //- unmerged when an edge is unmerged.
+  //! Return number of entities unmerged in last call to one
+  //! of the unmerge methods.  If an entity list is passed,
+  //! it will be populated with unmerged entities.
+  int unmerged_entities( DLIList<RefEntity*>* entities = NULL ) const;
      
-   int unmerged_entities( DLIList<RefEntity*>* entities = NULL ) const;
-     //- Return number of entities unmerged in last call to one
-     //- of the unmerge methods.  If an entity list is passed,
-     //- it will be populated with unmerged entities.
-     
-    CubitStatus separate_bodies( DLIList<Body*>& separate_list,
+  //! Unmerge such that the group of entities in
+  //! separate_list share no topology with the entities
+  //! in from_list, or if from_list is is null, any other
+  //! entities.
+  CubitStatus separate_bodies( DLIList<Body*>& separate_list,
                                  DLIList<Body*>* from_list = NULL );
-      //- Unmerge such that the group of entities in
-      //- separate_list share no topology with the entities
-      //- in from_list, or if from_list is is null, any other
-      //- entities.
-   
-    CubitStatus separate_volumes( DLIList<RefVolume*>& separate_list,
-                                  DLIList<RefVolume*>* from_list = NULL );
-      //- Unmerge such that the group of entities in
-      //- separate_list share no topology with the entities
-      //- in from_list, or if from_list is is null, any other
-      //- entities.
-   
-    CubitStatus separate_faces( DLIList<RefFace*>& separate_list,
-                                DLIList<RefFace*>* from_list = NULL );
-      //- Unmerge such that the group of entities in
-      //- separate_list share no topology with the entities
-      //- in from_list, or if from_list is is null, any other
-      //- entities.
   
-    CubitStatus separate_edges( DLIList<RefEdge*>& separate_list,
-                                DLIList<RefEdge*>* from_list = NULL );
-      //- Unmerge such that the group of entities in
-      //- separate_list share no topology with the entities
-      //- in from_list, or if from_list is is null, any other
-      //- entities.
-   
-   RefFace* force_merge( RefFace* face1, RefFace* face2 );
-   RefEdge* force_merge( RefEdge* edge1, RefEdge* edge2 );
-   RefVertex* force_merge( RefVertex* vtx1, RefVertex* vtx2 );
-   RefEntity* force_merge( RefEntity* ent1, RefEntity* ent2 );
-   RefEntity* force_merge( const DLIList<RefEntity*>& list );
-   
-   static CubitBoolean merge_has_occured();
-   static void set_merge_occurance( CubitBoolean t_or_f );
-     //- Sets/Gets the mergeCalled flag.  This signifies
-     //- that currently a merge operation has been called for 
-     //- the model.
+  //@{
+  //! Unmerge such that the group of entities in
+  //! separate_list share no topology with the entities
+  //! in from_list, or if from_list is is null, any other
+  //! entities.
+  CubitStatus separate_volumes( DLIList<RefVolume*>& separate_list,
+                                DLIList<RefVolume*>* from_list = NULL );
+  //@}
+  
+  //@{
+  //! Unmerge such that the group of entities in
+  //! separate_list share no topology with the entities
+  //! in from_list, or if from_list is is null, any other
+  //! entities.
+  CubitStatus separate_faces( DLIList<RefFace*>& separate_list,
+                              DLIList<RefFace*>* from_list = NULL );
+  //@}
+ 
+  //@{
+  //! Unmerge such that the group of entities in
+  //! separate_list share no topology with the entities
+  //! in from_list, or if from_list is is null, any other
+  //! entities.
+  CubitStatus separate_edges( DLIList<RefEdge*>& separate_list,
+                              DLIList<RefEdge*>* from_list = NULL );
+  //@}
+  
+  //@{
+  //! Force the merging of entities.  
+  //! Entities must have like topology though, i.e, 
+  //! two surfaces must have the same number of vertices and curves.
+  RefFace* force_merge( RefFace* face1, RefFace* face2 );
+  RefEdge* force_merge( RefEdge* edge1, RefEdge* edge2 );
+  RefVertex* force_merge( RefVertex* vtx1, RefVertex* vtx2 );
+  RefEntity* force_merge( RefEntity* ent1, RefEntity* ent2 );
+  RefEntity* force_merge( const DLIList<RefEntity*>& list );
+  
+  //@{
+  //! Sets/Gets the mergeCalled flag.  This signifies
+  //! that currently a merge operation has been called for 
+  //! the model.
+  static CubitBoolean merge_has_occured();
+  static void set_merge_occurance( CubitBoolean t_or_f );
+  //@}
 
-   static void group_results( CubitBoolean t_or_f );
-    //- tells us to group the results or not.
-    
-   static void set_new_ids_on_unmerge( CubitBoolean value );
-   static CubitBoolean get_new_ids_on_unmerge();
-   
-   static void initialize_settings();
+  //! Tells us to group the results or not.
+  static void group_results( CubitBoolean t_or_f );
   
+  //@{
+  //! Get/Sets flag for producing new ids when unmerging.
+  static void set_new_ids_on_unmerge( CubitBoolean value );
+  static CubitBoolean get_new_ids_on_unmerge();
+  //@}
+
+  //! Resets all member variables in this calls to defaults.
+  static void initialize_settings();
+  
+  //! Notifies MergeTool about comparisons found and put on ref entities
   void compare_notify(RefEntity *entity, CubitEventType event);
-    //- notifies MergeTool about comparisons found and put on ref entities
   
+  //! Remove TDCompares from RefEntities.
   void remove_compare_data();
-    //- Remove TDCompares from RefEntities.
     
-    void add_merge_tool_assistant( MergeToolAssistant* mta_ptr );
-    void remove_merge_tool_assistant( MergeToolAssistant* mta_ptr );
-    MergeToolAssistant* find_merge_tool_assistant( const type_info& type );
+  void add_merge_tool_assistant( MergeToolAssistant* mta_ptr );
+  void remove_merge_tool_assistant( MergeToolAssistant* mta_ptr );
+  MergeToolAssistant* find_merge_tool_assistant( const type_info& type );
   
   static void destroy_dead_geometry( CubitBoolean yes_no )
     { destroyDeadGeometry = yes_no; }
 
+  //! This function is to be used only right
+  //! after merging is called.  It is a way to
+  //! access the groups that are created during the
+  //! merge.  Note the groups can be destroyed
+  //! and these pointers can be stale if the
+  //! function is not called immediatly following merging...
   RefGroup* get_group_last_merged_surfs()
-    {
-        //clear this out once this function has been called.
-      RefGroup *temp = lastSurfsMerged;
-      lastSurfsMerged = NULL;
-      return temp;
-    }
-    ///
-    /// This function is to be used only right
-    /// after merging is called.  It is a way to
-    /// access the groups that are created during the
-    /// merge.  Note the groups can be destroyed
-    /// and these pointers can be stale if the
-    /// function is not called immediatly following merging...
-    ///
+  {
+      //clear this out once this function has been called.
+    RefGroup *temp = lastSurfsMerged;
+    lastSurfsMerged = NULL;
+    return temp;
+  }
+
+
+  //! This function is to be used only right
+  //! after merging is called.  It is a way to
+  //! access the groups that are created during the
+  //! merge.  Note the groups can be destroyed
+  //! and these pointers can be stale if the
+  //! function is not called immediatly following merging...
   RefGroup* get_group_last_merged_curvs()
-    {
-        //clear this out once this function has been called.
-      RefGroup *temp = lastCurvsMerged;
-      lastCurvsMerged = NULL;
-      return temp;
-    }
-    ///
-    /// This function is to be used only right
-    /// after merging is called.  It is a way to
-    /// access the groups that are created during the
-    /// merge.  Note the groups can be destroyed
-    /// and these pointers can be stale if the
-    /// function is not called immediatly following merging...
-    ///
+  {
+    //clear this out once this function has been called.
+    RefGroup *temp = lastCurvsMerged;
+    lastCurvsMerged = NULL;
+    return temp;
+  }
+
+  //! This function is to be used only right
+  //! after merging is called.  It is a way to
+  //! access the groups that are created during the
+  //! merge.  Note the groups can be destroyed
+  //! and these pointers can be stale if the
+  //! function is not called immediatly following merging...
   RefGroup* get_group_last_merged_verts()
-    {
-        //clear this out once this function has been called.
-      RefGroup *temp = lastVertsMerged;
-      lastVertsMerged = NULL;
-      return temp;
-    }
-    ///
-    /// This function is to be used only right
-    /// after merging is called.  It is a way to
-    /// access the groups that are created during the
-    /// merge.  Note the groups can be destroyed
-    /// and these pointers can be stale if the
-    /// function is not called immediatly following merging...
-    ///
+  {
+      //clear this out once this function has been called.
+    RefGroup *temp = lastVertsMerged;
+    lastVertsMerged = NULL;
+    return temp;
+  }
 
-  //Note:  The caller of the following 4 functions is responsible to 
-  //delete the DLIList*s that are returned.
-   CubitStatus find_mergeable_refentities( DLIList<RefEntity*> &entities,
+
+  //! From the specified list of entities, find mergeable surfaces, curves,
+  //! and vertices.  If two surfaces are found to be mergeable, their mergeable 
+  //! children, i.e, curves and vertices, are not included reported. 
+  //! Note:  The caller of the following 4 functions is responsible to 
+  //! delete the DLIList*s that are returned.
+  CubitStatus find_mergeable_refentities( DLIList<RefEntity*> &entities,
               DLIList< DLIList<RefFace*>*> &lists_of_mergeable_ref_faces,
               DLIList< DLIList<RefEdge*>*> &lists_of_mergeable_ref_edges,
               DLIList< DLIList<RefVertex*>*> &lists_of_mergeable_ref_vertices);
-   CubitStatus find_mergeable_reffaces( DLIList<RefEntity*> &entities,
+
+  //! From the specified list of entities, find mergeable surfaces.
+  //! Note:  The caller of this function responsible for  
+  //! deleting the DLIList*s that are returned.
+  CubitStatus find_mergeable_reffaces( DLIList<RefEntity*> &entities,
               DLIList< DLIList<RefFace*>*> &lists_of_mergeable_ref_faces,
               bool clean_up_compare_data = true );
-   CubitStatus find_mergeable_refedges( DLIList<RefEntity*> &entities,
+
+  //! From the specified list of entities, find mergeable curves.
+  //! Note:  The caller of this function responsible for  
+  //! deleting the DLIList*s that are returned.
+  CubitStatus find_mergeable_refedges( DLIList<RefEntity*> &entities,
               DLIList< DLIList<RefEdge*>*> &lists_of_mergeable_ref_edges,
               bool clean_up_compare_data = true );
-   CubitStatus find_mergeable_refvertices( DLIList<RefEntity*> &entities,
+
+  //! From the specified list of entities, find mergeable vertices.
+  //! Note:  The caller of this function responsible for  
+  //! deleting the DLIList*s that are returned.
+  CubitStatus find_mergeable_refvertices( DLIList<RefEntity*> &entities,
               DLIList< DLIList<RefVertex*>*> &lists_of_mergeable_ref_vertices,
               bool clean_up_compare_data = true );
 
-   //Faster comparison that only check for mergeable refedges between volumes.
-   //It reports all edges, even when the owning face is mergeable
-   CubitStatus find_only_mergeable_curves( DLIList<BodySM*> &body_list, 
-                  DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves );
+ 
+  //@{
+  //! Faster comparison that only checks for mergeable RefEdge 
+  //! or curves between bodies, surfaces, or curves.  
+  //! It reports all edges, even if the owning faces are mergeable
+  CubitStatus find_only_mergeable_curves( DLIList<Surface*> &surf_list, 
+                 DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves );
+  CubitStatus find_only_mergeable_curves( DLIList<Curve*> &all_curves, 
+                 DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves );
+  CubitStatus find_only_mergeable_curves( DLIList<BodySM*> &body_list, 
+                 DLIList< DLIList<Curve*>*> &lists_of_mergeable_curves );
+   CubitStatus find_only_mergeable_refedges( DLIList<Body*> &body_list, 
+                  DLIList< DLIList<RefEdge*>*> &lists_of_mergeable_ref_edges );
+  //@}
 
-   CubitStatus find_only_mergeable_surfaces( DLIList<BodySM*> &body_list, 
-                  DLIList< DLIList<Surface*>*> &lists_of_mergeable_surfaces);
+  //! Faster comparison that only checks for mergeable surfaces. 
+  CubitStatus find_only_mergeable_surfaces( DLIList<BodySM*> &body_list, 
+                 DLIList< DLIList<Surface*>*> &lists_of_mergeable_surfaces);
 
-   CubitStatus find_only_mergeable_refedges( DLIList<Body*> &body_list, 
-                  DLIList< DLIList<RefEdge*>*> &lists_of_mergeable_ref_edges );
-                                             
-   CubitBoolean about_spatially_equal( Surface *surf_1, Surface *surf_2,
-                                       double tolerance_factor );
-   CubitBoolean about_spatially_equal( LoopSM *loop_1, LoopSM *loop_2, 
-                                       CubitSense relative_sense, double tolerance_factor );
-   CubitBoolean about_spatially_equal( CoEdgeSM *coedge_1, CoEdgeSM *coedge_2, 
-                                       CubitSense relative_sense, double tolerance_factor );
-   CubitBoolean about_spatially_equal( Curve *curve_1, Curve *curve_2, 
-                                       CubitSense &relative_sense, double tolerance_factor );
-   CubitBoolean about_spatially_equal( Point *point_1, Point *point_2, 
-                                               double tolerance_factor );
+  //! Check for mergeability of two surfaces. 
+  CubitBoolean about_spatially_equal( Surface *surf_1, Surface *surf_2,
+                                      double tolerance_factor );
+
+  //! Check for mergeability of two loops. 
+  CubitBoolean about_spatially_equal( LoopSM *loop_1, LoopSM *loop_2, 
+                                      CubitSense relative_sense, double tolerance_factor );
+
+  //! Check for mergeability of two coedges. 
+  CubitBoolean about_spatially_equal( CoEdgeSM *coedge_1, CoEdgeSM *coedge_2, 
+                                      CubitSense relative_sense, double tolerance_factor );
+
+  //! Check for mergeability of two curves. 
+  CubitBoolean about_spatially_equal( Curve *curve_1, Curve *curve_2, 
+                                      CubitSense &relative_sense, double tolerance_factor );
+
+  //! Check for mergeability of two points. 
+  CubitBoolean about_spatially_equal( Point *point_1, Point *point_2, 
+                                      double tolerance_factor );
   
-   protected :
+  protected :
    
-   CubitStatus separate_entities( DLIList<TopologyEntity*>& separate_list,
-                                  DLIList<TopologyEntity*>* from_list = NULL );
-    //- Common implementation for public separate() functions.
-    //- All passed entities must be of the same type.
-    //- Unmerge such that the group of entities in
-    //- separate_list share no topology with the entities
-    //- in from_list, or if from_list is is null, any other
-    //- entities.
-   
-   BasicTopologyEntity* can_separate( DLIList<TopologyBridge*>& bridge_list,
-                                      bool check_parents );
-    //- Check if the passed list of bridges can be unmerged and if
-    //- so, return their owning BTE.  If check_parents is false, skip
-    //- check for merged parents.
+  //! Common implementation for public separate() functions.
+  //! All passed entities must be of the same type.
+  //! Unmerge such that the group of entities in
+  //! separate_list share no topology with the entities
+  //! in from_list, or if from_list is is null, any other
+  //! entities.
+  CubitStatus separate_entities( DLIList<TopologyEntity*>& separate_list,
+                                 DLIList<TopologyEntity*>* from_list = NULL );
+ 
+  //! Check if the passed list of bridges can be unmerged and if
+  //! so, return their owning BTE.  If check_parents is false, skip
+  //! check for merged parents.
+  BasicTopologyEntity* can_separate( DLIList<TopologyBridge*>& bridge_list,
+                                     bool check_parents );
   
-   RefFace* separate_face( DLIList<Surface*>& bridges, bool descend );
-    //- Split a merged entity into two such that the returned, new
-    //- entity contains the passed list of bridges.  If descend
-    //- is false, skip attempt to unmerge child entities.
+  //! Split a merged entity into two such that the returned, new
+  //! entity contains the passed list of bridges.  If descend
+  //! is false, skip attempt to unmerge child entities.
+  RefFace* separate_face( DLIList<Surface*>& bridges, bool descend );
   
-   RefEdge* separate_edge( DLIList<Curve*>& bridges, bool descend );
-    //- Split a merged entity into two such that the returned, new
-    //- entity contains the passed list of bridges.  If descend
-    //- is false, skip attempt to unmerge child entities.
+  //! Split a merged entity into two such that the returned, new
+  //! entity contains the passed list of bridges.  If descend
+  //! is false, skip attempt to unmerge child entities.
+  RefEdge* separate_edge( DLIList<Curve*>& bridges, bool descend );
    
    RefVertex* separate_vertex( DLIList<Point*>& bridges );
     //- Split a merged entity into two such that the returned, new

Modified: cgm/branches/cubit/geom/ModelQueryEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/ModelQueryEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/ModelQueryEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -89,6 +89,8 @@
       ~ModelQueryEngine() ;
       //- Destructor
 
+      static void delete_instance() {if(instance_) delete instance_; }
+
       //HEADER- Query functions on single source objects
       
       CubitStatus query_model( ModelEntity & source_object,

Modified: cgm/branches/cubit/geom/OffsetSplitTool.cpp
===================================================================
--- cgm/branches/cubit/geom/OffsetSplitTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/OffsetSplitTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -23,7 +23,7 @@
 #include "GeometryQueryTool.hpp"
 #include "CubitUtil.hpp"
 #include "DLIList.hpp"
-#include "GfxDebug.hpp"
+#include "GfxPreview.hpp"
 #include "GMem.hpp"
 #include "Curve.hpp"
 #include "BodySM.hpp"
@@ -61,17 +61,20 @@
     if(ref_face_list.size() < 1)
     {
         PRINT_ERROR( "No surfaces specified for splitting\n" );
-        return CUBIT_FAILURE;
-    }
+		return CUBIT_FAILURE;
+	}
 
-    if(edge_list.size() < 1)
-    {
-        PRINT_ERROR( "No curves specified for splitting\n" );
-        return CUBIT_FAILURE;
-    }
+	if(edge_list.size() < 1)
+	{
+		PRINT_ERROR( "No curves specified for splitting\n" );
+		return CUBIT_FAILURE;
+	}
 
-    DLIList<Curve*> offset_curves;
-    DLIList<DLIList<Curve*>*> imprint_list;
+	// clear the preview graphics
+	GfxPreview::clear();
+
+	DLIList<Curve*> offset_curves;
+	DLIList<DLIList<Curve*>*> imprint_list;
     for(int seg = 1;seg<num_segs+1;seg++)
     {
         // set the current distance
@@ -201,9 +204,6 @@
             united_body_list = body_list;
         else
         {
-#ifdef BOYD17 
-            BodySM* return_body = 0;
-#endif
             if(!gme->unite(body_list,united_body_list))//united_body_list))
             {
                 if(body_list.size() == 1)
@@ -241,9 +241,9 @@
 
                 // remove any very small curves from the intersection graph
                 // for some reason ACIS seems to return zero length curves
-                for(int k=0;k<intersection_curves.size();k++)
+                for(int k = intersection_curves.size();k--;)
                 {
-                    Curve* cur_curve = intersection_curves.get_and_step();
+                    Curve* cur_curve = intersection_curves[k];
                     double len = cur_curve->
                         length_from_u(cur_curve->start_param(),cur_curve->end_param());
 
@@ -323,7 +323,7 @@
 
         Body *new_body_ptr;
         if( GeometryModifyTool::instance()->imprint( surface_list,
-            imprint_list, new_body_ptr ) == CUBIT_FAILURE )
+            imprint_list, new_body_ptr, false, false ) == CUBIT_FAILURE )
         {
             //Delete the Curve entities
             for(i= offset_curves.size();i--;)
@@ -370,7 +370,7 @@
         draw_preview( curve_ptr, CUBIT_FALSE, color );
     }
 
-    GfxDebug::flush();
+    GfxPreview::flush();
 
     return CUBIT_SUCCESS;
 }
@@ -380,23 +380,26 @@
     CubitBoolean flush,
     int color )
 {
-    int num_points;
     CubitStatus result;
     GMem g_mem;
 
     // get the graphics
     result = curve_ptr->get_geometry_query_engine()->
-        get_graphics( curve_ptr, num_points, &g_mem );
+        get_graphics( curve_ptr, &g_mem );
 
-    if (result==CUBIT_FAILURE || num_points == 0)
+    if (result==CUBIT_FAILURE || g_mem.pointListCount == 0)
     {
-        PRINT_WARNING("Unable to preview a curve\n" );
+        PRINT_WARNING("Unable to preview a curve\n" );;
+        double len = curve_ptr->
+            length_from_u(curve_ptr->start_param(),curve_ptr->end_param());
+
+        PRINT_WARNING("Curve len: %f\n",len);
     }
 
     // Draw the polyline
-    GfxDebug::draw_polyline( g_mem.point_list(), g_mem.pointListCount, color );
+    GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, color );
     if( flush )
-        GfxDebug::flush();
+        GfxPreview::flush();
 
     return CUBIT_SUCCESS;
 }

Added: cgm/branches/cubit/geom/PeriodicParamTool.cpp
===================================================================
--- cgm/branches/cubit/geom/PeriodicParamTool.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/PeriodicParamTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,153 @@
+//- Class: PeriodicParamTool
+//-------------------------------------------------------------------------
+// Filename      : PeriodicParamTool.cpp
+//
+// Purpose       : Handles surfaces that have a periodic parameterization
+//		           Uses, but modifies, the underlying engine parameterization
+//
+//
+// Creator       : Ray J. Meyers
+//
+// Creation Date : 12/15/2008
+//
+// Owner         : Ray J. Meyers
+//-------------------------------------------------------------------------
+
+#include "PeriodicParamTool.hpp"
+//#include "CastTo.hpp"
+#include "Surface.hpp"
+//#include "DLIList.hpp"
+
+//-------------------------------------------------------------------------
+// Function:    PeriodicParamTool
+// Description: constructor
+// Author:      chynes
+// Date:        7/10/2002
+//-------------------------------------------------------------------------
+PeriodicParamTool::PeriodicParamTool(Surface *surf) 
+{
+	//- update private variables
+	refSurf = surf;
+	uOffset = 0.0;
+	vOffset = 0.0;
+  uPeriod = 0.0;
+  vPeriod = 0.0;
+  mirrorSurface = false;
+
+}
+
+//-------------------------------------------------------------------------
+// Function:    PeriodicParamTool
+// Description: deconstructor
+// Author:      chynes
+// Date:        7/10/2002
+//-------------------------------------------------------------------------
+PeriodicParamTool::~PeriodicParamTool() {}
+
+//===================================================================================
+// Function: set_up_space (Public)
+// Description: sets up space of flattening
+// Author: chynes
+// Date: 7/10/02
+//===================================================================================
+CubitStatus PeriodicParamTool::set_up_space(double u_period, double v_period, double u_offset, double v_offset)
+{
+	// store the u and periods 
+
+	uPeriod = u_period;
+	vPeriod = v_period;
+	uOffset = u_offset;
+	vOffset = v_offset;
+
+	
+	CubitStatus rv = CUBIT_SUCCESS;
+
+	return rv; 
+}
+
+//===================================================================================
+// Function: transform_to_uv (Public)
+// Description: same as title, the local sizing will be returned in the z coord 
+// Author: chynes
+// Date: 7/10/02
+//===================================================================================
+CubitStatus PeriodicParamTool::transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location) 
+{
+	 
+	double u,v;
+
+	CubitStatus rv = refSurf->u_v_from_position(xyz_location, u, v);
+
+	// offset values to avoid parameter discontinuity
+
+	if (uPeriod && u < uOffset)
+	{
+		u += uPeriod;
+	}
+  
+  // mirror surface if required to get correct loop orientation
+  if (mirrorSurface)
+  {
+    u = -u;
+  }
+
+	if (vPeriod && v < vOffset)
+	{
+		v += vPeriod;
+	}
+
+	uv_location.set(u,v,1.0);
+
+
+	return rv;
+}
+
+//===================================================================================
+// Function: transform_to_xyz (Public)
+// Description: same as title
+// Author: chynes
+// Date: 7/10/02
+//===================================================================================
+CubitStatus PeriodicParamTool::transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location) 
+{
+	double u = uv_location.x();	
+  if (mirrorSurface)
+  {
+    u = -u;
+  }
+	if (u > uPeriod)
+	{
+		u = u - uPeriod;
+	}
+	double v = uv_location.y();
+	if (v > vPeriod)
+	{
+		v = v - vPeriod;
+	}
+	xyz_location = refSurf->position_from_u_v(u,v);
+
+
+	return CUBIT_SUCCESS;
+}
+
+void PeriodicParamTool::mirror_surface(bool true_false)
+{
+  mirrorSurface = true_false;
+  if (mirrorSurface)
+    PRINT_INFO("Loops appear backwards, mirroring surface...\n");
+ 
+}
+
+CubitStatus PeriodicParamTool::uv_derivitives(double u_param, double v_param, 
+                                              CubitVector &du, CubitVector &dv)
+{
+  if (mirrorSurface)
+    u_param = -u_param;
+  if (u_param > uPeriod)
+    u_param = u_param-uPeriod;
+  if (v_param > vPeriod)
+    v_param = v_param-vPeriod;
+  refSurf->uv_derivitives(u_param, v_param, du, dv);
+  return CUBIT_SUCCESS;
+}
+//EOF

Added: cgm/branches/cubit/geom/PeriodicParamTool.hpp
===================================================================
--- cgm/branches/cubit/geom/PeriodicParamTool.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/PeriodicParamTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,60 @@
+//- Class: PeriodicParamTool
+//-------------------------------------------------------------------------
+// Filename      : PeriodicParamTool.cpp
+//
+// Purpose       : Handles surfaces that have a periodic parameterization
+//		           Uses, but modifies, the underlying engine parameterization
+//
+// Creator       : Ray J. Meyers
+//
+// Creation Date : 12/15/2008
+//
+// Owner         : Ray J. Meyers
+//-------------------------------------------------------------------------
+
+#ifndef PERIODIC_PARAM_TOOL_HPP
+#define PERIODIC_PARAM_TOOL_HPP
+
+#include "ParamTool.hpp"
+#include "CubitGeomConfigure.h"
+
+class Surface;
+class CubitVector;
+class CubitNode;
+template <class X> class DLIList;
+
+class CUBIT_GEOM_EXPORT PeriodicParamTool : public ParamTool
+{
+public:
+
+	//- constructor
+	PeriodicParamTool(Surface *surf);
+
+	//- destructor
+	~PeriodicParamTool();
+	
+	CubitStatus set_up_space(double u_period, double v_period, double u_offset, double v_offset);
+
+	CubitStatus transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location);
+
+	CubitStatus transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location);
+
+  void mirror_surface( bool true_false);
+
+  CubitStatus uv_derivitives( double u_param, double v_param, 
+		CubitVector &du, CubitVector &dv );
+
+private:
+
+	Surface *refSurf;
+	double uPeriod;
+	double vPeriod;
+	double uOffset;
+	double vOffset;
+  bool mirrorSurface;
+
+	//- reference surface
+};
+
+#endif // ACIS_PARAM_TOOL_HPP
+

Modified: cgm/branches/cubit/geom/RefEdge.cpp
===================================================================
--- cgm/branches/cubit/geom/RefEdge.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEdge.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -202,7 +202,7 @@
     // Move the point to the Curve (the following call modifes the values
     // of the input "vector", if necessary)
   CubitVector closest_point;
-  curvePtr->closest_point(vector, closest_point);
+  curvePtr->closest_point_trimmed(vector, closest_point);
   vector.set( closest_point.x(),
               closest_point.y(),
               closest_point.z() );
@@ -309,7 +309,12 @@
   DLIList<CoEdge*> co_edge_list;
   get_co_edges( co_edge_list, ref_face_ptr );
  
-  assert( co_edge_list.size() == 1 ); 
+  if( co_edge_list.size() != 1 )
+  {
+      PRINT_ERROR( "Ambiguous case in tangent calculation.\n" );
+	  return CUBIT_FAILURE;
+  }
+//  assert( co_edge_list.size() == 1 ); 
   
   if ( co_edge_list.get()->get_sense() == CUBIT_REVERSED )
       tangent_vec = -tangent_vec;
@@ -1278,18 +1283,16 @@
     {
       CubitVector start_pt = start_vertex()->coordinates();
       CubitVector end_pt   = end_vertex()->coordinates();
-      PRINT_WARNING (
-          "WARNING (RefEdge::initialize): Edge has zero arclength.\n"
-          "  Start vertex location is (%9.2f, %9.2f, %9.2f ).\n"
-          "  End   vertex location is (%9.2f, %9.2f, %9.2f ).\n",
+      PRINT_WARNING ( "(RefEdge::initialize): Edge has zero arclength.\n"
+                      "  Start vertex location is (%9.2f, %9.2f, %9.2f ).\n"
+                      "  End   vertex location is (%9.2f, %9.2f, %9.2f ).\n",
           start_pt.x(), start_pt.y(), start_pt.z(),
           end_pt.x(), end_pt.y(), end_pt.z() );
     }
     else if (!mSuppressEdgeLengthWarning)
     {
-      PRINT_WARNING(
-          "WARNING: Edge found with zero arclength\n"
-          "  For cones, this may be normal.\n");
+      PRINT_WARNING( "Edge found with zero arclength\n"
+                     "  For cones, this may be normal.\n");
     }
     
   }
@@ -1444,8 +1447,7 @@
     return CUBIT_FAILURE;
   }
   
-  int junk;
-  return curve_ptr->get_geometry_query_engine()->get_graphics(curve_ptr,junk,
+  return curve_ptr->get_geometry_query_engine()->get_graphics(curve_ptr,
     &polyline, tolerance);
 }
 
@@ -1469,3 +1471,70 @@
 	mSuppressEdgeLengthWarning = flag;
 }
     
+CubitStatus RefEdge::evaluate_exterior_angle(double *exterior_angle)
+{
+  //- Get the center point of this curve
+  CubitVector center = this->center_point();
+  CubitVector surf_norm[2];
+  CubitVector tangent;
+  RefFace* ref_face = NULL;
+  RefEdge* next_curve = NULL;
+
+  int i, j, k;
+
+    //- Get surfaces on this curve
+  DLIList<RefFace*> surf_list;
+  this->ref_faces(surf_list);
+  if(surf_list.size() == 2)
+  {
+    for( i = 0; i < surf_list.size(); i++)
+    {
+      RefFace* this_surf = surf_list.get_and_step();
+      surf_norm[i] = this_surf->normal_at(center);
+      if( i == 1)
+      {
+          //- Get the referance surface and curve to get exterior angle 
+        ref_face = this_surf;
+        DLIList<DLIList<RefEdge*>*> loop_lists;
+        ref_face->ref_edge_loops(loop_lists);
+        for( j = 0; j < loop_lists.size(); j++ )
+        {
+          DLIList<RefEdge*>* current_list = loop_lists.get_and_step();
+          for( k = 0; k < current_list->size(); k++ )
+          {
+            RefEdge* current_curve = current_list->get_and_step();
+            if( current_curve == this )
+            {
+              next_curve = current_list->get();
+              break;
+            }
+          }
+          if(next_curve != NULL)
+              break;
+        }
+      }
+    }
+  }
+  else
+  {
+    *exterior_angle = 0.0;
+    PRINT_ERROR("There aren't 2 surfaces on curve %d.  Can't compute angle.\n", this->id());
+    return CUBIT_FAILURE;
+  }
+
+  this->tangent(center, tangent, next_curve, ref_face);
+
+    //Find the angle from normal 1 to normal 0.
+  double rad_angle = tangent.vector_angle_quick(surf_norm[1], surf_norm[0]); //angle in radians
+  double angle = rad_angle * (180.0 / 3.14159); //angle in degrees
+
+    //Now convert to the exterior angle between the two surfaces.
+  angle += 180.0;
+  if( angle > 360.0 )
+      angle -= 360.0;
+    
+    //- Return the exterior angle for this curve in degrees.
+  *exterior_angle = angle;
+  return CUBIT_SUCCESS;
+}
+

Modified: cgm/branches/cubit/geom/RefEdge.hpp
===================================================================
--- cgm/branches/cubit/geom/RefEdge.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEdge.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -116,7 +116,7 @@
   
   CubitSense sense( RefFace *face );
     //- Sense of this edge wrt the given face.
-    //- Return CUBIT_FORWARD or CUBIT_REVERSE.
+    //- Return CUBIT_FORWARD or CUBIT_REVERSED.
     //- Returns CUBIT_UNKNOWN if there is more than one coedge, and
     //- senses don't agree, or if there are no coedges.
     
@@ -444,6 +444,26 @@
 
   double length_from_u( double parameter1,
                         double parameter2 );
+    //R double arc length
+    //I double parameter1, parameter value of one end of arc
+    //I double parameter2, parameter value of the other end of arc
+    //
+    //Calculates, the distance along the curve between parameters
+    // parameter1 and parameter2.
+    //
+    // The order of the paramters does not affect the result.
+    // That is, switching parameter1 and parameter2 will
+    // result in the same arc length.
+    //
+    // The resulting length is always non-negative.
+    //
+    // For periodic curves, the length is calculated along
+    // the curve in the diretion of increasing parameter value.
+    // Therefore, if the caller wants the length calculation
+    // to be in a direction that crosses the periodic break,
+    // the interval [parameter1, parameter2] should span a
+    // break point in the period.
+  
 
   CubitBoolean is_periodic();
     //R CubitBoolean
@@ -502,6 +522,12 @@
   virtual int validate();
     //- Check that entity is valid. Returns number of problems detected.
 
+  CubitStatus evaluate_exterior_angle(double *exterior_angle);
+    //- Calculate the exterior angle between this curve and the
+    //- attached surfaces.  This function assumes that the curve is
+    //- only attached to two (2) surfaces, otherwise it returns CUBIT_FAILURE;
+
+
 //=========  Add Code by SRS of Cat,  3/3/99 2:28:31 PM  =========
   CubitBoolean is_tolerant();
     //- Returns CUBIT_TRUE if refedge is a tolerant edge.  Tolerant

Modified: cgm/branches/cubit/geom/RefEntity.cpp
===================================================================
--- cgm/branches/cubit/geom/RefEntity.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEntity.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -69,10 +69,16 @@
   markedFlag           = CUBIT_FALSE;
   listFlag             = CUBIT_FALSE;
   mColor = CUBIT_DEFAULT_COLOR;
+
+  CGMHistory::Event evt(CGMHistory::ENTITY_CREATED, this);
+  GeometryQueryTool::instance()->history().add_event(evt);
 }
 
 RefEntity::~RefEntity()
 {
+  CGMHistory::Event evt(CGMHistory::ENTITY_DELETED, this);
+  GeometryQueryTool::instance()->history().add_event(evt);
+
   // Remove the name of this entity from the entity name map
   RefEntityName::instance()->remove_refentity_name(this, CUBIT_FALSE);
   
@@ -627,8 +633,8 @@
   }
   if ( all_same )
   {
-    ref_entities.get()->get_child_ref_entities(join_set);
-    return join_set.get();
+    join_set.append(ref_entities.get());
+    return ref_entities.get();
   }  
 
     // they aren't all the same; get all the children, intersect the lists,
@@ -932,13 +938,22 @@
   
     // Check that measure is positive
   int error = 0;
-  double this_measure = measure();
-  if (this_measure <= 0.0) {
-    PRINT_WARNING("\tWARNING: non-positive %s (%f) for %s, (%s %d)\n",
-                  measure_label().c_str(), this_measure,
-                  entity_name().c_str(), class_name(), id());
-    error++;
-  }    
+
+  Body *tmp_body = CAST_TO( this, Body);
+  bool is_sheet_body = false;
+  if( tmp_body )
+    is_sheet_body = tmp_body->is_sheet_body();
+  
+  if( false == is_sheet_body )
+  {
+    double this_measure = measure();
+    if (this_measure <= 0.0) {
+      PRINT_WARNING("\tWARNING: non-positive %s (%f) for %s, (%s %d)\n",
+                    measure_label().c_str(), this_measure,
+                    entity_name().c_str(), class_name(), id());
+      error++;
+    }  
+  }
   return error;
 }
 

Modified: cgm/branches/cubit/geom/RefEntity.hpp
===================================================================
--- cgm/branches/cubit/geom/RefEntity.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEntity.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -58,7 +58,7 @@
 
 
 // ********** END ENUM DEFINITIONS       **********
-
+//! Base class for all geometry entities, body, volume, surface... 
 class CUBIT_GEOM_EXPORT RefEntity: public CubitEntity,
                  public CubitObservable,
                  public ToolDataUser,
@@ -73,117 +73,146 @@
     //- A pure virtual destructor - this ensures that the class is
     //- non-instantiable.
 
-    // Class name related functions
+  //! \brief Gets the class name of a RefEntity type. 
   static const char* get_ref_class_name(const type_info& ref_type);
   
-    // Name-related functions
+  //! \brief Gets the RefEntity with the passed in name.
   static RefEntity* get_by_name(const CubitString& name);
+
+  //! \brief Gets the name of this RefEntity.
   CubitString entity_name() const;
+  
+  //! \brief Sets the name of this RefEntity.
   CubitStatus entity_name (CubitString name);
+
+  //! \brief Gets the names of this RefEntity.
   void entity_names(DLIList<CubitString*> &names) const;
+
+  //! \brief Get the number of names this RefEntity has.
   int num_names() const;
+
+  //! \brief Generates a default name for this RefEntity.  'name' is prepended
+  //! to the default name.
   CubitStatus generate_default_name ( CubitString &name );
+
+  //! \brief Assigns a default name to the entity. 
   CubitStatus assign_default_name( CubitBoolean user_setting = CUBIT_FALSE );
+
   CubitStatus remove_entity_name(CubitString const & name);
   CubitStatus remove_entity_names();
   void merge_entity_names(RefEntity* dead_entity);
   void switch_entity_names(RefEntity *other_entity);
-    //- Functions related to naming of RefEntity objects
-  
+ 
+  //@{
+  //- Generic flag for temporary use by algorithms.
+  //- Value is volatile and may change unexpectedly.
   virtual void marked(int value);
   virtual int  marked ();
-    //- Generic flag for temporary use by algorithms.
-    //- Value is volatile and may change unexpectedly.
+  //@}
+  
+  //! \brief Setting auto merge status flag.
+  virtual void is_mergeable(AutoMergeStatus val);
 
-  virtual void is_mergeable(AutoMergeStatus val);
+  //! \brief Gets auto merge status flag.
   AutoMergeStatus merge_status() const;
+
+  //! \brief Query to see if entity is free to merge.
   bool is_mergeable();
+
+  //! \brief Query to see if entity is merged.
   CubitBoolean is_merged();
   // return true if this RefEntity has multiple TopologyBridges.
 
+  //! Updates the auto merge state of the entity.   
   void update_auto_merge_state();
-    //- Set/Get the mergeable status for this entity.
     
+  //! \brief Get whether all child entities are mergeable.
   virtual bool children_mergeable();
-    //- Get whether all child entities are mergeable.
   
+  //! Allow unmerging and other operations.  Default in 
+  //! RefEntity always returns true.  Provided for
+  //! derived classes to override.
   virtual int can_modify();
-    //- Allow unmerging and other operations.  Default in 
-    //- RefEntity always returns true.  Provided for
-    //- derived classes to override.
   
+  //! Returns the geometric dimension of the entity. 
+  //! vertex == 0, edge == 1, etc.
   virtual int dimension() const; 
-    // Returns the geometric dimension of the entity. 
-    // vertex == 0, edge == 1, etc.
   
+  //! Appends all immediate (child) RefEntities owned by this RefEntity to 
+  //! entity_list. (The query goes down just one dimension.)
   virtual void get_child_ref_entities(DLIList<RefEntity*>& entity_list); 
-    //- Appends all immediate (child) RefEntities owned by this RefEntity to 
-    //- entity_list. (The query goes down just one dimension.)
   
+  //! Appends all child RefEntities owned by this entity to entity_list.
+  //! (The query recurses all the way down to RefEntities of dimension 0).
   void get_all_child_ref_entities(DLIList<RefEntity*>& entity_list);
-    //- Appends all child RefEntities owned by this entity to entity_list.
-    //- (The query recurses all the way down to RefEntities of dimension 0).
   
+  //! Appends all child RefEntities owned by entities in input_list to output_list
   static void get_all_child_ref_entities(DLIList<RefEntity*>& input_list,
 				  DLIList<RefEntity*>& output_list );
-  //- Appends all child RefEntities owned by entities in input_list to output_list
 
 
+  //! Gather the boundary entities of the entity_list into the bdy_list. 
+  //! Entities appear once in bdy_list, and will not appear in bdy_list
+  //! if they are already in the entity_list.
+  //! Uses listMark.
   static void gather_bdy_entities( DLIList<RefEntity*> &entity_list, 
                                    DLIList<RefEntity*> &bdy_list );
-    // Gather the boundary entities of the entity_list into the bdy_list. 
-    // Entities appear once in bdy_list, and will not appear in bdy_list
-    // if they are already in the entity_list.
-    // Uses listMark.
 
+  //! Appends all RefEntities that own this (parent RefEntities) to 
+  //! entity_list.
+  //! (The query goes up just one dimension. For example, if this is a
+  //! vertex, the resulting list contains only RefEdges).
   virtual void get_parent_ref_entities(DLIList<RefEntity*>& entity_list);
-    //- Appends all RefEntities that own this (parent RefEntities) to 
-    //- entity_list.
-    //- (The query goes up just one dimension. For example, if this is a
-    //- vertex, the resulting list contains only RefEdges).
   
+  //! Appends all parent RefEntities owned by this entity to entity_list.
+  //! Recurses up to RefVolumes, or RefBodies if get_bodies is true.
   void get_all_parent_ref_entities(DLIList<RefEntity*>& entity_list,
                                    const int get_bodies = CUBIT_FALSE );
-    //- Appends all parent RefEntities owned by this entity to entity_list.
-    //- Recurses up to RefVolumes, or RefBodies if get_bodies is true.
   
+  //! Modify the input list to contain the list of RefEntities that are
+  //! the parents of each of the RefEntities in the original list.
   static void change_to_parent_ref_entities( DLIList<RefEntity*>& ancestors );
-    //- Modify the input list to contain the list of RefEntities that are
-    //- the parents of each of the RefEntities in the original list.
-  
+ 
+  //@{
+  //! RefEntity* join( RefEntity* ref_entity_2 );
+  //! Computes the geometric "join" of elements (elements on the list or 
+  //! this and ref_entity_2).  
+  //! Definition "Join" = The lowest dimensional entitity that
+  //! is a higher dimensional ancestor of them all. 
+  //! Note join could be one of the entities itself, NULL, 
+  //! or multiple elements.
+  //! E.g. The join of a vertex and a curve containing the vertex is 
+  //! the curve. The join of two curves of a split cylinder is 
+  //! both containing surfaces.
+  //! The join of two entities in separate, unmerged volumes is null.
+  //! Returns the first element of the join_set, or NULL if set is empty.
   RefEntity *join( RefEntity* ref_entity_2, DLIList<RefEntity*> &join_set );
   static RefEntity *join( DLIList<RefEntity*> &ref_entities, 
                           DLIList<RefEntity*> &join_set );
-    // RefEntity* join( RefEntity* ref_entity_2 );
-    //- Computes the geometric "join" of elements (elements on the list or 
-    //- this and ref_entity_2).  
-    //- Definition "Join" = The lowest dimensional entitity that
-    //- is a higher dimensional ancestor of them all. 
-    //- Note join could be one of the entities itself, NULL, 
-    //- or multiple elements.
-    //- E.g. The join of a vertex and a curve containing the vertex is 
-    //- the curve. The join of two curves of a split cylinder is 
-    //- both containing surfaces.
-    //- The join of two entities in separate, unmerged volumes is null.
-    //- Returns the first element of the join_set, or NULL if set is empty.
+  //@}
   
+  //@{
+  //- like join, except returns the lower order entities common to the input 
+  //- entities
   RefEntity *meet( RefEntity* ref_entity_2, DLIList<RefEntity*> &join_set );
   static RefEntity *meet( DLIList<RefEntity*> &ref_entities, 
                           DLIList<RefEntity*> &join_set );
-    //- like join, except returns the lower order entities common to the input 
-    //- entities
+  //@}
 
+  //! the valence of this entity with respect to parent (absolute
+  //! valence if parent is null)
   int valence(RefEntity *parent = NULL);
-    //- the valence of this entity with respect to parent (absolute
-    //- valence if parent is null)
 
+  
+  //@{
+  //- Return TRUE if this is entity, or a direct child (parent) of entity.
   virtual CubitBoolean is_child(RefEntity *entity);
   virtual CubitBoolean is_parent(RefEntity *entity);
-    //- Return TRUE if this is entity, or a direct child (parent) of entity.
+  //@}
 
+  //! returns the number of parent entities of this; also useful for determining
+  //! whether an entity is free or not; returns -1 on error
   int num_parent_ref_entities();
-    //- returns the number of parent entities of this; also useful for determining
-    //- whether an entity is free or not; returns -1 on error
   
 //   void common_draw_label(int color, const int label_style);
 //     //- Common code used for drawing labels. Actually, the entire
@@ -193,85 +222,102 @@
   //CubitBoolean is_free_ref_entity();
     //- return CUBIT_TRUE if this ref entity has no non-virtual parents
 
+  //! Return the approximate (spatial) center of this RefEntity
   virtual CubitVector center_point();
-    //- Return the approximate (spatial) center of this RefEntity
   
+  //! A generic geometric extent function.
+  //! Returns volume for RefVolumes, area for RefFaces, length for RefEdge,
+  //! and 1.0 for RefVertices
+  //! A RefGroup calculates the maximum dimension of its contained
+  //! entities and returns the sum of the measures() of all entities
+  //! of that dimension.
+  //! Default return value is 0.0 for all other entities.
   virtual double measure();
-    //- A generic geometric extent function.
-    //- Returns volume for RefVolumes, area for RefFaces, length for RefEdge,
-    //- and 1.0 for RefVertices
-    //- A RefGroup calculates the maximum dimension of its contained
-    //- entities and returns the sum of the measures() of all entities
-    //- of that dimension.
-    //- Default return value is 0.0 for all other entities.
   
+  //! Returns the type of measure: (volume, area, length, or N/A)
   virtual CubitString measure_label();
-    //- Returns the type of measure: (volume, area, length, or N/A)
   
+  //! Perform checks to see if entity valid.
   virtual int validate();
-    //- Perform checks to see if entity valid.
   
+  //! Returns the dag type of this enity.
   virtual DagType dag_type() const = 0;
+
+  //! Returns the type info of this enity.
   virtual const type_info& entity_type_info() const = 0;
+
+  //! Translates the type info into dag type. 
   static DagType dag_type( const type_info& );
-    //- Return the type of the entity
-  
+ 
+  //! Gets the parent RefEntity type.
   DagType get_parent_ref_entity_type() const;
+
+  //! Gets the child RefEntity type.
   DagType get_child_ref_entity_type() const;
+
+  //! Given a child dag type, returns the parent dag type.
   static DagType get_parent_ref_entity_type( DagType child_type );
+
+  //! Given a parent dag type, returns the child dag type.
   static DagType get_child_ref_entity_type( DagType parent_type );
   
-  // send event to all observers (static and non-static) for 
-  // this entity and all children
+  //! send event to all observers (static and non-static) for 
+  //! this entity and all children
   void notify_sub_all_observers(const CubitEvent& event);
 
-  
+  //!R void
+  //!I partner
+  //!I- The merge partner for this object
+  //!I event
+  //!I- The type of event
+  //! This function takes actions depending on the type of event it
+  //! is notified of.
+  //!   COMPARISON_FOUND:
+  //!     Make temporary TDCompare objects and attach to "this" and
+  //!     the "partner" object.
   void notify(RefEntity* partner, CubitEventType event);
-    //R void
-    //I partner
-    //I- The merge partner for this object
-    //I event
-    //I- The type of event
-    //- This function takes actions depending on the type of event it
-    //- is notified of.
-    //-   COMPARISON_FOUND:
-    //-     Make temporary TDCompare objects and attach to "this" and
-    //-     the "partner" object.
   
+  //!R void
+  //!I partner
+  //!I- The compare partner for this object
+  //! This function makes the connection between the two RefEntities,
+  //! this and partner. At the end of this function the two entities
+  //! would know who they compare with.
   void add_compare_data(RefEntity* partner) ;
-    //R void
-    //I partner
-    //I- The compare partner for this object
-    //- This function makes the connection between the two RefEntities,
-    //- this and partner. At the end of this function the two entities
-    //- would know who they compare with.
   
+  //!- This function clears the compare related temporary data.
   void remove_compare_data() ;
-    //R void
-    //- This function clears the compare related temporary data.
     
+  //!R RefEntity*
+  //!R- The partner set in add_compare_data(), or NULL if none
+  //!R- has been set.
   RefEntity* get_compare_partner() ;
-    //R RefEntity*
-    //R- The partner set in add_compare_data(), or NULL if none
-    //R- has been set.
 
+  //! Premodify function called after CGM has been modified
+  virtual void geometry_premodify() { return; };
+
 //========  Change Code by RY of Cat,  5/7/99 11:08:12 AM  ========
   void get_related_entity_list(const type_info& related_entity_type,
 			       DLIList<RefEntity*>& entity_list);
   //- to parse group in <ref_entity> commands
 //========  Change End by RY of Cat,  5/7/99 11:08:12 AM  ========
 
+  //! Set the id of this RefEntity to i
   virtual void set_id(int i );
-    //- set the id of this entity to i
-  
+ 
+  //! Sets the id of this RefEntity and emits specified event static observers.
   void set_id(int i, CubitBoolean emit_event );
 
+  //! Returns the type of a class given the class name.
   static const type_info& get_entity_type_info(const char* entity_type);
-    //- Returns the type of a class given the class name.
-    
+   
+  //! Returns a dag type based on name passed in, i.e., body, volume, surface..
   static DagType dag_type( const char* cli_type_name );
+  
+  //! Sets the color of this RefEntity.
+  virtual void color(int value);
 
-  virtual void color(int value);
+  //! Gets the color of this RefEntity.
   virtual int color() const;
 
 protected :

Modified: cgm/branches/cubit/geom/RefEntityFactory.cpp
===================================================================
--- cgm/branches/cubit/geom/RefEntityFactory.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEntityFactory.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -8,6 +8,62 @@
 #include "GeometryQueryTool.hpp"
 #include "DLIList.hpp"
 
+static int sort_by_ascending_ids(CubitEntity*& a, CubitEntity*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
+static int sort_by_ascending_ids(RefVertex*& a, RefVertex*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
+static int sort_by_ascending_ids(RefVolume*& a, RefVolume*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
+static int sort_by_ascending_ids(RefEdge*& a, RefEdge*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
+static int sort_by_ascending_ids(RefFace*& a, RefFace*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
+static int sort_by_ascending_ids(Body*& a, Body*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
+static int sort_by_ascending_ids(RefGroup*& a, RefGroup*& b)
+{
+  if( a->id() < b->id() )
+    return -1;
+  else
+    return 1;
+} 
+
 RefEntityFactory *RefEntityFactory::instance_ = NULL;
 
 RefEntityFactory::RefEntityFactory(RefEntityFactory *factory) 
@@ -31,10 +87,26 @@
     refVolumeList = NULL;
     bodyList = NULL;
   }
+
+  refVertexListIsSorted = true;
+  refEdgeListIsSorted = true;
+  refFaceListIsSorted = true;
+  refVolumeListIsSorted = true;
+  bodyListIsSorted = true;
+  refGroupListIsSorted = true;
   
   reset_ids();
 }
 
+void RefEntityFactory::delete_instance()
+{
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}
+
 RefEntityFactory::~RefEntityFactory()
 {
   if (refVertexList != NULL) delete refVertexList;
@@ -163,6 +235,12 @@
 void RefEntityFactory::add(RefGroup* refGPtr)
 {
    assert(!refGroupList->is_in_list(refGPtr));
+   if(refGroupList->size() > 0)
+   {
+    refGroupList->last();
+    if(refGPtr->id() < refGroupList->get()->id())
+      refGroupListIsSorted = false;
+   }
    refGroupList->append(refGPtr);
    if (refGPtr->id() > maxRefGroupId) maxRefGroupId = refGPtr->id();
 }
@@ -170,6 +248,12 @@
 void RefEntityFactory::add(Body* bodyPtr)
 {
    assert(!bodyList->is_in_list(bodyPtr));
+   if(bodyList->size() > 0)
+   {
+    bodyList->last();
+    if(bodyPtr->id() < bodyList->get()->id())
+      bodyListIsSorted = false;
+   }
    bodyList->append(bodyPtr);
    if (bodyPtr->id() > maxBodyId) maxBodyId = bodyPtr->id();
 }
@@ -177,6 +261,12 @@
 void RefEntityFactory::add(RefVolume* refVPtr)
 {
    assert(!refVolumeList->is_in_list(refVPtr));
+   if(refVolumeList->size() > 0)
+   {
+    refVolumeList->last();
+    if(refVPtr->id() < refVolumeList->get()->id())
+      refVolumeListIsSorted = false;
+   }
    refVolumeList->append(refVPtr);
    if (refVPtr->id() > maxRefVolumeId)
        maxRefVolumeId = refVPtr->id();
@@ -185,6 +275,12 @@
 void RefEntityFactory::add(RefFace* refFPtr)
 {
    assert(!refFaceList->is_in_list(refFPtr));
+   if(refFaceList->size() > 0)
+   {
+    refFaceList->last();
+    if(refFPtr->id() < refFaceList->get()->id())
+      refFaceListIsSorted = false;
+   }
    refFaceList->append(refFPtr);
    if (refFPtr->entityId > maxRefFaceId)
        maxRefFaceId = refFPtr->entityId;
@@ -193,6 +289,12 @@
 void RefEntityFactory::add(RefEdge* refEPtr)
 {
    assert(!refEdgeList->is_in_list(refEPtr));
+   if(refEdgeList->size() > 0)
+   {
+    refEdgeList->last();
+    if(refEPtr->id() < refEdgeList->get()->id())
+      refEdgeListIsSorted = false;
+   }
    refEdgeList->append(refEPtr);
    if (refEPtr->id() > maxRefEdgeId)
        maxRefEdgeId = refEPtr->id();
@@ -201,6 +303,12 @@
 void RefEntityFactory::add(RefVertex* refVPtr)
 {
    assert(!refVertexList->is_in_list(refVPtr));
+   if(refVertexList->size() > 0)
+   {
+    refVertexList->last();
+    if(refVPtr->id() < refVertexList->get()->id())
+      refVertexListIsSorted = false;
+   }
    refVertexList->append(refVPtr);
    if (refVPtr->id() > maxRefVertexId)
        maxRefVertexId = refVPtr->id();
@@ -340,6 +448,18 @@
   ref_vertices = *refVertexList;
 }
 
+#ifdef PROE
+void RefEntityFactory::ref_parts(DLIList<RefPart*> &ref_parts)
+{
+	ref_parts = *refPartList;
+}
+
+void RefEntityFactory::ref_assemblies(DLIList<RefAssembly*> &ref_assemblies)
+{
+	ref_assemblies = *refAssemblyList;
+}
+#endif
+
 int RefEntityFactory::num_bodies() const {return bodyList->size();}
 int RefEntityFactory::num_ref_volumes() const {return refVolumeList->size();}
 int RefEntityFactory::num_ref_groups() const {return refGroupList->size();}
@@ -406,18 +526,46 @@
    if (!bodyList->size())
        return NULL;
    
-     // If the desired ID is less than the current list item's ID,
-     // it is 'probably' before current spot in list, so reset.
-   Body* body_ptr = bodyList->get();
-   if (body_ptr->id() > id)
-       bodyList->reset();
-   
-   for (int i = bodyList->size(); i--; )
+   // Make sure the list is sorted for the binary search.
+   if(!bodyListIsSorted)
    {
-      body_ptr = bodyList->get_and_step();
-      if (body_ptr->id() == id)
-          return body_ptr ;
+     bodyList->sort(sort_by_ascending_ids);
+     bodyListIsSorted = true;
    }
+
+   // Do a binary search on the sorted list.  We are making the assumption
+   // here that there are no NULL entries in the list.
+   bool found = false;
+   int left_index = 0;
+   int right_index = bodyList->size()-1;
+   int mid_index = (left_index + right_index)/2;
+   int mid_id = ((*bodyList)[mid_index])->id();
+
+   while(!found && (right_index-left_index) > 1)
+   {
+     if(mid_id == id)
+       found = true;
+     else
+     {
+       if(mid_id > id)
+         right_index = mid_index;
+       else
+         left_index = mid_index;
+       mid_index = (left_index + right_index)/2;
+       mid_id = ((*bodyList)[mid_index])->id();
+     }
+   }
+
+   if(!found)
+   {
+     if(((*bodyList)[left_index])->id() == id)
+       return ((*bodyList)[left_index]);
+     else if(((*bodyList)[right_index])->id() == id)
+       return ((*bodyList)[right_index]);
+   }
+   else
+     return ((*bodyList)[mid_index]);
+   
    return NULL ;
 }
 
@@ -426,18 +574,46 @@
    if (!refGroupList->size())
        return NULL;
    
-     // If the desired ID is less than the current list item's ID,
-     // it is 'probably' before current spot in list, so reset.
-   RefGroup* ref_group_ptr = refGroupList->get();
-   if (ref_group_ptr->id() > id)
-       refGroupList->reset();
-   
-   for (int i = refGroupList->size(); i--; )
+   // Make sure the list is sorted for the binary search.
+   if(!refGroupListIsSorted)
    {
-      ref_group_ptr = refGroupList->get_and_step();
-      if (ref_group_ptr->id() == id)
-          return ref_group_ptr ;
+     refGroupList->sort(sort_by_ascending_ids);
+     refGroupListIsSorted = true;
    }
+
+   // Do a binary search on the sorted list.  We are making the assumption
+   // here that there are no NULL entries in the list.
+   bool found = false;
+   int left_index = 0;
+   int right_index = refGroupList->size()-1;
+   int mid_index = (left_index + right_index)/2;
+   int mid_id = ((*refGroupList)[mid_index])->id();
+
+   while(!found && (right_index-left_index) > 1)
+   {
+     if(mid_id == id)
+       found = true;
+     else
+     {
+       if(mid_id > id)
+         right_index = mid_index;
+       else
+         left_index = mid_index;
+       mid_index = (left_index + right_index)/2;
+       mid_id = ((*refGroupList)[mid_index])->id();
+     }
+   }
+
+   if(!found)
+   {
+     if(((*refGroupList)[left_index])->id() == id)
+       return ((*refGroupList)[left_index]);
+     else if(((*refGroupList)[right_index])->id() == id)
+       return ((*refGroupList)[right_index]);
+   }
+   else
+     return ((*refGroupList)[mid_index]);
+
    return NULL ;
 }
 
@@ -446,18 +622,46 @@
    if (!refVolumeList->size())
        return NULL;
    
-     // If the desired ID is less than the current list item's ID,
-     // it is 'probably' before current spot in list, so reset.
-   RefVolume* ref_volume_ptr = refVolumeList->get();
-   if (ref_volume_ptr->id() > id)
-       refVolumeList->reset();
-   
-   for (int i = refVolumeList->size(); i--; )
+   // Make sure the list is sorted for the binary search.
+   if(!refVolumeListIsSorted)
    {
-      ref_volume_ptr = refVolumeList->get_and_step() ;
-      if (ref_volume_ptr->id() == id)
-          return ref_volume_ptr ;
+     refVolumeList->sort(sort_by_ascending_ids);
+     refVolumeListIsSorted = true;
    }
+
+   // Do a binary search on the sorted list.  We are making the assumption
+   // here that there are no NULL entries in the list.
+   bool found = false;
+   int left_index = 0;
+   int right_index = refVolumeList->size()-1;
+   int mid_index = (left_index + right_index)/2;
+   int mid_id = ((*refVolumeList)[mid_index])->id();
+
+   while(!found && (right_index-left_index) > 1)
+   {
+     if(mid_id == id)
+       found = true;
+     else
+     {
+       if(mid_id > id)
+         right_index = mid_index;
+       else
+         left_index = mid_index;
+       mid_index = (left_index + right_index)/2;
+       mid_id = ((*refVolumeList)[mid_index])->id();
+     }
+   }
+
+   if(!found)
+   {
+     if(((*refVolumeList)[left_index])->id() == id)
+       return ((*refVolumeList)[left_index]);
+     else if(((*refVolumeList)[right_index])->id() == id)
+       return ((*refVolumeList)[right_index]);
+   }
+   else
+     return ((*refVolumeList)[mid_index]);
+
    return NULL ;
 }
 
@@ -466,18 +670,46 @@
    if (!refFaceList->size())
        return NULL;
    
-     // If the desired ID is less than the current list item's ID,
-     // it is 'probably' before current spot in list, so reset.
-   RefFace* ref_face_ptr = refFaceList->get();
-   if (ref_face_ptr->id() > id)
-       refFaceList->reset();
-   
-   for (int i = refFaceList->size(); i--; )
+   // Make sure the list is sorted for the binary search.
+   if(!refFaceListIsSorted)
    {
-      ref_face_ptr = refFaceList->get_and_step() ;
-      if (ref_face_ptr->id() == id)
-          return ref_face_ptr ;
+     refFaceList->sort(sort_by_ascending_ids);
+     refFaceListIsSorted = true;
    }
+
+   // Do a binary search on the sorted list.  We are making the assumption
+   // here that there are no NULL entries in the list.
+   bool found = false;
+   int left_index = 0;
+   int right_index = refFaceList->size()-1;
+   int mid_index = (left_index + right_index)/2;
+   int mid_id = ((*refFaceList)[mid_index])->id();
+
+   while(!found && (right_index-left_index) > 1)
+   {
+     if(mid_id == id)
+       found = true;
+     else
+     {
+       if(mid_id > id)
+         right_index = mid_index;
+       else
+         left_index = mid_index;
+       mid_index = (left_index + right_index)/2;
+       mid_id = ((*refFaceList)[mid_index])->id();
+     }
+   }
+
+   if(!found)
+   {
+     if(((*refFaceList)[left_index])->id() == id)
+       return ((*refFaceList)[left_index]);
+     else if(((*refFaceList)[right_index])->id() == id)
+       return ((*refFaceList)[right_index]);
+   }
+   else
+     return ((*refFaceList)[mid_index]);
+
    return NULL ;
 }
 
@@ -486,18 +718,46 @@
    if (!refEdgeList->size())
        return NULL;
    
-     // If the desired ID is less than the current list item's ID,
-     // it is 'probably' before current spot in list, so reset.
-   RefEdge* ref_edge_ptr = refEdgeList->get();
-   if (ref_edge_ptr->id() > id)
-       refEdgeList->reset();
-   
-   for (int i = refEdgeList->size(); i--; )
+   // Make sure the list is sorted for the binary search.
+   if(!refEdgeListIsSorted)
    {
-      ref_edge_ptr = refEdgeList->get_and_step() ;
-      if (ref_edge_ptr->id() == id)
-          return ref_edge_ptr ;
+     refEdgeList->sort(sort_by_ascending_ids);
+     refEdgeListIsSorted = true;
    }
+
+   // Do a binary search on the sorted list.  We are making the assumption
+   // here that there are no NULL entries in the list.
+   bool found = false;
+   int left_index = 0;
+   int right_index = refEdgeList->size()-1;
+   int mid_index = (left_index + right_index)/2;
+   int mid_id = ((*refEdgeList)[mid_index])->id();
+
+   while(!found && (right_index-left_index) > 1)
+   {
+     if(mid_id == id)
+       found = true;
+     else
+     {
+       if(mid_id > id)
+         right_index = mid_index;
+       else
+         left_index = mid_index;
+       mid_index = (left_index + right_index)/2;
+       mid_id = ((*refEdgeList)[mid_index])->id();
+     }
+   }
+
+   if(!found)
+   {
+     if(((*refEdgeList)[left_index])->id() == id)
+       return ((*refEdgeList)[left_index]);
+     else if(((*refEdgeList)[right_index])->id() == id)
+       return ((*refEdgeList)[right_index]);
+   }
+   else
+     return ((*refEdgeList)[mid_index]);
+
    return NULL ;
 }
 
@@ -506,18 +766,46 @@
    if (!refVertexList->size())
        return NULL;
    
-     // If the desired ID is less than the current list item's ID,
-     // it is 'probably' before current spot in list, so reset.
-   RefVertex* ref_vertex_ptr = refVertexList->get();
-   if (ref_vertex_ptr->id() > id)
-       refVertexList->reset();
-   
-   for (int i = refVertexList->size(); i--; )
+   // Make sure the list is sorted for the binary search.
+   if(!refVertexListIsSorted)
    {
-      ref_vertex_ptr = refVertexList->get_and_step() ;
-      if (ref_vertex_ptr->id() == id)
-          return ref_vertex_ptr ;
+     refVertexList->sort(sort_by_ascending_ids);
+     refVertexListIsSorted = true;
    }
+
+   // Do a binary search on the sorted list.  We are making the assumption
+   // here that there are no NULL entries in the list.
+   bool found = false;
+   int left_index = 0;
+   int right_index = refVertexList->size()-1;
+   int mid_index = (left_index + right_index)/2;
+   int mid_id = ((*refVertexList)[mid_index])->id();
+
+   while(!found && (right_index-left_index) > 1)
+   {
+     if(mid_id == id)
+       found = true;
+     else
+     {
+       if(mid_id > id)
+         right_index = mid_index;
+       else
+         left_index = mid_index;
+       mid_index = (left_index + right_index)/2;
+       mid_id = ((*refVertexList)[mid_index])->id();
+     }
+   }
+
+   if(!found)
+   {
+     if(((*refVertexList)[left_index])->id() == id)
+       return ((*refVertexList)[left_index]);
+     else if(((*refVertexList)[right_index])->id() == id)
+       return ((*refVertexList)[right_index]);
+   }
+   else
+     return ((*refVertexList)[mid_index]);
+
    return NULL ;
 }
 
@@ -554,6 +842,18 @@
    return ++maxRefVertexId;
 }
 
+#ifdef PROE
+int RefEntityFactory::next_ref_assembly_id ()
+{
+	return ++maxRefAssemblyId;
+}
+
+int RefEntityFactory::next_ref_part_id ()
+{
+	return ++maxRefPartId;
+}
+#endif
+
 Body *RefEntityFactory::get_first_body()
 {
 	bodyList->reset(); 
@@ -792,15 +1092,6 @@
   }
 }
 
-//used to sort list below
-static int sort_by_ascending_ids(CubitEntity*& a, CubitEntity*& b)
-{
-  if( a->id() < b->id() )
-    return -1;
-  else
-    return 1;
-} 
-
 void RefEntityFactory::compress_ids(DLIList<CubitEntity*> &list)
 {
   int id = 1;
@@ -841,6 +1132,10 @@
   maxSurfSubDomainId  = 0;
   maxCurveSubDomainId = 0;
   maxRefCoordSysId    = 0;
+#ifdef PROE
+  maxRefAssemblyId    = 0;
+  maxRefPartId        = 0;
+#endif
 }
 
 #if 0
@@ -874,9 +1169,26 @@
   if (!entity) return CUBIT_FAILURE;
   
     //- handle MODEL_ENTITY_DESTRUCTED/MODEL_ENTITY_CONSTRUCTED events
-  if (observer_event.get_event_type() == MODEL_ENTITY_CONSTRUCTED) add(entity);
-  
-  else if (observer_event.get_event_type() == MODEL_ENTITY_DESTRUCTED) remove(entity);
+  int event = observer_event.get_event_type();
+  if (event == MODEL_ENTITY_CONSTRUCTED) 
+    add(entity);
+  else if (event == MODEL_ENTITY_DESTRUCTED) 
+    remove(entity);
+  else if (event == ID_SET) 
+  {
+    if(CAST_TO(entity, RefEdge))
+      refEdgeListIsSorted = false;
+    else if(CAST_TO(entity, RefFace))
+      refFaceListIsSorted = false;
+    else if(CAST_TO(entity, RefVertex))
+      refVertexListIsSorted = false;
+    else if(CAST_TO(entity, RefVolume))
+      refVolumeListIsSorted = false;
+    else if(CAST_TO(entity, RefGroup))
+      refGroupListIsSorted = false;
+    else if(CAST_TO(entity, Body))
+      bodyListIsSorted = false;
+  }
 
   return CUBIT_SUCCESS;
 }

Modified: cgm/branches/cubit/geom/RefEntityFactory.hpp
===================================================================
--- cgm/branches/cubit/geom/RefEntityFactory.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEntityFactory.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -25,7 +25,10 @@
 class RefGroup;
 class Body;
 class RefEntity;
-
+#ifdef PROE
+class RefAssembly;
+class RefPart;
+#endif
 class Point;
 class Curve;
 class Surface;
@@ -44,10 +47,11 @@
 {
 public:
 
-
   static RefEntityFactory *instance();
     //- the function used to access the singleton instance
 
+  static void delete_instance();
+
   virtual RefVertex *construct_RefVertex(Point *point = NULL);
 
   virtual RefEdge *construct_RefEdge(Curve *curve = NULL);
@@ -73,6 +77,10 @@
   virtual void ref_faces            (DLIList<RefFace*> &ref_faces);
   virtual void ref_edges            (DLIList<RefEdge*> &ref_edges);
   virtual void ref_vertices         (DLIList<RefVertex*> &ref_vertices);
+#ifdef PROE
+  virtual void ref_parts			(DLIList<RefPart*> &ref_parts);
+  virtual void ref_assemblies		(DLIList<RefAssembly*> &ref_assemblies);
+#endif
 
   virtual int num_bodies() const;
   virtual int num_ref_volumes() const;
@@ -135,6 +143,10 @@
   int next_ref_vertex_id ();
   int next_surf_sub_domain_id ();
   int next_curve_sub_domain_id();
+#ifdef PROE
+  int next_ref_assembly_id();
+  int next_ref_part_id();
+#endif
 
   int current_body_id() {return maxBodyId;};
   int current_volume_id() {return maxRefVolumeId;};
@@ -193,6 +205,10 @@
   int maxRefCoordSysId;
   int maxSurfSubDomainId;
   int maxCurveSubDomainId;
+#ifdef PROE
+  int maxRefAssemblyId;
+  int maxRefPartId;
+#endif
 
 #ifdef BOYD17 
   DLIList<RefEntity*> refEntityList;
@@ -201,12 +217,23 @@
 
 private:
 
+  bool refVertexListIsSorted;
+  bool refEdgeListIsSorted;
+  bool refFaceListIsSorted;
+  bool refVolumeListIsSorted;
+  bool bodyListIsSorted;
+  bool refGroupListIsSorted;
+
   DLIList<RefVertex*> *refVertexList;
   DLIList<RefEdge*> *refEdgeList;
   DLIList<RefFace*> *refFaceList;
   DLIList<RefGroup*> *refGroupList;
   DLIList<RefVolume*> *refVolumeList;
   DLIList<Body*> *bodyList;
+#ifdef PROE
+  DLIList<RefAssembly*> *refAssemblyList;
+  DLIList<RefPart*> *refPartList;
+#endif
 
 };
 

Modified: cgm/branches/cubit/geom/RefEntityName.cpp
===================================================================
--- cgm/branches/cubit/geom/RefEntityName.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEntityName.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -64,6 +64,8 @@
       CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME);
       attrib->has_updated(CUBIT_FALSE);
       attrib->update();
+      if( attrib->delete_attrib() )
+        entity->remove_cubit_attrib( attrib );
     }
 
     delete name_map;
@@ -73,6 +75,25 @@
 void RefEntityName::remove_refentity_name(RefEntity *entity,
                                           CubitBoolean update_attribs)
 {
+  //update the attribute so the names are put into the entity list
+  if (update_attribs)
+  {
+    CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME,
+                                                   CUBIT_FALSE);
+    if (attrib) 
+    {
+      //update the attribute so that the names are on it.
+      attrib->has_written( CUBIT_FALSE );
+      attrib->has_updated(CUBIT_FALSE);
+      attrib->update();
+
+      //remove the attribute from the underlying entity
+      //of the solid modeling kernel
+      RefEntity *attrib_owner = attrib->attrib_owner();
+      attrib_owner->remove_attrib_geometry_entity( attrib );
+    }
+  }
+
     // NOTE: There may be multiple names for one RefEntity. Make sure to 
     //       remove all of them. 
   
@@ -90,26 +111,28 @@
     nameEntityList.step();
   }
   nameEntityList.compress();
-  
+
     // now tell the entity to update its name attribute
   if (update_attribs)
   {
     CubitAttrib *attrib = entity->get_cubit_attrib(CA_ENTITY_NAME,
                                                    CUBIT_FALSE);
-    if (attrib) {
+    if (attrib) 
+    {
       attrib->has_updated(CUBIT_FALSE);
       attrib->update();
+      entity->remove_cubit_attrib( attrib );
     }
   }
 
   for (i = old_maps.size(); i > 0; i--)
     delete old_maps.get_and_step();
-  
 }
 
 CubitStatus RefEntityName::add_refentity_name(RefEntity *entity,
-				      DLIList<CubitString*> &names,
-                                              CubitBoolean update_attribs)
+                                              DLIList<CubitString*> &names,
+                                              bool update_attribs, 
+                                              bool check_name_validity)
 {
   names.reset();
   //int num_new_names = names.size();
@@ -124,13 +147,16 @@
     CubitBoolean warn_name_change = CUBIT_FALSE;
     
       // first, clean the name
-    if (clean(name))
+    if (check_name_validity)
     {
-//       PRINT_WARNING("Entity name '%s' is invalid. Changed to '%s'\n",
-//                     in_name.c_str(), name.c_str());
-      warn_name_change = CUBIT_TRUE;
+      if (clean(name))
+      {
+        // assign original name anyway, then
+        // continue on and assign modified name.
+        add_refentity_name(entity, in_name, false, false);
+        warn_name_change = CUBIT_TRUE;
+      }
     }
-    
       // now, check for valid name
     CubitBoolean name_valid = CUBIT_FALSE;
     
@@ -175,8 +201,9 @@
                           entity->class_name(), entity->id(), name.c_str());
           if(warn_name_change)
           {
-            PRINT_WARNING("Entity name '%s' is invalid. Changed to '%s'\n",
-                          in_name.c_str(), name.c_str());
+            PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
+                 "         Additional name '%s' assigned.\n",
+              in_name.c_str(), name.c_str());
           }
           
           name_valid = CUBIT_TRUE;
@@ -187,8 +214,9 @@
     {
       if(warn_name_change)
       {
-        PRINT_WARNING("Entity name '%s' is invalid. Changed to '%s'\n",
-                      in_name.c_str(), name.c_str());
+        PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
+          "         Additional name '%s' assigned.\n",
+          in_name.c_str(), name.c_str());
       }
       
         // else the name must be valid
@@ -244,8 +272,9 @@
 }
 
 CubitStatus RefEntityName::add_refentity_name(RefEntity *entity,
-				      CubitString &name,
-                                              CubitBoolean update_attribs)
+                                              CubitString &name,
+                                              bool update_attribs,
+                                              bool check_name_validity)
 {
   if (name == "")
     return CUBIT_FAILURE;
@@ -253,9 +282,15 @@
   CubitString in_name = name;
   bool warn_name_change = false;
   
-  if (clean(name))
+  if (check_name_validity)
   {
-    warn_name_change = true;
+    if (clean(name))
+    {
+      // Assign the invalid name anyway, then continue on and
+      // assign the modified name.
+      add_refentity_name(entity, in_name, false, false);
+      warn_name_change = true;
+    }
   }
   
   if (nameEntityList.move_to(name))
@@ -287,13 +322,14 @@
         {
           if (warn_name_change)
           {
-            PRINT_WARNING("Entity name '%s' is invalid. Changed to '%s'\n",
+            PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
+                 "         Additional name '%s' assigned.\n",
               in_name.c_str(), name.c_str());
           }
           if ( DEBUG_FLAG(92) )
             PRINT_WARNING("\t%s %d name changed to '%s'\n",
             entity->class_name(), entity->id(), name.c_str());
-          return add_refentity_name(entity, name);
+          return add_refentity_name(entity, name, update_attribs, false);
         }
       }
       return CUBIT_FAILURE;
@@ -302,7 +338,8 @@
 
   if (warn_name_change)
   {
-    PRINT_WARNING("Entity name '%s' is invalid. Changed to '%s'\n",
+    PRINT_WARNING("Entity name '%s' can't be used in commands.\n"
+      "         Additional name '%s' assigned.\n",
       in_name.c_str(), name.c_str());
   }
 
@@ -519,8 +556,8 @@
 
 CubitStatus RefEntityName::clean(CubitString &raw_name)
 {
-
-  if (raw_name == "") return CUBIT_FAILURE;
+  if (raw_name == "")
+    return CUBIT_FAILURE;
   
     // A valid name consists of alphanumeric characters plus '.', '_', '-', or '@'
   CubitStatus found_invalid_character = CUBIT_FAILURE;
@@ -828,7 +865,7 @@
     for( int i = source_list.size(); i > 0; i-- )
       get_refentity_name( source_list.get_and_step(), name_list );
     name_list.reset();
-    add_refentity_name( target, name_list, update_attribs );
+    add_refentity_name(target, name_list, update_attribs, false);
   }
 }
 

Modified: cgm/branches/cubit/geom/RefEntityName.hpp
===================================================================
--- cgm/branches/cubit/geom/RefEntityName.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefEntityName.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -33,6 +33,8 @@
   static RefEntityName *instance();
   ~RefEntityName();
 
+  static void delete_instance() { if(instance_) delete instance_; }
+
   void       remove_refentity_name(const CubitString &name,
                                    CubitBoolean update_attribs = CUBIT_TRUE);
   //- Remove the this name from the map. All other names for this
@@ -44,7 +46,8 @@
 
   CubitStatus add_refentity_name(RefEntity *entity,
                                  CubitString &name,
-                                 CubitBoolean update_attribs = CUBIT_TRUE);
+                                 bool update_attribs = true,
+                                 bool check_name_validity = true);
   //- Add the map between this RefEntity and the name.
   //- If 'name' is invalid or duplicate, it is changed and
   //- new name is returned.
@@ -52,7 +55,8 @@
 
   CubitStatus add_refentity_name(RefEntity *entity,
                                  DLIList<CubitString*> &names,
-                                 CubitBoolean update_attribs = CUBIT_TRUE);
+                                 bool update_attribs = true,
+                                 bool check_name_validity = true);
     //- add multiple names to the name map for this entity
   
   int        get_refentity_name(const RefEntity *entity,

Modified: cgm/branches/cubit/geom/RefFace.cpp
===================================================================
--- cgm/branches/cubit/geom/RefFace.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefFace.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -112,436 +112,112 @@
   remove_from_observers();	
 }
 
-double RefFace::get_crack_length()
-{          
-  double length = 0.0;
-  if( is_parametric() )
+
+static void dist_between(RefEdge* edge1, RefEdge* edge2, CubitVector& v1, CubitVector& v2, double& dist)
+{
+  // check compatibility first
+  DLIList<TopologyEntity*> entity_list(2);
+  DLIList<TopologyBridge*> bridge_list(2);
+  entity_list.append(edge1);
+  entity_list.append(edge2);
+  GeometryQueryEngine* gqe = GeometryQueryTool::instance()->common_query_engine( entity_list, bridge_list );
+  if(gqe)
   {
-    double u_period_val, v_period_val;
-//These just give the total period for the surface, I'm assuming that
-//it will usually be 2PI
-    double lower, upper;
-    CubitBoolean u_period = is_periodic_in_U( u_period_val );
-    CubitBoolean v_period = is_periodic_in_V( v_period_val );
-      //The Booleans tell us if (duh) it's periodic in that direction
-    if( ( u_period ) && ( v_period ) )//Uh-oh, periodic in both
-//directions, now we have to do some magic to find out the crack
-//length.
-    {
-        // find whether loops differ more in u or v direction.
-        // the direction that they differ the most in is the direction
-        // that we will step along to determine crack length.
-      int m;
-      double lowerv[2], upperv[2], loweru[2], upperu[2];
-        //the eight variables above keep track of the lowest and
-        //highest u- and v-parameter values for both boundaries of the
-        //surface
-      
-      lowerv[0] = lowerv[1] = CUBIT_DBL_MAX;
-      upperv[0] = upperv[1] = CUBIT_DBL_MAX;
-      loweru[0] = loweru[1] = CUBIT_DBL_MAX;
-      upperu[0] = upperu[1] = CUBIT_DBL_MAX;
-      DLIList<Loop*> loops;
-      this->loops( loops );
-        // should be exactly 2 loops
-      for( m = 0; m < loops.size() && m < 2; m++ )
-      {
-        int n;
-        Loop* func_loop = loops.get_and_step();
-        DLIList<RefEdge*> edges;
-        func_loop->ordered_ref_edges( edges );
-        for( n = edges.size(); n > 0; n-- )
-        {
-            // sample edges at 8 locations to approximate maximum and minimum
-            // parameter extents of the line
-          RefEdge* func_edge = edges.get_and_step();
-          const int num_segments = 8;
-          CubitVector location[num_segments];
-          int i;
-          for ( i = num_segments; i--; )
-          {
-            func_edge->position_from_fraction( ((double) i) / ((double) num_segments),
-                                               location[i] );
-            
-          }
-          CubitVector* closest_location = NULL;
-          double temp_u, temp_v;
+    GeometryQueryTool::instance()->entity_entity_distance(edge1, edge2, v1, v2, dist);
+  }
+}
 
-          for ( i = num_segments; i--; )
-          {
-              //now we fill temp_u and temp_v with the u and v values
-              //of the closest point on the surface to the location[i]
-              //vector--Note--the closest-point should be right where
-              //the vector is, since that's where we got the vector
-              //from
-            this->u_v_from_position( location[i], temp_u, temp_v, closest_location );
-            if( upperv[m] == CUBIT_DBL_MAX )
-               upperv[m] = temp_v;
-            if( lowerv[m] == CUBIT_DBL_MAX )
-               lowerv[m] = temp_v;
-            
-            if( temp_v > upperv[m] )
-               upperv[m] = temp_v;
-            if( temp_v < lowerv[m] )
-               lowerv[m] = temp_v;
-            
-            if( upperu[m] == CUBIT_DBL_MAX )
-               upperu[m] = temp_u;
-            if( loweru[m] == CUBIT_DBL_MAX )
-               loweru[m] = temp_u;
-            
-            if( temp_u > upperu[m] )
-               upperu[m] = temp_u;
-            if( temp_u < loweru[m] )
-               loweru[m] = temp_u;
-          }
-        }
-      }
-      if(DEBUG_FLAG(99))
-      {
-        int debug_int;
-        
-        for(debug_int = 0; debug_int <2; debug_int ++)
-        {
-          PRINT_INFO("Loweru[%d] = %f Upperu[%d] = %f\n",
-                     debug_int,loweru[debug_int],debug_int,upperu[debug_int]);
-        }
-        
-        for(debug_int = 0; debug_int <2; debug_int ++)
-        {
-          PRINT_INFO("Lowerv[%d] = %f Upperv[%d] = %f\n",
-                     debug_int,lowerv[debug_int],debug_int,upperv[debug_int]);
-        }
-      }
- 
-//Okay, we look at our u-params.  The upperu of one loop should be
-//lower than the loweru of the other loop.  If they cross, then we're
-//most likely looking at the direction parallel to the loop, and the
-//lower[1] and lower[0] values are probably very close to each other
-      double u_start, u_end, v_start, v_end;
-      u_start = u_end = v_start = v_end = 0.;
-//u_diff is the gap between the loops.
-        //u_start is the midpoint of the lower loop's u_space
-        //u_end is the midpoint of the upper loop's u_space
-      double u_diff = 0.;
-                  
-      if ( upperu[1] < loweru[0] )
-      {
-        u_diff = loweru[0] - upperu[1];
-        u_start = (loweru[1] + upperu[1]) / 2.;
-        u_end   = (loweru[0] + upperu[0]) / 2.;
-      }
-      else if ( upperu[0] < loweru[1] )
-      {
-        u_diff = loweru[1] - upperu[0];
-        u_start = (loweru[0] + upperu[0]) / 2.;
-        u_end   = (loweru[1] + upperu[1]) / 2.;
-      }
+double RefFace::get_crack_length()
+{
+  // find two loops to check the shortest distance between as that's where Cubit is most
+  // likely to crack surfaces
 
-        //Okay, we have u_start and u_end.  We have to decide how to
-        //get from one to the other.  This comes up because u_start
-        //might be smaller than u_end, but the trimmed surface might
-        //not exist in between.  If this is the case, then we need to
-        //go around the other way to get to u_end
-      double low_u, mid_u, high_u;
-      double low_v, mid_v, high_v;
-      
-      mid_u = (u_start + u_end )/2.0;
-      
-      get_param_range_V( low_v, high_v );
-      PRINT_DEBUG_99("low_v = %f high_v = %f\n",low_v, high_v);
-      PRINT_DEBUG_99("u_start = %f u_end = %f\n",u_start, u_end);
-      mid_v = (low_v + high_v) / 2.;
-      double delta_u = fabs(u_end - u_start);
-            
-      switch(point_containment(mid_u, mid_v))
-      {
-        case CUBIT_PNT_OUTSIDE:
-           PRINT_DEBUG_99("Point outside\n");
-           delta_u = -(u_period_val - delta_u);
-           break;
-        case CUBIT_PNT_INSIDE:
-           PRINT_DEBUG_99("Point inside\n");
-           break;
-        case CUBIT_PNT_BOUNDARY:
-           PRINT_DEBUG_99("Point on boundary\n");
-           break;
-        case CUBIT_PNT_UNKNOWN:
-        default:
-           PRINT_DEBUG_99("Point Unknown\n");
-           break;
-      }
-      
-      delta_u = delta_u / 10.;
-         
+  DLIList<Loop*> crack_loops;
 
-      double v_diff = 0.;
-      if ( upperv[1] < lowerv[0] )
-      {
-        v_diff = lowerv[0] - upperv[1];
-        v_start = (lowerv[1] + upperv[1]) / 2.;
-        v_end   = (lowerv[0] + upperv[0]) / 2.;
-      }
-      
-      else if ( upperv[0] < lowerv[1] )
-      {
-        v_diff = lowerv[1] - upperv[0];
-        v_start = (lowerv[0] + upperv[0]) / 2.;
-        v_end   = (lowerv[1] + upperv[1]) / 2.;
-      }
+  DLIList<Loop*> loops;
+  this->loops(loops);
 
-      mid_v = (v_start + v_end )/2.0;
-      
-      get_param_range_U( low_u, high_u );
-      PRINT_DEBUG_99("low_u = %f high_u = %f\n",low_u, high_u);
-      PRINT_DEBUG_99("v_start = %f v_end = %f\n",v_start, v_end);
-      mid_u = (low_u + high_u) / 2.;
-      double delta_v = fabs(v_end - v_start);
-            
-      switch(point_containment(mid_u, mid_v))
-      {
-        case CUBIT_PNT_OUTSIDE:
-           PRINT_DEBUG_99("Point outside\n");
-           delta_v = -(v_period_val - delta_v);
-           break;
-        case CUBIT_PNT_INSIDE:
-           PRINT_DEBUG_99("Point inside\n");
-           break;
-        case CUBIT_PNT_BOUNDARY:
-           PRINT_DEBUG_99("Point on boundary\n");
-           break;
-        case CUBIT_PNT_UNKNOWN:
-        default:
-           PRINT_DEBUG_99("Point Unknown\n");
-           break;
-      }
-      delta_v = delta_v / 10.;
-      
-        //Okay, by now we have the delta_u and delta_v values.
-        //Theoretically they are the distance between the two
-        //parameters' midpoints, divided by 10
+  int i, j;
+  for(i=0; i<loops.size(); i++)
+  {
+    Loop* l = loops.get_and_step();
+    LoopType loop_type = l->loop_type();
+    if(loop_type == LOOP_TYPE_U_PERIODIC || loop_type == LOOP_TYPE_V_PERIODIC)
+      crack_loops.append(l);
+  }
 
-        //u_diff and v_diff are the gap between the lowest point on
-        //the high one and the highest point on the low loop, they
-        //will always be positive or zero
+  if(crack_loops.size() >= 2)
+  {
+    Loop* loop1 = crack_loops.get_and_step();
+    Loop* loop2 = crack_loops.get_and_step();
 
-        //Note, if a loop is a complete circle, then the parameter
-        //value going around that way will yield a delta_? and ?_diff
-        //of zero
-      int i;
-      CubitVector start1, end1;
-      CubitVector start2, end2;
-      double length1 = 0, length2 = 0;
-      PRINT_DEBUG_99("delta_v %e, delta_u %e\n",delta_v, delta_u); //zzyk
-      PRINT_DEBUG_99("v_diff %e, u_diff %e\n",v_diff, u_diff); //zzyk
+    DLIList<RefEdge*> loop1_edges;
+    loop1->ref_edges(loop1_edges);
+    DLIList<RefEdge*> loop2_edges;
+    loop2->ref_edges(loop2_edges);
 
-        //We want to get the longest crack length in the surface, so
-        //if v_diff is smaller than u_diff, we'll step around the
-        //u_direction, and vice versa
-      if( v_diff < u_diff )
-      { 
-        get_param_range_V( low_v, high_v );
-        PRINT_DEBUG_99("low_v = %f high_v = %f\n",low_v, high_v);
-        PRINT_DEBUG_99("u_start = %f u_end = %f\n",u_start, u_end);
-        mid_v = (low_v + high_v) / 2.;
+    CubitVector p1, p2;
+    double min_dist = -1.0;
 
-        for( i = 0; i < 10; i++ )
-        {
-          start1 = this->position_from_u_v( (u_start+(delta_u*i)), low_v );
-          end1 = this->position_from_u_v( (u_start+(delta_u*(i+1))), low_v );
-          if(DEBUG_FLAG(99))
-          {
-            GfxDebug::draw_vector(start1,end1, CUBIT_RED);
-            GfxDebug::flush();
-            PRINT_INFO("At position %f in u\n",u_start + (delta_u*i));
-          }
-          length1 += start1.distance_between( end1 );
-        }
-        for( i = 0; i < 10; i++ )
-        {
-          start2 = this->position_from_u_v( (u_start+(delta_u*i)), mid_v );
-          end2 = this->position_from_u_v( (u_start+(delta_u*(i+1))), mid_v );
-          if(DEBUG_FLAG(99))
-          {
-            GfxDebug::draw_vector(start2,end2, CUBIT_BLUE);
-            GfxDebug::flush();
-            PRINT_INFO("At position %f in u\n",u_start + (delta_u*i));
-          }
-          length2 += start2.distance_between( end2 );
-        }
-      }
-      else //u_diff is less than v_diff
+    for(i=0; i<loop1_edges.size(); i++)
+    {
+      RefEdge* edge1 = loop1_edges.get_and_step();
+      for(j=0; j<loop2_edges.size(); j++)
       {
-        get_param_range_U( low_u, high_u );
-        PRINT_DEBUG_99("low_u = %f high_u = %f\n",low_u, high_u);
-        PRINT_DEBUG_99("v_start = %f v_end = %f\n",v_start, v_end);
-          //Remember, v_start is halfway between the low and high
-          //points of the lower loop, v_end is halfway between the low
-          //and high points of the upper loop
-        mid_u = (low_u + high_u) / 2.;
-        mid_v = (v_start + v_end )/2.0;
-          //Now we step aroung the loop of edges in ten places, and
-          //add up the chord lengths of those 10 chords to get our
-          //crack length.  We do it twice and average just to make
-          //sure everything is kosher.
-        for( i = 0; i < 10; i++ )
+        RefEdge* edge2 = loop2_edges.get_and_step();
+        if(edge2 != edge1)
         {
-          start1 = this->position_from_u_v( low_u, (v_start+(delta_v*i)) );
-          end1 = this->position_from_u_v( low_u, (v_start+(delta_v*(i+1))) );
-          if(DEBUG_FLAG(99))
+          CubitVector v1, v2;
+          double dist = -1;
+          dist_between(edge1, edge2, v1, v2, dist);
+          if(min_dist < 0 || (dist < min_dist && dist > 0))
           {
-            GfxDebug::draw_vector(start1,end1, CUBIT_RED);
-            GfxDebug::flush();
-            PRINT_INFO("At position %f in v\n",v_start + (delta_v*i));
+            min_dist = dist;
+            p1 = v1;
+            p2 = v2;
           }
-          length1 += start1.distance_between( end1 );
         }
-        for( i = 0; i < 10; i++ )
-        {
-          start2 = this->position_from_u_v( mid_u, (v_start+(delta_v*i)) );
-          end2 = this->position_from_u_v( mid_u, (v_start+(delta_v*(i+1))) );
-          if(DEBUG_FLAG(99))
-          {
-            GfxDebug::draw_vector(start2,end2, CUBIT_BLUE);
-            GfxDebug::flush();
-            PRINT_INFO("At position %f in v\n",v_start + (delta_v*i));
-          }
-          length2 += start2.distance_between( end2 );
-        }
       }
-      
-      length = ( (length1 + length2) / 2.0 );
     }
-    else if( v_period )
+
+    // estimate distance along the surface in case of curvature
+    if(min_dist > 0)
     {
-      int i;
-      get_param_range_U( lower, upper );
-      double low_v, high_v, mid_v;
-      get_param_range_V( low_v, high_v );
-      mid_v = (low_v + high_v) / 2.;
-      double delta = ( ( upper - lower ) / 10.0 );
-      CubitVector start, end;
-      for( i = 0; i < 10; i++ )
+      double new_min_dist = 0;
+      double start_uv[2];
+      double end_uv[2];
+      this->u_v_from_position(p1, start_uv[0], start_uv[1]);
+      this->u_v_from_position(p2, end_uv[0], end_uv[1]);
+      double delta_uv[2];
+      delta_uv[0] = (end_uv[0] - start_uv[0]) / 10.0;
+      delta_uv[1] = (end_uv[1] - start_uv[1]) / 10.0;
+
+      CubitVector start = p1;
+      CubitVector next;
+      for(i=0; i<10; i++)
       {
-        start = this->position_from_u_v( (lower+(delta*i)), mid_v );
-        end = this->position_from_u_v( (lower+(delta*(i+1))), mid_v );
-      //  GfxDebug::draw_vector(start, end, CUBIT_RED);
-      //  GfxDebug::flush();
-        length += start.distance_between( end );
+        start_uv[0] += delta_uv[0];
+        start_uv[1] += delta_uv[1];
+        next = this->position_from_u_v( start_uv[0], start_uv[1] );
+        new_min_dist += start.distance_between(next);
+        start = next;
       }
+      min_dist = new_min_dist;
     }
-    else if( u_period )
+
+    if(min_dist < 0)
     {
-      int i;
-      get_param_range_V( lower, upper );
-      double low_u, high_u, mid_u;
-      get_param_range_U( low_u, high_u );
-      mid_u = (low_u + high_u) / 2.;
-      double delta = ( ( upper - lower ) / 10.0 );
-      CubitVector start, end;
-      for( i = 0; i < 10; i++ )
-      {
-        start = this->position_from_u_v( mid_u, (lower+(delta*i)) );
-        end = this->position_from_u_v( mid_u, (lower+(delta*(i+1))) );
-        length += start.distance_between( end );
-      }
+      min_dist = 0;
     }
-    else
-    {
-      PRINT_WARNING( "Surface %d is_periodic, but has neither a "
-                     "u_period or v_period.\n", id() );
-    }
-  }
-  if ( length == 0.0 )
-  {
-    PRINT_DEBUG_99("Crack length from uv was zero. Trying geometric method.\n");
-    //This basically means that this function failed.  Lets try another
-    //method that may be less generic but will work for map/submap type 
-    //surfaces where getting this crack length is more important.
-    length = find_crack_length_no_uv();
 
+    PRINT_DEBUG_99("Crack_length is %f\n", min_dist);
+    return min_dist;
   }
-  PRINT_DEBUG_99("Crack_length is %f\n",length);
-  return length;
-}
-double RefFace::find_crack_length_no_uv()
-{
-  double length = 0.0;
-  //assume that this surface has exactly 2 loops, again this is for
-  //map/submap.  This function also assumes the surface is periodic.
-  //ie, this basically assumes some sort of cylinder wall, torus wall or
-  //something that looks like that.
-  if ( this->num_loops() != 2 || !this->is_periodic() )
-    return length;
 
-  //Pick a point on one of the loops, find the closest point to that on the other
-  //loops.  Then find the closest point to that point on the first loop.  Keep iterating
-  //till we have the two closest points between the loops (may not be closest, but they
-  //are mutually the closest to each other.).
-  DLIList<Loop*> loops;
-  this->loops(loops);
-  Loop *first_loop = loops.get();
-  Loop *other_loop = loops.next();
-  RefEdge *tmp_edge = first_loop->co_edge()->get_ref_edge_ptr();
-  CubitVector this_point, closest_point;
-   // use the mid point of the first curve as the start point.
-  if ( tmp_edge->mid_point(this_point) != CUBIT_SUCCESS )
-    return length;
-  CoEdge *other_co_edge = NULL;
-  GeometryUtil *gu = GeometryUtil::instance();
-  CoEdge *closest_co_edge = gu->closest_loop_coedge(other_loop, this_point,
-                                                 other_co_edge, &closest_point);
-  if ( closest_co_edge == NULL )
-    return length;
-  CubitVector this_closest;
-  int counter = 0;
-  const int MAX_LOOP_ITR = 6;
-  for(;;)
-  {
-    if ( counter >= MAX_LOOP_ITR )
-      break;
-    counter++;
-    //find a new this_closest from closest_point.
-    closest_co_edge = gu->closest_loop_coedge(first_loop, closest_point,
-                                           other_co_edge, &this_closest);
-    if ( closest_co_edge == NULL )
-      return length;
-    if ( (this_point-this_closest).length_squared() <= GEOMETRY_RESABS*GEOMETRY_RESABS )
-      break;
-    //make this_closest our point.
-    this_point = this_closest;
-    //get a new closest_point.
-    closest_co_edge = gu->closest_loop_coedge(other_loop, this_point,
-                                           other_co_edge, &closest_point);
-    if ( closest_co_edge == NULL )
-      return length;
-  }
-  //if we are here we succeeded.  Our points are, this_point and closest_point.
-  //Now, find some linear steps between these points, move them to the surface,
-  //and calculate the length.
-  int num_steps = 10;
-  //Find the num_steps positions by treating this_point and closest_point as the
-  //end points of a curve and parameterizing it...
-  int ii;
-  double param_step = 1/(double)num_steps;
-  double curr_param = param_step;
-  CubitVector start_point = this_point;
-  CubitVector next_point;
-  CubitVector diff_vec = closest_point - this_point;
-  for ( ii = 0; ii < num_steps; ii++ )
-  {
-    next_point = this_point + curr_param*(diff_vec);
-    this->move_to_surface(next_point);
-    length += (next_point-start_point).length();
-    start_point = next_point;
-    curr_param += param_step;
-  }
-  PRINT_INFO("Crack length (no u-v) is = %f\n", length);
-
-  return length;
+  PRINT_DEBUG_99("No valid crack length for surface %i\n", this->id());
+  return 0.0;
 }
 
-
 CubitVector RefFace::normal_at ( const CubitVector& location, 
                                  RefVolume* volume, 
                                  double* u_guess, double* v_guess)
@@ -579,7 +255,7 @@
                   location.x(), location.y(), location.z(),
                   this->entity_name().c_str(),
                   this->id());
-      assert ( result == CUBIT_SUCCESS );
+      //assert ( result == CUBIT_SUCCESS );
       return CubitVector(0.0, 0.0, 0.0);
    }
    
@@ -693,7 +369,6 @@
        
    if ( ref_volume_ptr ) {
       CubitSense s = sense( ref_volume_ptr );
-      assert( s == CUBIT_FORWARD || s == CUBIT_REVERSED );
       if (  s == CUBIT_REVERSED ) {
          curvature1 = -curvature1;
          curvature2 = -curvature2;
@@ -943,8 +618,11 @@
         return CUBIT_FALSE;
      }
    }
-
-   if ( test_internal != 0 )
+    
+   //if both lists of edges are zero, this is the concentric sphere or torus case.
+   //must look for a point on the surface then.
+   if ( (ref_edge_list_1.size() == 0 && ref_edge_list_2.size() == 0 ) ||
+         test_internal != 0 )
    {
        //test a point in the middle.
      CubitVector center_1, center_2;
@@ -1442,7 +1120,10 @@
 //-------------------------------------------------------------------------
 Surface* RefFace::get_surface_ptr() 
 {
-  return CAST_TO(get_geometry_entity_ptr(), Surface);
+  // Just do one cast instead of two -- KGM
+  TopologyBridge* bridge = bridge_manager()->topology_bridge();
+  return CAST_TO(bridge, Surface);
+  //return CAST_TO(get_geometry_entity_ptr(), Surface);
 }
 
 const Surface* RefFace::get_surface_ptr() const
@@ -1484,6 +1165,40 @@
    }
 }
 
+
+//-------------------------------------------------------------------------
+// Purpose       : This function returns CUBIT_TRUE if the underlying 
+//                 geometry of the face is cylindrical. CUBIT_FALSE otherwise.
+//
+// Special Notes :
+//
+// Creator       : KGM
+//
+// Creation Date : 03/22/07
+//-------------------------------------------------------------------------
+CubitBoolean RefFace::is_cylindrical() 
+{
+     // Cast the generic GeometryEntity pointer to Surface pointer
+   Surface* surfacePtr = this->get_surface_ptr() ;
+   
+     // Check if we have a valid Surface. If so, return the result of
+     // querying the Surface if it is planar.
+   if ( surfacePtr != NULL )
+   {
+      GeometryType geo_type;
+      geo_type = surfacePtr->is_cylindrical();
+      return geo_type == CYLINDER_SURFACE_TYPE ? CUBIT_TRUE : CUBIT_FALSE;
+   }
+   else
+   {
+      PRINT_WARNING("In RefFace::is_cylindrical\n"
+                    "         %s (surface %d) is not associated with a valid\n"
+                    "         underlying geoemtric Surface\n",
+                    entity_name().c_str(), id()) ;
+      return CUBIT_FALSE ;
+   }
+}
+
 CubitStatus RefFace::get_point_normal( CubitVector& origin, CubitVector& normal )
 {
    if( is_planar() == CUBIT_FALSE)
@@ -1626,7 +1341,6 @@
                                    double distance_tolerance,
                                    double longest_edge )
 {
-  int junk1, junk2, junk3;
   Surface* surf_ptr = get_surface_ptr();
   if (!surf_ptr)
   {
@@ -1635,7 +1349,7 @@
   }
   
   return surf_ptr->get_geometry_query_engine()->
-    get_graphics(surf_ptr, junk1, junk2, junk3, &facets, 
+    get_graphics(surf_ptr, &facets, 
       normal_tolerance, distance_tolerance, longest_edge );
 }
 

Modified: cgm/branches/cubit/geom/RefFace.hpp
===================================================================
--- cgm/branches/cubit/geom/RefFace.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefFace.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -450,6 +450,13 @@
     //R CUBIT_TRUE/CUBIT_FALSE
     //- This function returns CUBIT_TRUE if the underlying geometry
     //- of the face is planar. CUBIT_FALSE otherwise.
+  
+  CubitBoolean is_cylindrical();
+    //R CubitBoolean
+    //R CUBIT_TRUE/CUBIT_FALSE
+    //- This function returns CUBIT_TRUE if the underlying geometry
+    //- of the face is conical (cylinders are subsets of cones). 
+    //- CUBIT_FALSE otherwise.
 
   CubitStatus get_point_normal( CubitVector& origin, CubitVector& normal );
     //- Only valid for planar surfaces
@@ -516,10 +523,6 @@
 #endif
   int hardPointColor;
 
-  double find_crack_length_no_uv();
-  //- returns the crack length of the periodic surface (which can only have
-  //- two loops, if there is some problem with the uv space.
-     
 };
 #endif
 

Modified: cgm/branches/cubit/geom/RefGroup.cpp
===================================================================
--- cgm/branches/cubit/geom/RefGroup.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefGroup.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -138,11 +138,7 @@
 
 void RefGroup::get_child_entities(DLIList<CubitEntity*>& cub_entity_list)
 {
-  entityList.reset();
-  DLIList<CubitEntity*> temp_list;
-  CAST_LIST_TO_PARENT( entityList, temp_list );
-  cub_entity_list.merge_unique(temp_list, CUBIT_TRUE);
-//  cub_entity_list.merge_unique(entityList, CUBIT_TRUE);
+  cub_entity_list.casting_merge_unique(entityList, CUBIT_TRUE);
 }
 
 void RefGroup::expand_group( DLIList<RefEntity*> & entity_list )

Modified: cgm/branches/cubit/geom/RefVertex.cpp
===================================================================
--- cgm/branches/cubit/geom/RefVertex.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefVertex.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -179,6 +179,10 @@
   int i;
   for (i = temp_list.size(); i > 0; i--) {
     RefEdge *common_edge = CAST_TO(temp_list.get(), RefEdge);
+
+    if( NULL == common_edge )
+      continue;
+
       //This extra 'if' block is needed in case other_vertex == this
     if ( ( common_edge->start_vertex() == other_vertex &&
            common_edge->end_vertex() == this) ||
@@ -187,6 +191,8 @@
     {
       if (common_edge && (!owning_face || common_edge->is_child(owning_face)))
         return common_edge;
+      else
+        temp_list.step();
     }
     else
       temp_list.step();

Modified: cgm/branches/cubit/geom/RefVolume.cpp
===================================================================
--- cgm/branches/cubit/geom/RefVolume.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefVolume.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -173,6 +173,26 @@
   }
 }
 
+CubitStatus RefVolume::mass_properties( CubitVector  principal_axes[3], 
+                                        CubitVector &principal_moments, 
+                                        CubitVector &centroid, 
+                                        double &volume )
+{
+  DLIList<Body*> bodies;
+  this->bodies( bodies );
+  if( bodies.get()->is_sheet_body() )
+  {
+    centroid.set(0,0,0);
+    volume = 0;
+    return CUBIT_SUCCESS;
+  }
+  else
+  {
+    Lump *lump = get_lump_ptr();
+    return lump->mass_properties( principal_axes, principal_moments, centroid, volume );
+  }
+}
+
 CubitString RefVolume::measure_label()
 {
   return "volume";
@@ -367,3 +387,28 @@
   return CUBIT_TRUE;
 }
   
+int RefVolume::validate()
+{
+     //- This function determines whether the entity is valid.
+     //- Several types of checks can be done, 
+   int error = 0;
+
+     // Perform general RefEntity checks (measure > 0)
+   error += RefEntity::validate();
+
+     // Pass through to surface and add in its validation
+   Lump *lump = this->get_lump_ptr();
+
+     // check surface ptr
+   if (lump != NULL) {
+        // Check underlying surface
+	   DLIList <TopologyEntity*> bad_entities;
+      error += lump->validate(entity_name(), bad_entities);
+   } else {
+      PRINT_WARNING("\tWARNING: Null underlying volume for %s, (%s %d)\n",
+                    entity_name().c_str(), class_name(), id());
+      error++;
+   }
+   return error;
+}
+

Modified: cgm/branches/cubit/geom/RefVolume.hpp
===================================================================
--- cgm/branches/cubit/geom/RefVolume.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/RefVolume.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -47,6 +47,7 @@
 
 // ********** END FORWARD DECLARATIONS     **********
 
+//! RefVolume class.
 class CUBIT_GEOM_EXPORT RefVolume : public BasicTopologyEntity
 {
 public :
@@ -60,70 +61,89 @@
     //- The destructor
 
     /* topology */
-    
+
+  //! Gets the dag type.
   DagType dag_type() const { return DagType::ref_volume_type(); }  
+
+  //! Gets the type info of this RefVolume.
   const type_info& entity_type_info() const { return typeid(RefVolume); }
 
+  //! Gets the class name for a volume: "Volume".
   static const char* get_class_name()
-     {
-       return "Volume";
-     }
+  {
+    return "Volume";
+  }
 
+  //! Gets the class name for a volume: "Volume".
   virtual const char* class_name() const
-     {
-       return get_class_name();
-     }
+  {
+    return get_class_name();
+  }
   
+  //! Gets the lump pointer.
   Lump* get_lump_ptr() ;
+
+  //!R Lump*
+  //!R- A pointer to the Lump to which the current 
+  //!R- volume  points. 
+  //! This function returns a pointer to the Lump
+  //! to which the current volume points.
   Lump const* get_lump_ptr() const ;
-    //R Lump*
-    //R- A pointer to the Lump to which the current 
-    //R- volume  points. 
-    //- This function returns a pointer to the Lump
-    //- to which the current volume points.
 
+  //! Gets the owning Body of this RefVolume.
   Body* get_body_ptr() ;
 
+  //! Return the number of connected components bounding this volume.
+  //! Note: this counts the number of ref_edge-connected ref_face 
+  //! components, which may not be the same as the number of acis shells.
   int num_boundary_components();
-    //- Return the number of connected components bounding this volume.
-    //- Note: this counts the number of ref_edge-connected ref_face 
-    //- components, which may not be the same as the number of acis shells.
 
+  //!R CubitBoolean
+  //!R-CUBIT_TRUE/CUBIT_FALSE
+  //!I RefVolume*
+  //!O CubitBoolean
+  //!O- If the two RefVolumes are spatially equal within the GEOMETRY_RESABS*
+  //! the tolerance_factor, then CUBIT_TRUE will be returned.  Otherwise
+  //! CUBIT_FALSE is returned.
+  //! The comparison is done by checking the bounding boxes of the
+  //! RefVolumes.
   CubitBoolean about_spatially_equal ( RefVolume* ref_vol_ptr_2,
                                        double tolerance_factor);
-     //R CubitBoolean
-    //R-CUBIT_TRUE/CUBIT_FALSE
-    //I RefVolume*
-    //O CubitBoolean
-    //O- If the two RefVolumes are spatially equal within the GEOMETRY_RESABS*
-    //- the tolerance_factor, then CUBIT_TRUE will be returned.  Otherwise
-    //- CUBIT_FALSE is returned.
-    //- The comparison is done by checking the bounding boxes of the
-    //- RefVolumes.
 
+  //! returns the genus of the volume, where
+  //! g = 1 - .5(v - e + f - gs), and v,e,f = # vertices, edges, faces,
+  //! and gs = summed genus of surfaces
   int genus();
-    //- returns the genus of the volume, where
-    //- g = 1 - .5(v - e + f - gs), and v,e,f = # vertices, edges, faces,
-    //- and gs = summed genus of surfaces
 
     /* geometry */
 
+  //! Returns centroid of the RefVolume
   virtual CubitVector center_point();
-    //- Returns centroid of the RefVolume
   
+  //! Returns true if all Shells of RefVolume are sheets.
   CubitBoolean is_sheet();
-    //- Returns true if all Shells of RefVolume are sheets.
   
 //**********Graphics Related Functions**********//
+
+  //! returns dimension of the actual entity. 
   virtual int dimension() const; 
-    //- returns dimension of the actual entity. 
 
     /* other functions */
 
   virtual CubitString measure_label();
 
+  //@{
+  //! Get the mass properties from the underlying lump
   CubitStatus mass_properties( CubitVector &centroid, double &volume );
+  CubitStatus mass_properties( CubitVector principal_axes[3], 
+                               CubitVector &principal_moments, 
+                               CubitVector &centroid, 
+                               double &volume );
+  //@}
 
+  //! Do a an api entity check.
+  int validate();
+
 protected:
 
   RefVolume(Lump* lumpPtr) ;

Modified: cgm/branches/cubit/geom/SenseEntity.hpp
===================================================================
--- cgm/branches/cubit/geom/SenseEntity.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SenseEntity.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -192,7 +192,7 @@
    
 CubitStatus SenseEntity::gpe_insert_before(SenseEntity* next_ptr)
 {
-  prevInParent = prevInParent;
+  prevInParent = next_ptr->prevInParent;
   if (prevInParent)
     prevInParent->nextInParent = this;
   nextInParent = next_ptr;

Modified: cgm/branches/cubit/geom/SplitSurfaceTool.cpp
===================================================================
--- cgm/branches/cubit/geom/SplitSurfaceTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SplitSurfaceTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,14 +1,15 @@
 //-------------------------------------------------------------------------
 // Filename      : SplitSurfaceTool.cpp
 //
-// Purpose       : Split a single or chain of surfaces (ie., split a fillet 
-//                 down the middle so that a mesh sweep can occur).  Used by
-//                 the "split surface" commands.
+// Purpose       : Split a single or chain of surfaces (e.g., split a fillet 
+//                 down the middle so that a mesh sweep can occur, or split
+//                 across a surface).  Used by the "split surface" commands.
 //
 //   Split Surface <id> Across [Pair] Location <options multiple locs>
 //       [Preview [Create]]
 //   Split Surface <id> Across Location <multiple locs> Onto Curve <id>
 //       [Preview [Create]]
+//   Split Surface <id_list> Extend [Vertex <id_list> | Auto] [Preview [Create]]
 //
 //   Split Surface <id_list> [Corner Vertex <id_list>] [Direction Curve <id>]
 //       [Segment <val> | Fraction|Distance <val> [From Curve <id>]]
@@ -38,6 +39,7 @@
 #include "DLIList.hpp"
 #include "TDSplitSurface.hpp"
 #include "GfxDebug.hpp"
+#include "GfxPreview.hpp"
 #include "Cubit2DPoint.hpp"
 #include "GMem.hpp"
 #include "SettingHandler.hpp"
@@ -55,6 +57,9 @@
 CubitBoolean SplitSurfaceTool::autoDetectTriangles = CUBIT_TRUE;
 double SplitSurfaceTool::sideAngleThreshold = 27.0; // From 180
 double SplitSurfaceTool::pointAngleThreshold = 45.0; // Below is a point
+double SplitSurfaceTool::extendGapThreshold = CUBIT_DBL_MAX;
+CubitBoolean SplitSurfaceTool::extendNormalFlg = CUBIT_FALSE;
+double SplitSurfaceTool::extendTolerance = .1;
 
 SplitSurfaceTool::SplitSurfaceTool()
 {
@@ -90,23 +95,54 @@
   SettingHandler::instance()->add_setting("Split Surface Point Angle Threshold", 
                                           SplitSurfaceTool::set_point_angle_threshold, 
 					                                SplitSurfaceTool::get_point_angle_threshold);
+
+  SettingHandler::instance()->add_setting("Split Surface Extend Gap Threshold", 
+                                          SplitSurfaceTool::set_extend_gap_threshold, 
+					                                SplitSurfaceTool::get_extend_gap_threshold);
+
+  SettingHandler::instance()->add_setting("Split Surface Extend Tolerance", 
+                                          SplitSurfaceTool::set_extend_tolerance, 
+					                                SplitSurfaceTool::get_extend_tolerance);
+
+  SettingHandler::instance()->add_setting("Split Surface Extend Normal", 
+                                          SplitSurfaceTool::set_extend_normal_flg, 
+					                                SplitSurfaceTool::get_extend_normal_flg);
 }
 
 CubitStatus                                
 SplitSurfaceTool::preview( RefFace *ref_face_ptr,
                            DLIList<CubitVector*> &locations,
                            DLIList<DLIList<CubitVector*>*> &vec_lists,
-                           CubitBoolean create_ref_edges_flg )
+                           CubitBoolean create_ref_edges_flg,
+                           CubitBoolean clear_previous_previews )
 {
   // Create curves from the input vec_lists (locations are just the original
   // locations the user specified - these need to be drawn)
-  int i;
+  int i, j;
   Curve *curve_ptr;
   DLIList<CubitVector*> *vec_list_ptr;
   vec_lists.reset();
+  DLIList<Surface*> surfs;
 
   Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
 
+  // Support composite surfaces by getting the surfaces underlying
+  // the composite and creating split curves for them individually.
+  GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine();
+  DLIList<TopologyBridge*> tbs;
+  gqe->get_underlying_surfaces(surf_ptr, tbs);
+  if(tbs.size() > 0)
+  {
+    for(j=tbs.size(); j>0; j--)
+      surfs.append(dynamic_cast<Surface*>(tbs.get_and_step()));
+  }
+  else
+    surfs.append(surf_ptr);
+
+  // Clear previous previews if necessary
+  if( clear_previous_previews == CUBIT_TRUE )
+    GfxPreview::clear();
+
   for( i=vec_lists.size(); i--; )
   {
     vec_list_ptr = vec_lists.get_and_step();
@@ -118,21 +154,112 @@
       continue;
     }
 
-    curve_ptr = create_curve( *vec_list_ptr, surf_ptr );
+    for(j=surfs.size(); j>0; j--)
+    {
+      Surface *cur_surf = surfs.get_and_step();
+      curve_ptr = create_curve( *vec_list_ptr, cur_surf );
 
-    if( curve_ptr )
-    {
-      if( create_ref_edges_flg == CUBIT_TRUE )
+      if( curve_ptr )
       {
-        GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+        if( create_ref_edges_flg == CUBIT_TRUE )
+        {
+          RefEdge *ref_edge_ptr;
+          ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+          if( ref_edge_ptr )
+            PRINT_INFO( "Created new curve %d\n", ref_edge_ptr->id() );
+        }
+        else
+        {
+          draw_preview( curve_ptr, CUBIT_FALSE );
+          curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr );
+        }
       }
+    }
+  }
+  
+  // Draw locations too
+  draw_points( locations, CUBIT_BLUE );
+  
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus                                
+SplitSurfaceTool::preview( DLIList<RefFace*> &ref_face_list,
+                           DLIList<CubitVector*> &locations,
+                           DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
+                           CubitBoolean create_ref_edges_flg,
+                           CubitBoolean clear_previous_previews )
+{
+   //Reset ref_face_list and list_of_vec_lists (just in case)
+   ref_face_list.reset();
+   list_of_vec_lists.reset();
+
+   // Clear previous previews if necessary
+   if( clear_previous_previews == CUBIT_TRUE )
+      GfxPreview::clear();  
+   
+   int qq;
+   for( qq = ref_face_list.size(); qq > 0 ; qq--)
+   {
+      //Initialize the values to be used upon each iteration
+      RefFace* ref_face_ptr = ref_face_list.get_and_step();
+      DLIList<DLIList<CubitVector*>*> vec_lists = *( list_of_vec_lists.get_and_step() );
+
+      int i, j;
+      Curve *curve_ptr;
+      DLIList<CubitVector*> *vec_list_ptr;
+      vec_lists.reset();
+      DLIList<Surface*> surfs;
+
+      Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
+
+      // Support composite surfaces by getting the surfaces underlying
+      // the composite and creating split curves for them individually.
+      GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine();
+      DLIList<TopologyBridge*> tbs;
+      gqe->get_underlying_surfaces(surf_ptr, tbs);
+      if(tbs.size() > 0)
+      {
+         for(j=tbs.size(); j>0; j--)
+            surfs.append(dynamic_cast<Surface*>(tbs.get_and_step()));
+      }
       else
+         surfs.append(surf_ptr);
+
+      for( i=vec_lists.size(); i--; )
       {
-        draw_preview( curve_ptr, CUBIT_FALSE );
-         curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr );
+         vec_list_ptr = vec_lists.get_and_step();
+
+         vec_list_ptr->reset();
+         if( vec_list_ptr->size() < 2 )
+         {
+            PRINT_ERROR( "Unable to create a curve from less than two locations.\n" );
+            continue;
+         }
+
+         for(j=surfs.size(); j>0; j--)
+         {
+            Surface *cur_surf = surfs.get_and_step();
+            curve_ptr = create_curve( *vec_list_ptr, cur_surf );
+
+            if( curve_ptr )
+            {
+               if( create_ref_edges_flg == CUBIT_TRUE )
+               {
+                  RefEdge *ref_edge_ptr;
+                  ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+                  if( ref_edge_ptr )
+                     PRINT_INFO( "Created new curve %d\n", ref_edge_ptr->id() );
+               }
+               else
+               {
+                  draw_preview( curve_ptr, CUBIT_FALSE );
+                  curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr );
+               }
+            }
+         }
       }
-    }
-  }
+   }
   
   // Draw locations too
   draw_points( locations, CUBIT_BLUE );
@@ -145,20 +272,24 @@
 //       created curves when it is done with them.
 CubitStatus                                
 SplitSurfaceTool::calculate_split_curves( RefFace *ref_face_ptr,
-                                 DLIList<CubitVector*> &locations,
                                  DLIList<DLIList<CubitVector*>*> &vec_lists,
                                  DLIList<Curve*>& curve_list )
 {
-  // Create curves from the input vec_lists (locations are just the original
-  // locations the user specified - these need to be drawn).  NOTE: drawing
-  // the locations was removed 6/16/05 per Sandia request.
+  Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
+
+  return calculate_split_curves(surf_ptr, vec_lists, curve_list);
+}
+
+CubitStatus                                
+SplitSurfaceTool::calculate_split_curves( Surface *surf_ptr,
+                                 DLIList<DLIList<CubitVector*>*> &vec_lists,
+                                 DLIList<Curve*>& curve_list )
+{
   int i;
   Curve *curve_ptr;
   DLIList<CubitVector*> *vec_list_ptr;
   vec_lists.reset();
 
-  Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
-
   for( i=vec_lists.size(); i--; )
   {
     vec_list_ptr = vec_lists.get_and_step();
@@ -206,6 +337,9 @@
     return CUBIT_FAILURE;
   }
 
+  // Clear any previews
+  GfxPreview::clear();
+
   // Perform the split on the real (e.g. ACIS) geometry. 
   Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
 
@@ -226,10 +360,6 @@
 
   while( curve_list.size() ) 
     delete curve_list.pop();
-  
-  // TODO: Need to find a better place to do the drawing.  Should not be 
-  // using debug graphics to do previews or highlights from within CGM. 
-  // This could create unwanted dependencies between CGM and the graphics. 
 
   // Draw locations too
   // draw_points( locations, CUBIT_BLUE );
@@ -251,14 +381,12 @@
 
 CubitStatus                                
 SplitSurfaceTool::split_surface( RefFace *ref_face_ptr,
-                                 DLIList<CubitVector*> &locations,
                                  DLIList<DLIList<CubitVector*>*> &vec_lists )
 {
   // Count number of surfaces in owning body prior to split - this is used to
   // determine if split is actually successful.
   Body *body_ptr;
   int num_surfaces_prior = count_surfaces_in_owning_body( ref_face_ptr, body_ptr );
-  int num_curves_prior = count_curves_in_body( body_ptr );
   if( num_surfaces_prior == -1 )
   {
     PRINT_ERROR( "Cannot split a surface that is not part of a volume\n" );
@@ -269,39 +397,89 @@
     PRINT_ERROR( "Cannot split a surface that is contained by multiple volumes\n" );
     return CUBIT_FAILURE;
   }
+  int num_curves_prior = count_curves_in_body( body_ptr );
 
+  int original_id = ref_face_ptr->id();
+  Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
+
+  // Clear any previews
+  GfxPreview::clear();
+
   // Find the splitting curves
-  DLIList<Curve*> curve_list;
-  CubitStatus err  = calculate_split_curves( ref_face_ptr, locations, 
-                                             vec_lists, curve_list );
+  DLIList<DLIList<Curve*>*> curve_lists_list;
+
+  // Support composite surfaces by getting the surfaces underlying
+  // the composite and creating split curves for them individually.
+  GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine();
+  DLIList<TopologyBridge*> tbs;
+  gqe->get_underlying_surfaces(surf_ptr, tbs);
+  CubitStatus err = CUBIT_SUCCESS;
+  if(tbs.size() > 0)
+  {
+    err = CUBIT_FAILURE;
+    for(int k=tbs.size(); k>0; k--)
+    {
+      Surface *srf = dynamic_cast<Surface*>(tbs.get_and_step());
+      if(srf)
+      {
+        DLIList<Curve*> *curve_list = new DLIList<Curve*>;
+        CubitStatus tmp_status = calculate_split_curves( srf, vec_lists, *curve_list );
+        // If at least one split is successful return success.  We anticipate that some curves
+        // won't imprint on some of the underlying surfaces of the composite surface.  Because
+        // we are allowing success this way there are sometimes errors that get printed even
+        // though we are calling it a success.  Need to find a good way to fix this.
+        if(tmp_status)
+          err = CUBIT_SUCCESS;
+        curve_lists_list.append(curve_list);
+      }
+    }
+  }
+  else
+  {
+    DLIList<Curve*> *curve_list = new DLIList<Curve*>;
+    err = calculate_split_curves( ref_face_ptr, vec_lists, *curve_list );
+    curve_lists_list.append(curve_list);
+  }
+
   if( err == CUBIT_FAILURE )
+  {
+    while(curve_lists_list.size())
+    {
+      DLIList<Curve*> *cur_list = curve_lists_list.pop();
+      while(cur_list->size())
+        delete cur_list->pop();
+      delete cur_list;
+    }
     return CUBIT_FAILURE;
+  }
 
   // Perform the split on the real (e.g. ACIS) geometry. 
-  Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
-
   DLIList<Surface*> surface_list;
   surface_list.append( surf_ptr );
-  DLIList<DLIList<Curve*>*> curve_lists_list;
-  curve_lists_list.append( &curve_list );
 
   Body *new_body_ptr;
 
   if( GeometryModifyTool::instance()->imprint( surface_list,
     curve_lists_list, new_body_ptr ) == CUBIT_FAILURE )
   {
-    while( curve_list.size() ) 
-      delete curve_list.pop();
+    while(curve_lists_list.size())
+    {
+      DLIList<Curve*> *cur_list = curve_lists_list.pop();
+      while(cur_list->size())
+        delete cur_list->pop();
+      delete cur_list;
+    }
     return CUBIT_FAILURE;
   }
 
-  while( curve_list.size() ) 
-    delete curve_list.pop();
+  while(curve_lists_list.size())
+  {
+    DLIList<Curve*> *cur_list = curve_lists_list.pop();
+    while(cur_list->size())
+      delete cur_list->pop();
+    delete cur_list;
+  }
 
-  // TODO: Need to find a better place to do the drawing.  Should not be 
-  // using debug graphics to do previews or highlights from within CGM. 
-  // This could create unwanted dependencies between CGM and the graphics. 
-
   // Draw locations too
   //draw_points( locations, CUBIT_BLUE );
 
@@ -316,10 +494,144 @@
       return CUBIT_SUCCESS;
   }
   
-  PRINT_ERROR( "Split failed - surface %d was not split\n", ref_face_ptr->id() );
+  PRINT_ERROR( "Split failed - surface %d was not split\n", original_id );
   return CUBIT_FAILURE;
 }
+//ADDED BY GJS (CAT) 6/26/08 @ 11:00am
+CubitStatus                                
+SplitSurfaceTool::split_surface( DLIList<RefFace*> &ref_face_list,
+                                 DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists )
+{
+   //Initialize inputs to imprint function call     
+   DLIList<Surface*> surface_list;
+   DLIList<DLIList<Curve*>*> curve_lists_list;
 
+   // Clear any previews
+   GfxPreview::clear();
+
+   //Reset all lists
+   ref_face_list.reset();
+   list_of_vec_lists.reset();
+
+   int hh;
+   for( hh = ref_face_list.size() ; hh > 0 ; hh--)
+   {
+      // Count number of surfaces in owning body prior to split - this is used to
+      // determine if split is actually successful.   0
+      RefFace* ref_face_ptr = ref_face_list.get_and_step();
+      Body* body_ptr;
+      
+      int num_surfaces_prior = count_surfaces_in_owning_body( ref_face_ptr, body_ptr );
+      if( num_surfaces_prior == -1 )
+      {
+         PRINT_ERROR( "Cannot split a surface that is not part of a volume\n" );
+         return CUBIT_FAILURE;
+      }
+      else if( num_surfaces_prior == -2 )
+      {
+         PRINT_ERROR( "Cannot split a surface that is contained by multiple volumes\n" );
+         return CUBIT_FAILURE;
+      }
+      int num_curves_prior = count_curves_in_body( body_ptr );
+
+      int original_id = ref_face_ptr->id();
+      Surface *surf_ptr = ref_face_ptr->get_surface_ptr();
+
+
+
+      // Support composite surfaces by getting the surfaces underlying
+      // the composite and creating split curves for them individually.
+      GeometryQueryEngine *gqe = surf_ptr->get_geometry_query_engine();
+      DLIList<TopologyBridge*> tbs;
+      gqe->get_underlying_surfaces(surf_ptr, tbs);
+      CubitStatus err = CUBIT_SUCCESS;
+      if(tbs.size() > 0)
+      {
+         err = CUBIT_FAILURE;
+         for(int k=tbs.size(); k>0; k--)
+         {
+            Surface *srf = dynamic_cast<Surface*>(tbs.get_and_step());
+            if(srf)
+            {
+               DLIList<Curve*> *curve_list = new DLIList<Curve*>;
+               DLIList<DLIList<CubitVector*>*> temp_vec_lists = *( list_of_vec_lists.get_and_step() );
+               CubitStatus tmp_status = calculate_split_curves( srf, temp_vec_lists, *curve_list );
+               // If at least one split is successful return success.  We anticipate that some curves
+               // won't imprint on some of the underlying surfaces of the composite surface.  Because
+               // we are allowing success this way there are sometimes errors that get printed even
+               // though we are calling it a success.  Need to find a good way to fix this.
+               if(tmp_status)
+                  err = CUBIT_SUCCESS;
+               curve_lists_list.append(curve_list);
+            }
+         }
+      }
+      else
+      {
+         DLIList<Curve*> *curve_list = new DLIList<Curve*>;
+         DLIList<DLIList<CubitVector*>*> temp_vec_lists = *( list_of_vec_lists.get_and_step() );
+         err = calculate_split_curves( ref_face_ptr, temp_vec_lists, *curve_list );
+         curve_lists_list.append(curve_list);
+      }
+
+      if( err == CUBIT_FAILURE )
+      {
+         while(curve_lists_list.size())
+         {
+            DLIList<Curve*> *cur_list = curve_lists_list.pop();
+            while(cur_list->size())
+               delete cur_list->pop();
+            delete cur_list;
+         }
+         return CUBIT_FAILURE;
+      }
+
+      surface_list.append( surf_ptr );
+   }
+
+   // Perform the split on the real (e.g. ACIS) geometry. 
+   Body *new_body_ptr;
+
+   if( GeometryModifyTool::instance()->imprint( surface_list,
+      curve_lists_list, new_body_ptr ) == CUBIT_FAILURE )
+   {
+      while(curve_lists_list.size())
+      {
+         DLIList<Curve*> *cur_list = curve_lists_list.pop();
+         while(cur_list->size())
+            delete cur_list->pop();
+         delete cur_list;
+      }
+      return CUBIT_FAILURE;
+   }
+
+   while(curve_lists_list.size())
+   {
+      DLIList<Curve*> *cur_list = curve_lists_list.pop();
+      while(cur_list->size())
+         delete cur_list->pop();
+      delete cur_list;
+   }
+
+   //NOTE: current assumption is failure will not occur since user does not
+   //      control input parameters to this function (may need to fix).
+   //int num_surfaces_after = count_surfaces_in_body( body_ptr );
+
+   //if( num_surfaces_after > num_surfaces_prior )
+   //   return CUBIT_SUCCESS;
+   //else
+   //{
+   //   int num_curves_after = count_curves_in_body( body_ptr );
+   //   if( num_curves_after > num_curves_prior )
+   //      return CUBIT_SUCCESS;
+   //}
+
+   //PRINT_ERROR( "Split failed - surface %d was not split\n", original_id );
+   //return CUBIT_FAILURE;
+
+   return CUBIT_SUCCESS;
+}
+
 CubitStatus
 SplitSurfaceTool::draw_points( DLIList<CubitVector*> &pnt_list, int color, 
                                int flush )
@@ -333,7 +645,7 @@
 
   if( flush )
   {
-    GfxDebug::flush();
+    GfxPreview::flush();
   }
 
   return CUBIT_SUCCESS;
@@ -342,10 +654,10 @@
 CubitStatus
 SplitSurfaceTool::draw_point( CubitVector &pnt, int color, int flush )
 {
-  GfxDebug::draw_point( pnt, color );
+  GfxPreview::draw_point( pnt, color );
   if( flush )
   {
-    GfxDebug::flush();
+    GfxPreview::flush();
   }
   return CUBIT_SUCCESS;
 }
@@ -367,6 +679,9 @@
   CubitBoolean just_curves_flg = CUBIT_FALSE;
   DLIList<DLIList<Curve*>*> curve_lists_list;
 
+  // Clear any previous previews
+  GfxPreview::clear();
+
   // Call the primary function
   status = split_surfaces( ref_face_list, num_segs, fraction, distance, 
                            from_curve_ptr, corner_vertex_list, 
@@ -643,6 +958,9 @@
   // Now build up the coordinates and get the curve(s) for each surface
   // curve_lists_list will contain a list of curve lists for each surface
 
+  // Keep track of new RefEdges created
+  DLIList<RefEdge*> new_ref_edge_list;
+
   TDSplitSurface *tdss;
   refFaceChain.reset();
   for(i=refFaceChain.size(); i--; )
@@ -690,14 +1008,23 @@
         draw_preview( *curve_list_ptr );
       else
       {
-        create_ref_edges( *curve_list_ptr );
+        create_ref_edges( *curve_list_ptr, new_ref_edge_list );
 
         // This just draws each curve as we go, same as preview does
-        GfxDebug::flush();
+        GfxPreview::flush();
       }
     }
   }
 
+  // Let the user know if new curves were created
+  if( preview_flg == CUBIT_TRUE && create_ref_edges_flg == CUBIT_TRUE
+      && new_ref_edge_list.size() )
+  {
+    DLIList<CubitEntity*> cubit_entity_list;
+    CAST_LIST( new_ref_edge_list, cubit_entity_list, CubitEntity );
+    CubitUtil::list_entity_ids( "Created new curves: ", cubit_entity_list );
+  }
+
   // Determine if all of the 'through' vertices were used - if not give a warning
   if( throughVertexList.size() )
   {
@@ -3802,7 +4129,7 @@
 }
 
 CubitStatus
-SplitSurfaceTool::check_through_vertices( char *type )
+SplitSurfaceTool::check_through_vertices( const char *type )
 {
   if( throughVertexList.size() )
   {
@@ -4483,8 +4810,9 @@
     
     // Free matrix memory
     for( i=0; i<nr; i++ )
-      delete coords[i];
-    delete coords;
+      delete []coords[i];
+    delete []coords;
+    coords = NULL;
   }
   else
   {
@@ -4558,8 +4886,9 @@
     
     // Free matrix memory
     for( i=0; i<nr; i++ )
-      delete coords[i];
-    delete coords;
+      delete []coords[i];
+    delete []coords;
+    coords = NULL;
   }
 
   return CUBIT_SUCCESS; 
@@ -5020,8 +5349,9 @@
           delete frac_coords[r][c];
       }
       for( r=0; r<nr; r++ )
-        delete frac_coords[r];
-      delete frac_coords;
+        delete []frac_coords[r];
+      delete []frac_coords;
+      frac_coords = NULL;
       
       return CUBIT_FAILURE;
     }
@@ -5058,8 +5388,9 @@
           delete frac_coords[r][c];
       }
       for( r=0; r<nr; r++ )
-        delete frac_coords[r];
-      delete frac_coords;
+        delete []frac_coords[r];
+      delete []frac_coords;
+      frac_coords = NULL;
       
       return CUBIT_FAILURE;
     }
@@ -5107,9 +5438,10 @@
         
         // Free matrix memory
         for( r=0; r<nr; r++ )
-          delete frac_coords[r];
-        delete frac_coords;
-
+          delete []frac_coords[r];
+        delete []frac_coords;
+        frac_coords = NULL;
+        
         // Free spline
         curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr );
         return CUBIT_FAILURE;
@@ -5131,9 +5463,10 @@
   
   // Free matrix memory
   for( r=0; r<nr; r++ )
-    delete frac_coords[r];
-  delete frac_coords;
-
+    delete []frac_coords[r];
+  delete []frac_coords;
+  frac_coords = NULL;
+  
   // Free backup coords
   while( backup_coords.size() )
     delete backup_coords.pop();
@@ -5402,14 +5735,15 @@
 {
   int i;
   Curve *curve_ptr;
-  curve_list.reset();  
+  curve_list.reset();
+
   for( i=curve_list.size(); i--; )
   {
     curve_ptr = curve_list.get_and_step();
     draw_preview( curve_ptr, CUBIT_FALSE, color );
   }
 
-  GfxDebug::flush();
+  GfxPreview::flush();
 
   return CUBIT_SUCCESS;
 }
@@ -5418,37 +5752,39 @@
 SplitSurfaceTool::draw_preview( Curve *curve_ptr, CubitBoolean flush,
                                 int color )
 {
-  int num_points;
   CubitStatus result;
   GMem g_mem;
   
   // get the graphics 
   result = curve_ptr->get_geometry_query_engine()->
-    get_graphics( curve_ptr, num_points, &g_mem );
+    get_graphics( curve_ptr, &g_mem );
   
-  if (result==CUBIT_FAILURE || num_points == 0)
+  if (result==CUBIT_FAILURE || g_mem.pointListCount == 0)
   {
     PRINT_WARNING("Unable to preview a curve\n" );
   }
   
   // Draw the polyline
-  GfxDebug::draw_polyline( g_mem.point_list(), g_mem.pointListCount, color );
+  GfxPreview::draw_polyline( g_mem.point_list(), g_mem.pointListCount, color );
   if( flush )
-    GfxDebug::flush();
+    GfxPreview::flush();
 
   return CUBIT_SUCCESS;
 }
 
 CubitStatus
-SplitSurfaceTool::create_ref_edges( DLIList<Curve*> &curve_list )
+SplitSurfaceTool::create_ref_edges( DLIList<Curve*> &curve_list,
+                                    DLIList<RefEdge*> &ref_edge_list )
 {
   int i;
   Curve *curve_ptr;
+  RefEdge *ref_edge_ptr;
   curve_list.reset();  
   for( i=curve_list.size(); i--; )
   {
     curve_ptr = curve_list.get_and_step();
-    GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+    ref_edge_ptr = GeometryQueryTool::instance()->make_free_RefEdge(curve_ptr);
+    if( ref_edge_ptr ) ref_edge_list.append( ref_edge_ptr );
   }
   return CUBIT_SUCCESS;
 }
@@ -5482,7 +5818,7 @@
 
   if (NULL == gme)
   {
-    PRINT_ERROR("No geometry modify engine available.  Unable to create split curve.");
+    PRINT_ERROR("No geometry modify engine available.  Unable to create split curve.\n");
     return NULL;
   }
 
@@ -5640,26 +5976,22 @@
       PRINT_DEBUG_154( "Inserted %d points when creating spline\n", insert_num );
   }
 
-  if( surf_ptr->geometry_type() != PLANE_SURFACE_TYPE && 
-      project_curve == CUBIT_TRUE )
+  // Project the spline to the surface (if the surface is not planar)
+  DLIList<Surface*> surf_list;
+  surf_list.append( surf_ptr );
+  DLIList<Curve*> curve_list;
+  curve_list.append( curve_ptr );
+  DLIList<Curve*> curve_list_new;
+
+  if( gme->project_edges( surf_list, curve_list, curve_list_new ) == CUBIT_FAILURE )
   {
-    // Project the spline to the surface (if the surface is not planar)
-    DLIList<Surface*> surf_list;
-    surf_list.append( surf_ptr );
-    DLIList<Curve*> curve_list;
-    curve_list.append( curve_ptr );
-    DLIList<Curve*> curve_list_new;
-
-    if( gme->project_edges( surf_list, curve_list, curve_list_new ) == CUBIT_FAILURE )
-    {
-      PRINT_WARNING( "Unable to project curve to surface - split may fail\n" );
-    }
-    else
-    {
-        curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr );
-        curve_ptr = curve_list_new.get();
-    }
+    PRINT_WARNING( "Unable to project curve to surface - split may fail\n" );
   }
+  else
+  {
+      curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr );
+      curve_ptr = curve_list_new.get();
+  }
 
   if( curve_ptr && draw_pnts == CUBIT_TRUE )
   {
@@ -5700,7 +6032,7 @@
     check_pnt.set( start_pnt.x() + .25 * (end_pnt.x() - start_pnt.x()),
                    start_pnt.y() + .25 * (end_pnt.y() - start_pnt.y()),
                    start_pnt.z() + .25 * (end_pnt.z() - start_pnt.z()) );
-    if( is_point_on_surface( surf_ptr, check_pnt, GEOMETRY_RESABS ) == CUBIT_FALSE )
+    if( is_point_on_surface( surf_ptr, check_pnt, GEOMETRY_RESABS ) == CUBIT_FALSE ) 
       return CUBIT_FALSE;
 
     check_pnt.set( start_pnt.x() + .5 * (end_pnt.x() - start_pnt.x()),
@@ -6319,3 +6651,612 @@
   return ref_edge_list.size();
 }
 
+CubitStatus
+SplitSurfaceTool::split_surfaces_extend( DLIList<RefFace*> &ref_face_list,
+                                         DLIList<RefVertex*> &ref_vertex_list,
+                                         CubitBoolean preview_flg,
+                                         CubitBoolean create_ref_edges_flg )
+{
+  // In the below code, "manual" mode refers to when vertices are passed in. In
+  // this mode, an extension must occur from each given vertex for success.
+  // "Auto" mode refers to when no vertices are passed in.  In this mode the 
+  // vertices (curves to extend) are found automatically - the ends of 
+  // hardlines.  Only in auto mode are the gap threshold and normal settings
+  // valid.
+  int i, j;
+  RefFace *ref_face_ptr;
+  RefVertex *ref_vertex_ptr;
+  GeometryModifyEngine *gme;
+  TDSplitSurfaceExtend *tdsse = 0;
+
+  // Clear previous graphics previews
+  GfxPreview::clear();
+  
+  CubitBoolean auto_flg = CUBIT_TRUE;
+  if( ref_vertex_list.size() )
+    auto_flg = CUBIT_FALSE;
+
+  // Copy input face list since we don't want to modify it
+  DLIList<RefFace*> copied_ref_face_list = ref_face_list;
+  
+  // Check for errors
+  copied_ref_face_list.reset();
+  for( i=copied_ref_face_list.size(); i--; )
+  {
+    ref_face_ptr = copied_ref_face_list.get();
+
+    // Check for free and merged surfaces... for both manual and auto cases.
+    //  (we make this fatal for the auto case too since the user can correct
+    //   these and may not even know about them)
+    DLIList<Body*> body_list;
+    ref_face_ptr->bodies( body_list );
+    if( body_list.size()==0 )
+    {
+      PRINT_ERROR( "Surface %d is not contained within a parent body.\n"
+        "       It cannot be split.\n", ref_face_ptr->id() );
+      return CUBIT_FAILURE;
+    }
+    else if( body_list.size() > 1 )
+    {
+      PRINT_ERROR( "Surface %d is merged and cannot be split.\n",
+        ref_face_ptr->id() );
+      return CUBIT_FAILURE;
+    }
+
+    // Check for nonplanar surface.  For auto case, just remove these, but
+    // for manual case, give a fatal error.
+    if( ref_face_ptr->is_planar() == CUBIT_FALSE )
+    {
+      if( auto_flg == CUBIT_TRUE )
+      {
+        copied_ref_face_list.change_to( NULL );
+        copied_ref_face_list.step();
+        continue;
+      }
+      else
+      {
+        // Error out
+        PRINT_ERROR( "The 'split across extend' command only works on planar surfaces.\n"
+          "       Surface %d is nonplanar\n", ref_face_ptr->id() );
+        return CUBIT_FAILURE;
+      }
+    }
+    copied_ref_face_list.step();
+  }
+
+  copied_ref_face_list.remove_all_with_value( NULL );
+
+  // If we don't have any faces left, we exit (could only occur for auto case...
+  // make this a warning instead of an error).
+  if( !copied_ref_face_list.size() )
+  {
+    PRINT_WARNING( "No valid surfaces found to be split. Note to be split, they\n"
+      "         must be nonplanar, contained in a body, and not merged.\n" );
+    return CUBIT_SUCCESS;
+  }
+
+  // Mark each of the input vertices with a tooldata
+  ref_vertex_list.reset();
+  for( i=ref_vertex_list.size(); i--; )
+  {
+    ref_vertex_ptr = ref_vertex_list.get_and_step();
+    ref_vertex_ptr->add_TD( new TDSplitSurfaceExtend() );
+  }
+
+  // Store list of faces and new curves sorted by body and face
+  DLIList<DLIList<Surface*>*> body_surf_list_list;
+  DLIList<DLIList<DLIList<Curve*>*>*> curve_lists_lists_list;
+
+  // Store ids of Curves that are extended
+  DLIList<int> ext_curve_ids;
+
+  // Operate by common body - pull faces out of the input face list that are
+  // from a common Body and place them in a separate list (split_face_list).  
+  Body *curr_Body_ptr;
+  while( copied_ref_face_list.size() )
+  {
+    DLIList<RefFace*> split_face_list; // Holds faces from common body
+
+    // Store new curves for this body, sorted by face
+    DLIList<DLIList<Curve*>*> *curve_lists_list_ptr;
+    curve_lists_list_ptr = new DLIList<DLIList<Curve*>*>;
+    curve_lists_lists_list.append( curve_lists_list_ptr );
+
+    curr_Body_ptr = NULL;
+
+    copied_ref_face_list.reset();
+    for( i=copied_ref_face_list.size(); i--; )
+    {
+      ref_face_ptr = copied_ref_face_list.get();
+
+      DLIList<Body*> body_list;
+      ref_face_ptr->bodies( body_list );
+
+      if( curr_Body_ptr == NULL )
+        curr_Body_ptr = body_list.get();
+
+      if( curr_Body_ptr == body_list.get() )
+      {
+        split_face_list.append( ref_face_ptr );
+        copied_ref_face_list.change_to( NULL );
+      }
+
+      copied_ref_face_list.step();
+    }
+
+    copied_ref_face_list.remove_all_with_value( NULL );
+
+    DLIList<Surface*> *body_surf_list_ptr;
+    body_surf_list_ptr = new DLIList<Surface*>;
+    body_surf_list_list.append( body_surf_list_ptr );
+
+    // Loop through each face on the common body
+    RefFace *split_face_ptr;
+    DLIList<Curve*> *curve_list_ptr;
+    split_face_list.reset();
+    for( i=split_face_list.size(); i--; )
+    {
+      split_face_ptr = split_face_list.get_and_step();
+      body_surf_list_ptr->append( split_face_ptr->get_surface_ptr() );
+
+      curve_list_ptr = new DLIList<Curve*>;
+      curve_lists_list_ptr->append( curve_list_ptr );
+
+      // Get the RefEdges to fire a ray at (from surface)
+      DLIList<RefEdge*> ref_edge_list;
+      split_face_ptr->ref_edges( ref_edge_list );
+      DLIList<RefEntity*> at_entity_list;
+      CAST_LIST( ref_edge_list, at_entity_list, RefEntity );
+
+      // Fire a ray from each vertex in an outward direction from the tangent
+      // of the owning curve at the at_entity_list
+      DLIList<RefVertex*> tmp_vertex_list;
+      split_face_ptr->ref_vertices( tmp_vertex_list );
+
+      tmp_vertex_list.reset();
+      for( j=tmp_vertex_list.size(); j--; )
+      {
+        ref_vertex_ptr = tmp_vertex_list.get_and_step();
+
+        // The vertex must be part of the surface being considered, plus
+        // the attached curve must be on the surface.  We must have one and
+        // only one attached curve.  This curve must be linear.
+
+        // For manual case, only consider vertices that are in the input list
+        if( auto_flg == CUBIT_FALSE )
+        {
+          tdsse = (TDSplitSurfaceExtend *)ref_vertex_ptr->
+            get_TD(&TDSplitSurfaceExtend::is_split_surface_extend);
+          if( !tdsse ) continue;
+        }
+
+        // Get attached RefEdges to this vertex
+        DLIList<RefEdge*> att_ref_edge_list;
+        ref_vertex_ptr->ref_edges( att_ref_edge_list );
+
+        RefEdge *extend_edge_ptr = 0;
+        RefEdge *ref_edge_ptr;
+        int k;
+        for( k=att_ref_edge_list.size(); k--; )
+        {
+          ref_edge_ptr = att_ref_edge_list.get_and_step();
+          if( ref_edge_ptr->is_directly_related( split_face_ptr ) )
+            if( !extend_edge_ptr ) 
+              extend_edge_ptr = ref_edge_ptr;
+            else
+            {
+              extend_edge_ptr = 0;
+              break;
+            }
+        }
+
+        if( !extend_edge_ptr )
+          continue;
+
+        // For now, limit this to linear curves.  Technically, we should be able
+        // to extend non-linear curves though.
+        Curve *curve_ptr = extend_edge_ptr->get_curve_ptr();
+        if( curve_ptr->geometry_type() != STRAIGHT_CURVE_TYPE )
+          continue;
+
+        RefVertex *start_vertex_ptr, *end_vertex_ptr;
+
+        start_vertex_ptr = extend_edge_ptr->start_vertex();
+        end_vertex_ptr = extend_edge_ptr->end_vertex();
+
+        DLIList<double> ray_params;
+        CubitVector start_loc = ref_vertex_ptr->coordinates();
+
+        // Find direction to fire ray
+        CubitVector ray_dir;
+
+        if( ref_vertex_ptr == start_vertex_ptr )
+          ray_dir = start_vertex_ptr->coordinates() - 
+          end_vertex_ptr->coordinates();
+        else
+          ray_dir = end_vertex_ptr->coordinates() - 
+          start_vertex_ptr->coordinates();
+
+        ray_dir.normalize();
+
+        // Remove the curve being extended from the at_entity_list
+        DLIList<RefEntity*> tmp_at_entity_list = at_entity_list;
+        tmp_at_entity_list.remove_all_with_value( extend_edge_ptr );
+
+        // Fire the ray, asking for only one hit
+        DLIList<RefEntity*> hit_entity_list;
+        if( GeometryQueryTool::instance()->fire_ray( start_loc, ray_dir,
+          tmp_at_entity_list, ray_params, 1, 0.0, &hit_entity_list  ) 
+          == CUBIT_FAILURE  ||
+          ray_params.size() == 0 || ray_params.get() == 0.0 )
+          continue;
+
+        //PRINT_INFO( "Got hit from vertex %d on surface %d at distance %lf\n", 
+        //  ref_vertex_ptr->id(), split_face_ptr->id(), ray_params.get() )
+
+        CubitVector end_loc;
+        double ray_param = ray_params.get();
+
+        // Note the hit entity could be a curve or a vertex
+        RefEntity *hit_entity_ptr = 0;
+        RefEdge *hit_edge_ptr = 0;
+        if( hit_entity_list.size() ) // In case fire_ray didn't return hit ents
+        {
+          hit_entity_ptr = hit_entity_list.get();
+          hit_edge_ptr = CAST_TO( hit_entity_ptr, RefEdge );
+        }
+
+        if( extendNormalFlg == CUBIT_TRUE )
+        {
+          // Try going normal to the curve hit.
+          double norm_dist = CUBIT_DBL_MAX;
+
+          if( hit_edge_ptr )
+          {
+            hit_edge_ptr->closest_point( start_loc, end_loc );
+
+            // Only valid if end_loc is ON the curve
+            CubitPointContainment contain = hit_edge_ptr->
+                point_containment( end_loc );
+
+            if( contain != CUBIT_PNT_ON )
+            {
+                // find the nearest curve which the vertex can be extended to and normal
+                RefEdge* new_edge_ptr = NULL;
+                CubitVector new_end_loc;
+                find_nearest_curve_for_normal_projection(
+                    hit_edge_ptr, start_loc, split_face_ptr, ray_dir, new_edge_ptr, new_end_loc);
+
+                if (new_edge_ptr)
+                {
+                    hit_edge_ptr = new_edge_ptr;
+                    end_loc = new_end_loc;
+                }
+            }
+
+            norm_dist = start_loc.distance_between( end_loc );
+          }
+
+          // Use shortest distance between closest normal and ray_param
+          if( ray_param < norm_dist )
+            start_loc.next_point( ray_dir, ray_param, end_loc );
+        }
+        else
+          // Use ray_dir along ray
+          start_loc.next_point( ray_dir, ray_param, end_loc );
+
+        // For auto mode, check to see if we are out of the extendGapThreshold
+        if( auto_flg && 
+           ( start_loc.distance_between( end_loc ) > extendGapThreshold ) )
+          continue;
+
+        // Check for close vertex
+        if( hit_edge_ptr )
+        {
+          double arc_length;
+          
+          // Check distance to start of curve
+          arc_length = hit_edge_ptr->get_arc_length( end_loc, 0 );
+
+          if( arc_length <= extendTolerance )
+          {
+            end_loc = hit_edge_ptr->start_coordinates();
+            PRINT_INFO( "Snapping to close vertex for curve %d extended from vertex %d\n",
+              extend_edge_ptr->id(), ref_vertex_ptr->id() );
+          }
+          else
+          {
+            // Check distance to end of curve
+            arc_length = hit_edge_ptr->get_arc_length( end_loc, 1 );
+
+            if( arc_length <= extendTolerance )
+            {
+              end_loc = hit_edge_ptr->end_coordinates();
+              PRINT_INFO( "Snapping to close vertex for curve %d extended from vertex %d\n",
+                extend_edge_ptr->id(), ref_vertex_ptr->id() );
+            }
+          }
+        }
+
+        curve_ptr = NULL;
+
+        // Create curve (from start_vec to end_vec)
+        Surface *surf_ptr = split_face_ptr->get_surface_ptr();
+
+        gme = GeometryModifyTool::instance()->get_engine( surf_ptr );
+        if( gme == NULL )
+        {
+          PRINT_ERROR("No geometry modify engine available for surface %d\n"
+            "       Unable to create split curve.\n", split_face_ptr->id());
+          // Remove tooldatas and free memory
+          cleanup_for_extend_op( ref_vertex_list, body_surf_list_list,
+            curve_lists_lists_list );
+          return CUBIT_FAILURE;
+        }
+
+        // Create a straight line on the surface
+        Point *start_Point = gme->make_Point( start_loc );
+        Point *end_Point = gme->make_Point( end_loc );
+        if( start_Point == NULL || end_Point == NULL )
+        {
+          PRINT_ERROR("Unable to create points for curve on surface %d\n",
+            split_face_ptr->id() );
+          // Remove tooldatas and free memory
+          cleanup_for_extend_op( ref_vertex_list, body_surf_list_list,
+            curve_lists_lists_list );
+          return CUBIT_FAILURE;
+        }
+        curve_ptr = gme->make_Curve( start_Point, end_Point, surf_ptr );
+        if( !curve_ptr )
+        {
+          PRINT_ERROR( "Unable to create split curve from vertex %d on surface %d\n",
+            ref_vertex_ptr->id(), split_face_ptr->id() );
+          // Remove tooldatas and free memory
+          cleanup_for_extend_op( ref_vertex_list, body_surf_list_list,
+            curve_lists_lists_list );
+          return CUBIT_FAILURE;
+        }
+
+        curve_list_ptr->append( curve_ptr );
+
+        // Keep track of which curves are extended
+        ext_curve_ids.append( extend_edge_ptr->id() );
+
+        if( tdsse )
+          tdsse->set_success();
+      }
+
+    }
+
+    curr_Body_ptr = 0;
+  }
+
+  // For manual mode, check to make sure that all vertices had success,
+  // otherwise, this is an error.  Note... vertices seem to live through
+  // these operations.
+  DLIList<int> vertex_id_list;
+  for( i=ref_vertex_list.size(); i--; )
+  {
+    ref_vertex_ptr = ref_vertex_list.get_and_step();
+
+    tdsse = (TDSplitSurfaceExtend *)ref_vertex_ptr->
+      get_TD(&TDSplitSurfaceExtend::is_split_surface_extend);
+
+    if( !tdsse ) continue;
+
+    if( !tdsse->is_success() )
+      vertex_id_list.append( ref_vertex_ptr->id() );
+  }
+  if( vertex_id_list.size() )
+  {
+    if( vertex_id_list.size() == 1 )
+      PRINT_ERROR( "Unable to extend from vertex %d\n", ref_vertex_ptr->id() );
+    else
+    {
+      PRINT_ERROR( "Unable to extend from vertices\n" );
+      CubitUtil::list_entity_ids( "       Problem vertices: ", vertex_id_list );
+    }
+    PRINT_INFO( "       Vertices must be at the end of only one curve on the surface to split,\n"
+                "       extended curves must be linear, and surfaces to split must be planar.\n" );
+
+    // Remove tooldatas and free memory
+    cleanup_for_extend_op( ref_vertex_list, body_surf_list_list,
+      curve_lists_lists_list );
+    return CUBIT_FAILURE;
+  }
+
+  // Give message as to which curves were extended
+  char msg[50];
+  if( ext_curve_ids.size() )
+  {
+    // Remove duplicates (curves extended from both ends)
+    ext_curve_ids.uniquify_ordered();
+
+    // Give a nice message
+    if( ext_curve_ids.size() == 1 )
+      CubitUtil::list_entity_ids( "1 curve extended: ", ext_curve_ids );
+    else
+    {
+      sprintf( msg, "%d curves extended: ", ext_curve_ids.size() );
+      CubitUtil::list_entity_ids( msg, ext_curve_ids );
+    }
+  }
+  else
+  {
+    // Might as well exit
+    PRINT_INFO( "No curves found to extend\n" );
+    // Remove tooldatas and free memory
+    cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 
+      curve_lists_lists_list );
+    return CUBIT_SUCCESS;
+  }
+
+  // Do the splitting
+  DLIList<Surface*> *surf_list_ptr;
+  DLIList<DLIList<Curve*>*> *curve_lists_list_ptr;
+  body_surf_list_list.reset();
+  curve_lists_lists_list.reset();
+  if( preview_flg==CUBIT_FALSE && create_ref_edges_flg==CUBIT_FALSE )
+  {
+    for( i=body_surf_list_list.size(); i--; )
+    {
+      surf_list_ptr = body_surf_list_list.get_and_step();
+      curve_lists_list_ptr = curve_lists_lists_list.get_and_step();
+
+      Body *new_body_ptr;
+      if( GeometryModifyTool::instance()->imprint( *surf_list_ptr,
+        *curve_lists_list_ptr, new_body_ptr ) == CUBIT_FAILURE )
+      {
+        // Remove tooldatas and free memory
+        cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 
+          curve_lists_lists_list );
+        return CUBIT_FAILURE;
+      }
+    }
+  }
+  else if( preview_flg==CUBIT_TRUE && create_ref_edges_flg==CUBIT_TRUE )
+  {
+    // Just create the RefEdges
+    DLIList<RefEdge*> new_ref_edge_list;
+    curve_lists_lists_list.reset();
+
+    for( i=curve_lists_lists_list.size(); i--; )
+    {
+      curve_lists_list_ptr = curve_lists_lists_list.get_and_step();
+
+      curve_lists_list_ptr->reset();
+      for( j=curve_lists_list_ptr->size(); j--; )
+      {
+        DLIList<Curve*> *curve_list_ptr = curve_lists_list_ptr->get_and_step();
+        curve_list_ptr->reset();
+
+        create_ref_edges( *curve_list_ptr, new_ref_edge_list );
+      }
+    }
+    // Let the user know about the new curves created
+    if( new_ref_edge_list.size() )
+    {
+      DLIList<CubitEntity*> cubit_entity_list;
+      CAST_LIST( new_ref_edge_list, cubit_entity_list, CubitEntity );
+      CubitUtil::list_entity_ids( "Created new curves: ", cubit_entity_list );
+    }
+  }
+  else
+  {
+    // Just preview
+    for( i=body_surf_list_list.size(); i--; )
+    {
+      curve_lists_list_ptr = curve_lists_lists_list.get_and_step();
+
+      curve_lists_list_ptr->reset();
+      for( j=curve_lists_list_ptr->size(); j--; )
+      {
+        DLIList<Curve*> *curve_list_ptr = curve_lists_list_ptr->get_and_step();
+
+        // Draw the curves
+        draw_preview( *curve_list_ptr );
+      }
+    }
+  }
+
+  // Flush the graphics
+  GfxPreview::flush();
+
+  // Remove tooldatas and free memory
+  cleanup_for_extend_op( ref_vertex_list, body_surf_list_list, 
+    curve_lists_lists_list );
+
+  return CUBIT_SUCCESS;
+}
+
+void
+SplitSurfaceTool::cleanup_for_extend_op( DLIList<RefVertex*> &ref_vertex_list,
+                   DLIList<DLIList<Surface*>*> &body_surf_list_list,
+                   DLIList<DLIList<DLIList<Curve*>*>*> &curve_lists_lists_list,
+                   CubitBoolean free_curves_flg )
+{
+  int i;
+  RefVertex *ref_vertex_ptr;
+
+  // Remove tooldatas from vertices
+  ref_vertex_list.reset();
+  for( i=ref_vertex_list.size(); i--; )
+  {
+    ref_vertex_ptr = ref_vertex_list.get_and_step();
+    ref_vertex_ptr->delete_TD( &TDSplitSurfaceExtend::is_split_surface_extend );
+  }
+
+  // Free allocated lists in body_surf_list_list
+  while( body_surf_list_list.size() ) delete body_surf_list_list.pop();
+
+  // Free allocated lists in curve_list_lists_list, as well as Curves (if not
+  // attached to RefEdges).
+  DLIList<DLIList<Curve*>*> *curve_list_lists_ptr;
+  for( i=curve_lists_lists_list.size(); i--; )
+  {
+    curve_list_lists_ptr = curve_lists_lists_list.get();
+
+    free_curves_lists( *curve_list_lists_ptr );
+    delete curve_list_lists_ptr;
+
+    curve_lists_lists_list.step();
+  }
+
+  return;
+}
+
+void SplitSurfaceTool::find_nearest_curve_for_normal_projection(
+	RefEdge* hit_edge_ptr, CubitVector& start_loc, 
+	RefFace* face, CubitVector& ray_dir, RefEdge*& new_edge_ptr,
+	CubitVector& new_end_loc)
+{
+	// traverse the curves in the surface and find the closest curve to the hardline
+	// which the hardline can extend normal to
+
+	DLIList<RefEdge*> edge_list;
+	face->ref_edges(edge_list);
+
+	std::map<double, std::pair<RefEdge*, CubitVector> > potential_curves_map;
+
+	// maybe traverse all curves all of the time, and use the one closest to the point
+	int i;
+	for (i=edge_list.size(); i--;)
+	{
+		RefEdge* edge = edge_list.get_and_step();
+
+		if (edge == hit_edge_ptr)
+			continue;
+
+		CubitVector closest_point;
+		edge->closest_point(start_loc, closest_point);
+
+		// Only valid if location is ON the curve
+		CubitPointContainment contain = edge->point_containment( closest_point );
+		if( contain == CUBIT_PNT_ON )
+		{
+			// check to make sure angle isn't too bad
+			// have a user setting for this in the future
+			// but for now, use 90 degrees
+			CubitVector split_direction = closest_point - start_loc;
+			if (split_direction.length_squared() <= GEOMETRY_RESABS) //ignore self
+				continue;
+
+			double angle = ray_dir.interior_angle(split_direction);
+			if (fabs(angle) <= 90.0)
+			{
+				double dist = start_loc.distance_between(closest_point);
+				potential_curves_map.insert(std::map<double, std::pair<RefEdge*, CubitVector> >::value_type(
+					dist, std::make_pair<RefEdge*, CubitVector>(edge, closest_point)));
+			}
+		}
+	}
+
+	if (potential_curves_map.size())
+	{
+		std::map<double, std::pair<RefEdge*, CubitVector> >::iterator iter = potential_curves_map.begin();
+		new_edge_ptr = (iter->second).first;
+		new_end_loc = (iter->second).second;
+	}
+
+	return;
+}

Modified: cgm/branches/cubit/geom/SplitSurfaceTool.hpp
===================================================================
--- cgm/branches/cubit/geom/SplitSurfaceTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SplitSurfaceTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,13 +1,15 @@
 //-------------------------------------------------------------------------
 // Filename      : SplitSurfaceTool.hpp
 //
-// Purpose       :
+// Purpose       : Split a single or chain of surfaces (e.g., split a fillet 
+//                 down the middle so that a mesh sweep can occur, or split
+//                 across a surface).  Used by the "split surface" commands.
 //
 // Special Notes : 
 //
-// Creator       :
+// Creator       : Steve Storm
 //
-// Creation Date :
+// Creation Date : 10/06/2002
 //-------------------------------------------------------------------------
 
 #ifndef SPLITSURFACETOOL_HPP
@@ -27,6 +29,7 @@
 
 template <class X> class DLIList;
 
+//! Tool class for splitting surfaces.
 class CUBIT_GEOM_EXPORT SplitSurfaceTool
 {
 
@@ -35,25 +38,74 @@
     SplitSurfaceTool();
     ~SplitSurfaceTool(){}
 
+    //! Preview function for simple surface splitting.  Temporary Curves are
+    //! created on the RefFace and displayed.  The curves are created from 
+    //! the input vec_lists (straight lines, arcs or splines).  The input 
+    //! locations are the original input locations from the user, which are 
+    //! displayed as well as the Curves.  The clear_previous_previews flag 
+    //! controls whether previous previews are cleared from the graphics
+    //! window.
     CubitStatus preview( RefFace *ref_face_ptr,
                          DLIList<CubitVector*> &locations,
                          DLIList<DLIList<CubitVector*>*> &vec_lists,
-                         CubitBoolean create_ref_edges_flg );
-    //- Preview function for simple surface splitting.  Temporary Curves are
-    //- created on the RefFace and displayed.  The curves are created from 
-    //- the input vec_lists (straight lines, arcs or splines).  The input 
-    //- locations are the original input locations from the user, which are 
-    //- displayed as well as the Curves.
+                         CubitBoolean create_ref_edges_flg,
+                         CubitBoolean clear_previous_previews = CUBIT_TRUE );
 
+    //! Overloaded preview function to handle multiple surfaces (see above).
+    CubitStatus preview( DLIList<RefFace*> &ref_face_list,
+                         DLIList<CubitVector*> &locations,
+                         DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
+                         CubitBoolean create_ref_edges_flg,
+                         CubitBoolean clear_previous_previews = CUBIT_TRUE );
+   
+    //@{
+    //! Calculate the split curves based on the surface and user parameters.
+    //! The curves are created from the input vec_lists (straight lines, 
+    //! arcs or splines). The input locations are the original input locations 
+    //! from the user.
     CubitStatus calculate_split_curves( RefFace *ref_face_ptr,
-                                        DLIList<CubitVector*> &locations,
                                         DLIList<DLIList<CubitVector*>*> &vec_lists,
-                                        DLIList<Curve*>& curve_list );
-    //- Calculate the split curves based on the surface and user parameters.
-    //- The curves are created from the input vec_lists (straight lines, 
-    //- arcs or splines). The input locations are the original input locations 
-    //- from the user.
+                                        DLIList<Curve*> &curve_list );
+    CubitStatus calculate_split_curves( Surface *surf_ptr,
+                                        DLIList<DLIList<CubitVector*>*> &vec_lists,
+                                        DLIList<Curve*> &curve_list );
+    //@}
 
+    //! Calculates the curves to split a chain of surfaces.
+    //! ref_face_list - chain of surfaces to split.  Can be given in any order
+    //!                 as long as they are connected.  Can be a continuous
+    //!                 loop of surfaces.  If a single surface is given, by
+    //!                 default it will be split along the narrowest aspect
+    //!                 ratio of the surface (i.e., along a fillet).  Periodic
+    //!                 surfaces are not handled.
+    //! num_segs - the number of segments to create (must be >= 2 );
+    //! fraction - the fraction along the surfaces to split, not valid if
+    //!            num_segs > 2.  This value is not used if a distance is
+    //!            specified instead.  
+    //! distance - if 2 segments, allow the split to be at a user specified
+    //!            distance across the surface.  Specify -1.0 to use the
+    //!            fraction instead.
+    //! from_curve_ptr - (OPTIONAL) if user specified a fraction or distance,
+    //!                  orient from this curve.  If not specified, a default
+    //!                  is chosen automatically.
+    //! corner_vertex_list - (OPTIONAL) the user can specify the corners of the,
+    //!                      chain, typically if the detected corners are incorrect.
+    //!                      The split direction is from corners 0-1 to 
+    //!                      corners 2-3 (for single surfaces, if not overridden
+    //!                      by curve_dir_ptr).
+    //! through_vertex_list - (OPTIONAL) user specifies forced vertices for the split
+    //!                       to run through (on curves).  Not valid with
+    //!                       more than 2 segments.
+    //! curve_dir_ptr - (OPTIONAL) for single surfaces, the direction of split can be
+    //!                 specified by picking a curve on the surface.
+    //! preview_flg - if CUBIT_TRUE, just draw the curves that will be used to split 
+    //!               instead of actually splitting.              
+    //! create_ref_edges_flg - valid only if preview_flg=CUBIT_TRUE.  If CUBIT_TRUE,
+    //!                    create RefEdges *instead* of splitting.
+    //! Note this function also utilizes five additional settings which are 
+    //! supplied through the set_tolerance, set_parametric_flg, 
+    //! set_auto_detect_triangles_flg, set_side_angle_threshold, 
+    //! and set_point_angle_threshold functions.     
     CubitStatus calculate_split_curves( DLIList<RefFace*> &ref_face_list, 
                                         int num_segs, double fraction, 
                                         double distance, RefEdge *from_curve_ptr,
@@ -64,52 +116,57 @@
                                         CubitBoolean create_ref_edges_flg,
                                         CubitBoolean just_curves_flg,
                                         DLIList<DLIList<Curve*>*> &curve_lists_list ); 
-    //- Calculates the curves to split a chain of surfaces.
-    //- ref_face_list - chain of surfaces to split.  Can be given in any order
-    //-                 as long as they are connected.  Can be a continuous
-    //-                 loop of surfaces.  If a single surface is given, by
-    //-                 default it will be split along the narrowest aspect
-    //-                 ratio of the surface (i.e., along a fillet).  Periodic
-    //-                 surfaces are not handled.
-    //- num_segs - the number of segments to create (must be >= 2 );
-    //- fraction - the fraction along the surfaces to split, not valid if
-    //-            num_segs > 2.  This value is not used if a distance is
-    //-            specified instead.  
-    //- distance - if 2 segments, allow the split to be at a user specified
-    //-            distance across the surface.  Specify -1.0 to use the
-    //-            fraction instead.
-    //- from_curve_ptr - (OPTIONAL) if user specified a fraction or distance,
-    //-                  orient from this curve.  If not specified, a default
-    //-                  is chosen automatically.
-    //- corner_vertex_list - (OPTIONAL) the user can specify the corners of the,
-    //-                      chain, typically if the detected corners are incorrect.
-    //-                      The split direction is from corners 0-1 to 
-    //-                      corners 2-3 (for single surfaces, if not overridden
-    //-                      by curve_dir_ptr).
-    //- through_vertex_list - (OPTIONAL) user specifies forced vertices for the split
-    //-                       to run through (on curves).  Not valid with
-    //-                       more than 2 segments.
-    //- curve_dir_ptr - (OPTIONAL) for single surfaces, the direction of split can be
-    //-                 specified by picking a curve on the surface.
-    //- preview_flg - if CUBIT_TRUE, just draw the curves that will be used to split 
-    //-               instead of actually splitting.              
-    //- create_ref_edges_flg - valid only if preview_flg=CUBIT_TRUE.  If CUBIT_TRUE,
-    //-                    create RefEdges *instead* of splitting.
-    //- Note this function also utilizes two additional settings which are 
-    //- supplied through the set_tolerance and set_parametric_flg functions.    
 
+    //! Split function for simple surface splitting.  Temporary Curves are
+    //! created on the RefFace and used to split the RefFace.  The curves are 
+    //! created from the input vec_lists (straight lines, arcs or splines).
+    //! The input locations are the original input locations from the user,
+    //! which are displayed for user reference.
     CubitStatus split_surface( RefFace *ref_face_ptr,
-                               DLIList<CubitVector*> &locations,
                                DLIList<DLIList<CubitVector*>*> &vec_lists );
-    //- Split function for simple surface splitting.  Temporary Curves are
-    //- created on the RefFace and used to split the RefFace.  The curves are 
-    //- created from the input vec_lists (straight lines, arcs or splines).
-    //- The input locations are the original input locations from the user,
-    //- which are displayed for user reference.
 
+    //! Overloaded split function to allow multiple surfaces to be split (see above).
+    CubitStatus split_surface( DLIList<RefFace*> &ref_face_list, 
+                               DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists );
+
+    //! Split function for simple surface splitting using a list of predefined curves
     CubitStatus split_surface( RefFace *ref_face_ptr, DLIList<Curve*> &curve_list);
-    //- Split function for simple surface splitting using a list of predefined curves
     
+    //! Splits the chain of surfaces.
+    //! ref_face_list - chain of surfaces to split.  Can be given in any order
+    //!                 as long as they are connected.  Can be a continuous
+    //!                 loop of surfaces.  If a single surface is given, by
+    //!                 default it will be split along the narrowest aspect
+    //!                 ratio of the surface (i.e., along a fillet).  Periodic
+    //!                 surfaces are not handled.
+    //! num_segs - the number of segments to create (must be >= 2 );
+    //! fraction - the fraction along the surfaces to split, not valid if
+    //!            num_segs > 2.  This value is not used if a distance is
+    //!            specified instead.  
+    //! distance - if 2 segments, allow the split to be at a user specified
+    //!            distance across the surface.  Specify -1.0 to use the
+    //!            fraction instead.
+    //! from_curve_ptr - (OPTIONAL) if user specified a fraction or distance,
+    //!                  orient from this curve.  If not specified, a default
+    //!                  is chosen automatically.
+    //! corner_vertex_list - (OPTIONAL) the user can specify the corners of the,
+    //!                      chain, typically if the detected corners are incorrect.
+    //!                      The split direction is from corners 0-1 to 
+    //!                      corners 2-3 (for single surfaces, if not overridden
+    //!                      by curve_dir_ptr).
+    //! through_vertex_list - (OPTIONAL) user specifies forced vertices for the split
+    //!                       to run through (on curves).  Not valid with
+    //!                       more than 2 segments.
+    //! curve_dir_ptr - (OPTIONAL) for single surfaces, the direction of split can be
+    //!                 specified by picking a curve on the surface.
+    //! preview_flg - if CUBIT_TRUE, just draw the curves that will be used to split 
+    //!               instead of actually splitting.              
+    //! create_ref_edges_flg - valid only if preview_flg=CUBIT_TRUE.  If CUBIT_TRUE,
+    //!                    create RefEdges *instead* of splitting.
+    //! Note this function also utilizes five additional settings which are 
+    //! supplied through the set_tolerance, set_parametric_flg, 
+    //! set_auto_detect_triangles_flg, set_side_angle_threshold, 
+    //! and set_point_angle_threshold functions.    
     CubitStatus split_surfaces( DLIList<RefFace*> &ref_face_list,
                                 int num_segs,
                                 double fraction,
@@ -120,40 +177,13 @@
                                 RefEdge *curve_dir_ptr = NULL,
                                 CubitBoolean preview_flg = CUBIT_FALSE,
                                 CubitBoolean create_ref_edges_flg = CUBIT_FALSE );
-    //- Splits the chain of surfaces.
-    //- ref_face_list - chain of surfaces to split.  Can be given in any order
-    //-                 as long as they are connected.  Can be a continuous
-    //-                 loop of surfaces.  If a single surface is given, by
-    //-                 default it will be split along the narrowest aspect
-    //-                 ratio of the surface (i.e., along a fillet).  Periodic
-    //-                 surfaces are not handled.
-    //- num_segs - the number of segments to create (must be >= 2 );
-    //- fraction - the fraction along the surfaces to split, not valid if
-    //-            num_segs > 2.  This value is not used if a distance is
-    //-            specified instead.  
-    //- distance - if 2 segments, allow the split to be at a user specified
-    //-            distance across the surface.  Specify -1.0 to use the
-    //-            fraction instead.
-    //- from_curve_ptr - (OPTIONAL) if user specified a fraction or distance,
-    //-                  orient from this curve.  If not specified, a default
-    //-                  is chosen automatically.
-    //- corner_vertex_list - (OPTIONAL) the user can specify the corners of the,
-    //-                      chain, typically if the detected corners are incorrect.
-    //-                      The split direction is from corners 0-1 to 
-    //-                      corners 2-3 (for single surfaces, if not overridden
-    //-                      by curve_dir_ptr).
-    //- through_vertex_list - (OPTIONAL) user specifies forced vertices for the split
-    //-                       to run through (on curves).  Not valid with
-    //-                       more than 2 segments.
-    //- curve_dir_ptr - (OPTIONAL) for single surfaces, the direction of split can be
-    //-                 specified by picking a curve on the surface.
-    //- preview_flg - if CUBIT_TRUE, just draw the curves that will be used to split 
-    //-               instead of actually splitting.              
-    //- create_ref_edges_flg - valid only if preview_flg=CUBIT_TRUE.  If CUBIT_TRUE,
-    //-                    create RefEdges *instead* of splitting.
-    //- Note this function also utilizes two additional settings which are 
-    //- supplied through the set_tolerance and set_parametric_flg functions.    
 
+    //! Same as above except this method simply returns a list of lists of 
+    //! Curves (one list per input RefFace).  This method is intended for
+    //! use by a programmer (rather than a user from GeometryCommands).
+    //! Note it is the calling functions responsibility to free the memory
+    //! allocated in curve_lists_list, as well as the Curves (note this can
+    //! be accomplished with the function free_curves_lists).
     CubitStatus split_surfaces( DLIList<RefFace*> &ref_face_list,
                                 int num_segs,
                                 double fraction,
@@ -163,13 +193,8 @@
                                 DLIList<RefVertex*> &through_vertex_list,
                                 RefEdge *curve_dir_ptr,
                                 DLIList<DLIList<Curve*>*> &curve_lists_list );
-    //- Same as above except this method simply returns a list of lists of 
-    //- Curves (one list per input RefFace).  This method is intended for
-    //- use by a programmer (rather than a user from GeometryCommands).
-    //- Note it is the calling functions responsibility to free the memory
-    //- allocated in curve_lists_list, as well as the Curves (note this can
-    //- be accomplished with the function free_curves_lists).
 
+    //! Same as above except this method simply returns a simple list of Curves.
     CubitStatus split_surfaces( DLIList<RefFace*> &ref_face_list,
                                 int num_segs,
                                 double fraction,
@@ -179,65 +204,118 @@
                                 DLIList<RefVertex*> &through_vertex_list,
                                 RefEdge *curve_dir_ptr,
                                 DLIList<Curve*> &curve_list );
-    //- Same as above except this method simply returns a simple list of Curves.
 
+    //! Splits surfaces by extending curves at the end of hardlines across the
+    //! surface.  Only works on planar surfaces and by extending linear curves.
+    //! If specified vertex list is provided, only try to extend curves
+    //! attached to those vertices, and error out if unable to perform the
+    //! operation using any vertex.  If no vertex list is provided, find 
+    //! appropriate vertices automatically, and limit the split to gaps less
+    //! than or equal to the specified "split surface extend gap threshold".
+    //! {ref_face_list} - list of connected surfaces to split
+    //! {ref_vertex_list} - (OPTIONAL) - vertices to extend from. Function will
+    //!                     error out if unable to extend from any vertex. If
+    //!                     not supplied, function will automatically find
+    //!                     valid vertices to extend from on the surfaces, and
+    //!                     will limit the split to gaps less than or equal to 
+    //!                     the specified extend gap threshold (see setting 
+    //!                     below).
+    //! {preview_flg} - routine only displays graphics preview of splits
+    //! {create_ref_edges_flg} - valid only if preview_flg=CUBIT_TRUE.  If
+    //!                          CUBIT_TRUE, create RefEdges *instead* of
+    //!                          splitting.
+    //! Note this function also utilizes thress additional settings which are 
+    //! supplied through the set_extend_gap_threshold, set_extend_tolerance and
+    //! set_extend_normal functions. 
+    CubitStatus split_surfaces_extend( DLIList<RefFace*> &ref_face_list,
+                                     DLIList<RefVertex*> &ref_vertex_list,
+                                     CubitBoolean preview_flg = CUBIT_FALSE,
+                                     CubitBoolean create_ref_edges_flg = CUBIT_FALSE );
+
+    //! Free the curves and lists memory.  If free_curves_flg is CUBIT_TRUE,
+    //! free the Curves as well (however, the function checks if a RefEdge is 
+    //! attached to the Curve - if a RefEdge is attached the Curve is not freed).
     void free_curves_lists( DLIList<DLIList<Curve*>*> &curve_lists_list,
                             CubitBoolean free_curves_flg = CUBIT_TRUE );
-    //- Free the curves and lists memory.  If free_curves_flg is CUBIT_TRUE,
-    //- free the Curves as well (however, the function checks if a RefEdge is 
-    //- attached to the Curve - if a RefEdge is attached the Curve is not freed).
 
+    //! Set the tolerance (function returns previous tolerance)
     static void set_tolerance( double tol );
-    //- Set the tolerance (function returns previous tolerance)
+
+    //! Get the tolerance.  In layman's terms, the tolerance controls how 
+    //! closely the split actually follows the center of the surface. In the
+    //! code, it determines how accurately to facet the bounding curves (the 
+    //! facets are used to interpolate points on the surface using a mapping 
+    //! concept).  It is also used in an iterative procedure in fitting splines
+    //! to the line segments generated by the mapping (just fitting a spline 
+    //! through the interpolated points was found to give very bad results - 
+    //! instead we check the deviation of the spline from the line segments and
+    //! add additional points until the resultant spline is within tolerance to
+    //! the line segments.
     static double get_tolerance();
-    //- Get the tolerance.  In layman's terms, the tolerance controls how 
-    //- closely the split actually follows the center of the surface. In the
-    //- code, it determines how accurately to facet the bounding curves (the 
-    //- facets are used to interpolate points on the surface using a mapping 
-    //- concept).  It is also used in an iterative procedure in fitting splines
-    //- to the line segments generated by the mapping (just fitting a spline 
-    //- through the interpolated points was found to give very bad results - 
-    //- instead we check the deviation of the spline from the line segments and
-    //- add additional points until the resultant spline is within tolerance to
-    //- the line segments.
 
+    //! Set the auto detect triangles flag
     static void set_auto_detect_triangles_flg( CubitBoolean auto_detect_flg );
-    //- Set the auto detect triangles flag
+
+    //! Get the auto detect triangles flag
     static CubitBoolean get_auto_detect_triangles_flg();
-    //- Get the auto detect triangles flag
 
+    //! Set the side angle threshold
     static void set_side_angle_threshold( double angle );
-    //- Set the side angle threshold
+
+    //! Get the side angle threshold.  If there is a corner angle within this
+    //! threshold to 180 and another corner angle less than the point threshold, a
+    //! triangle is created.
     static double get_side_angle_threshold();
-    //- Get the side angle threshold.  If there is a corner angle within this
-    // threshold to 180 and another corner angle less than the point threshold, a
-    // triangle is created.
 
+    //! Set the point angle threshold
     static void set_point_angle_threshold( double tol );
-    //- Set the point angle threshold
+
+    //! Get the point angle threshold.  If there is a corner angle less than
+    //! this value and another corner angle within the side threshold to 180, a
+    //! triangle is created.
     static double get_point_angle_threshold();
-    //- Get the point angle threshold.  If there is a corner angle less than
-    // this value and another corner angle within the side threshold to 180, a
-    // triangle is created.
 
+    //! Set the parametric flag
     static void set_parametric_flg( CubitBoolean parametric_flg );
-    //- Set the parametric flag
+
+    //! Get the parametric flag.  If the parametric_flg is CUBIT_TRUE, find
+    //! spline locations in the parametric space of the surface, otherwise
+    //! initially find the spline locations in 3D space then project back to
+    //! the surface.  Typically, the parametric space gives better results
+    //! (on curvy surfaces, it will result in a spline that is much closer to
+    //! the middle of the surface).  However, sometimes the parameter space
+    //! is bad or the mapping algorigm gets confused (frequently on conic
+    //! surfaces, resulting in points revolved 180 deg away), so the 3D method
+    //! gives a better result.  Note the default is thus 3D.
     static CubitBoolean get_parametric_flg();
-    //- Get the parametric flag.  If the parametric_flg is CUBIT_TRUE, find
-    //- spline locations in the parametric space of the surface, otherwise
-    //- initially find the spline locations in 3D space then project back to
-    //- the surface.  Typically, the parametric space gives better results
-    //- (on curvy surfaces, it will result in a spline that is much closer to
-    //- the middle of the surface).  However, sometimes the parameter space
-    //- is bad or the mapping algorigm gets confused (frequently on conic
-    //- surfaces, resulting in points revolved 180 deg away), so the 3D method
-    //- gives a better result.  Note the default is thus 3D.
 
+    //! Set the extend gap threshold.  Only split if gap is less than this.
+    static void set_extend_gap_threshold( double threshold = CUBIT_DBL_MAX );
+
+    //! Get the extend gap threshold.
+    static double get_extend_gap_threshold();
+
+    //! Set the extend tolerance.  Snaps to vertices along curves within this
+    //! tolerance so as to avoid creating short curves when splitting surfaces
+    //! with the extend method.
+    static void set_extend_tolerance( double tol );
+
+    //! Get the extend tolerance.
+    static double get_extend_tolerance();
+
+    //! Set the extend normal flag.  If projecting normal to curve is less
+    //! distance, use that instead of extending curve, if this setting is 
+    //! true.
+    static void set_extend_normal_flg( CubitBoolean extend_normal_flg );
+
+    //! Return extend normal setting.
+    static CubitBoolean get_extend_normal_flg();
+
+    //! Initialize settings for this class
     static void initialize_settings();
-    //- Initialize settings for this class
 
+    //! preview the curves
     CubitStatus draw_preview( DLIList<Curve*> &curve_list, int color=CUBIT_BLUE );
-    //- preview the curves
 
   private:
 
@@ -459,7 +537,7 @@
     CubitBoolean is_triangle();
     //- Determines if a single surface chain is a triangle
 
-    CubitStatus check_through_vertices( char *type );
+    CubitStatus check_through_vertices( const char *type );
     //- Determines if the through vertices are on valid sides of the surface.
     //- Call this function after adjusting for a Curve direction.
     //- This function only checks - it gives an error if through vertices are 
@@ -554,8 +632,9 @@
       int color=CUBIT_BLUE );
     //- Draw the curves
 
-    CubitStatus create_ref_edges( DLIList<Curve*> &curve_list );
-    //- Create RefEdges from the given Curves
+    CubitStatus create_ref_edges( DLIList<Curve*> &curve_list, 
+                                  DLIList<RefEdge*> &ref_edge_list );
+    //- Create RefEdges from the given Curves.  Appends to the output list.
 
     int number_coedges( RefEdge *ref_edge_ptr, RefFace *ref_face_ptr );
     //- Finds the number of coedges for the given edge on the given surface
@@ -674,6 +753,23 @@
     int count_curves_in_body( Body *body_ptr );
     //- Return number of curves in the body
 
+    void cleanup_for_extend_op( DLIList<RefVertex*> &ref_vertex_list,
+      DLIList<DLIList<Surface*>*> &body_surf_list_list,
+      DLIList<DLIList<DLIList<Curve*>*>*> &curve_lists_lists_list,
+      CubitBoolean free_curves_flg = CUBIT_TRUE );
+    //- This function cleans up after the split extend operation.  It removes
+    //- the tooldatas from the vertices and frees the lists memory.  If
+    //- free_curves_flg is CUBIT_TRUE, free the Curves as well (however, the 
+    //- function checks if a RefEdge is attached to the Curve - if a RefEdge
+    //- is attached the Curve is not freed).
+
+	void find_nearest_curve_for_normal_projection(
+		RefEdge* hit_edge_ptr, CubitVector& start_loc, RefFace* face, 
+		CubitVector& ray_dir, RefEdge*& new_edge_ptr, CubitVector& new_end_loc);
+	//- This function is used when the split extend command is used with normal = TRUE and
+	//- the hardline does not intersect the curve found by fire_ray at a 90 degree angle.
+	//- This function traverses the curve's neighbors to find a curve that can be split normal.
+
     static CubitBoolean parametricFlg; // Split parametrically or not (3D)
     static double splitTolerance; // Length tolerance for tessellations, etc.
     static CubitBoolean autoDetectTriangles; // Detect triangles automatically?
@@ -684,6 +780,14 @@
                                        // the triangle point (if sideAngleThreshold
                                        // criteria also met)
 
+    static double extendGapThreshold; // Only gaps below this value are split
+    static CubitBoolean extendNormalFlg; // If true, extend normal to curve 
+                                         // instead of in curve direction if 
+                                         // distance is less
+    static double extendTolerance; // If split end is equal or closer than this
+                                   // to a vertex along a curve snap to the
+                                   // vertex.
+
     DLIList<RefFace*> refFaceChain;
     DLIList<RefVertex*> throughVertexList;
     DLIList<CoEdge*> outerCoEdgeLoop;
@@ -732,5 +836,29 @@
 SplitSurfaceTool::get_parametric_flg()
 { return parametricFlg; }
 
+inline void
+SplitSurfaceTool::set_extend_gap_threshold( double gap )
+{ extendGapThreshold = gap; }
+
+inline double
+SplitSurfaceTool::get_extend_gap_threshold()
+{ return extendGapThreshold; }
+
+inline void
+SplitSurfaceTool::set_extend_tolerance( double tol )
+{ extendTolerance = tol; }
+
+inline double
+SplitSurfaceTool::get_extend_tolerance()
+{ return extendTolerance; }
+
+inline void
+SplitSurfaceTool::set_extend_normal_flg( CubitBoolean extend_normal_flg )
+{ extendNormalFlg = extend_normal_flg; }
+
+inline CubitBoolean
+SplitSurfaceTool::get_extend_normal_flg()
+{ return extendNormalFlg; }
+
 #endif
 

Modified: cgm/branches/cubit/geom/SurfParamTool.cpp
===================================================================
--- cgm/branches/cubit/geom/SurfParamTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SurfParamTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -17,7 +17,7 @@
 #include "SurfParamTool.hpp"
 #include "CastTo.hpp"
 #include "Surface.hpp"
-#include "DLIList.hpp"
+#include "DLIList.hpp" 
 
 //-------------------------------------------------------------------------
 // Function:    SurfParamTool
@@ -27,13 +27,9 @@
 //-------------------------------------------------------------------------
 SurfParamTool::SurfParamTool(Surface *surf) 
 {
-//	FacetEvalTool **surf_eval_tool = NULL;
-//	DLIList<CubitFacet *> facet_list;
 
 	//- update private variables
 	refSurf = surf;
-//	refSurf->setup_use_facets(facet_list,0,surf_eval_tool);
-//	feTool = *surf_eval_tool;
 
 }
 
@@ -53,111 +49,8 @@
 //===================================================================================
 CubitStatus SurfParamTool::set_up_space(void) {
 	
-	//double u, v, s;
 	CubitStatus rv = CUBIT_SUCCESS;
 
-	//- calculate uv position for every point
-//	TDFacetBoundaryPoint *td_fbp;
-//	CubitBoolean on_internal_boundary;
-//	DLIList<CubitFacet *> facet_list;
-//	DLIList<CubitPoint *> point_list;
-//	CubitPoint *pt_ptr;
-//	int ii;
-//	feTool->get_points(point_list);
-//	for(ii = 0; ii < point_list.size() && rv == CUBIT_SUCCESS; ii++) {
-//		pt_ptr = point_list.get_and_step();
-//		rv = refSurf->u_v_from_position(pt_ptr->coordinates(), u, v);
-//		facet_list.clean_out();
-//		pt_ptr->facets_on_surf( feTool->tool_id(), facet_list, on_internal_boundary );
-//		if (on_internal_boundary)
-//		{
-//			td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( pt_ptr );
-//			if (!td_fbp)
-//			{
-//				TDFacetBoundaryPoint::add_facet_boundary_point( pt_ptr );
-//				td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( pt_ptr );
-//				td_fbp->add_surf_facets( facet_list );
-//				td_fbp->set_uv( facet_list.get(), u, v);
-//			}
-//			else
-//			{
-//				if (td_fbp->set_uv( facet_list.get(),
-//					u, v ) != CUBIT_SUCCESS)
-//				{
-//					td_fbp->add_surf_facets( facet_list );
-//					td_fbp->set_uv( facet_list.get(), u, v);
-//				}
-//			}
-//		}
-//		else
-//		{
-//			pt_ptr->set_uv( u, v);
-//		}
-//	}
-//
-//	//- calculate distortion [sum(original facet area/uv area)/total facets]
-//	CubitFacet *facet_ptr;
-//	CubitPoint *p0, *p1, *p2;
-//	int jj;
-//	double orig_area, uv_area, sum_area, u0, u1, u2, v0, v1, v2;
-//	for(ii = 0; ii < point_list.size() && rv == CUBIT_SUCCESS; ii++) {
-//		pt_ptr = point_list.get_and_step();
-//		facet_list.clean_out();
-//		pt_ptr->facets_on_surf(feTool->tool_id(), facet_list, on_internal_boundary);
-//		
-//		sum_area = 0;
-//		for(jj = 0; jj < facet_list.size(); jj++){
-//			facet_ptr = facet_list.get_and_step();
-//
-//			//- calculate original area
-//			orig_area = facet_ptr->area();
-//
-//			//- extract uv data
-//			facet_ptr->points(p0, p1, p2);
-//			p0->get_uv(facet_ptr, u0, v0);
-//			p1->get_uv(facet_ptr, u1, v1);
-//			p2->get_uv(facet_ptr, u2, v2);
-//
-//			//- calculate uv area
-//			CubitVector uv0(u0,v0,0.0);
-//			CubitVector uv1(u1,v1,0.0);
-//			CubitVector uv2(u2,v2,0.0);
-//			CubitVector e0(uv0, uv1);
-//			CubitVector e1(uv0, uv2);
-//			uv_area = (e0*e1).length()*0.5;
-//
-//			sum_area += sqrt(uv_area/orig_area);
-//		}
-//	
-//		s = sum_area/facet_list.size();
-//		pt_ptr->get_uv(facet_list.get(), u, v);
-//
-//		if (on_internal_boundary)
-//		{
-//			td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( pt_ptr );
-//			if (!td_fbp)
-//			{
-//				TDFacetBoundaryPoint::add_facet_boundary_point( pt_ptr );
-//				td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( pt_ptr );
-//				td_fbp->add_surf_facets( facet_list );
-//				td_fbp->set_uvs( facet_list.get(), u, v, s);
-//			}
-//			else
-//			{
-//				if (td_fbp->set_uvs( facet_list.get(),
-//					u, v, s ) != CUBIT_SUCCESS)
-//				{
-//						td_fbp->add_surf_facets( facet_list );
-//						td_fbp->set_uvs( facet_list.get(), u, v, s);
-//				}
-//			}
-//		}
-//		else
-//		{
-//			pt_ptr->set_uvs( u, v, s);
-//		}
-//				
-//	}
 	
 	return rv; 
 }
@@ -168,55 +61,217 @@
 // Author: chynes
 // Date: 7/10/02
 //===================================================================================
-CubitStatus SurfParamTool::transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location) 
+CubitStatus SurfParamTool::transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location) 
 {
 	double u,v;
-	CubitStatus rv = CUBIT_SUCCESS;
-//	DLIList<CubitFacet *> facet_list; 
-//	CubitFacet *tri_ptr;
-//	CubitBoolean *outside = CUBIT_FALSE;
-//	CubitVector closest_point;
-//	CubitVector area_coord;
-//	double compare_tol;
+
+	CubitStatus rv = refSurf->u_v_from_position(xyz_location, u, v);
+	uv_location.set(u,v,1.0);
+
+	CubitVector du, dv;
+	uv_derivitives(u,v,du,dv);
+
+	return rv;
+}
+
+//===================================================================================
+// Function: transform_to_xyz (Public)
+// Description: same as title
+// Author: chynes
+// Date: 7/10/02
+//===================================================================================
+CubitStatus SurfParamTool::transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location) 
+{
+	xyz_location = refSurf->position_from_u_v(uv_location.x(), uv_location.y());
+
+	return CUBIT_SUCCESS;
+}
+
+CubitStatus SurfParamTool::uv_derivitives( double u_param, double v_param, CubitVector &du, CubitVector &dv )
+{
+	return refSurf->uv_derivitives (u_param, v_param, du, dv);
+}
+
+//void intersect2DLines(double x0, double y0, double x1, double y1, 
+//					  double x2, double y2, double x3, double y3,
+//					  double &xc, double &yc)
+////
+//// intersect two lines in 2D.  First line defined by points 0 and 1, second by points 2 and 3
+////
+//{
+//	double u = ( (x3-x2)*(y0-y2) - (y3-y2)*(x0-x2) ) / ( (y3-y2)*(x1-x0) - (x3-x2)*(y1-y0) );
 //
-//	// find best compare_tol
-//	compare_tol = 1e-3*(feTool->bounding_box().diagonal().length());
+//	xc = x0 + u * (x1-x0);
+//	yc = y0 + u * (y1-y0);
+//}
 //
-//	// locate point
-//	feTool->get_facets(facet_list);
-//	rv = FacetEvalTool::project_to_facets(facet_list, 
-//										  tri_ptr, 
-//										  0, 
-//										  compare_tol, 
-//										  xyz_location, 
-//										  CUBIT_FALSE, 
-//										  outside, 
-//										  &closest_point, 
-//										  NULL);
-//	// determine barycentric coordinates for in facet
-//	if(rv == CUBIT_SUCCESS) 
-//	{
-//		FacetEvalTool::facet_area_coordinate(tri_ptr, closest_point, area_coord);
+//	
 //
-//		// extract data
-//		double u0, u1, u2, v0, v1, v2, s0, s1, s2;
-//		CubitPoint *p0, *p1, *p2;
-//		tri_ptr->points(p0, p1, p2);
-//		p0->get_uvs(tri_ptr, u0, v0, s0);
-//		p1->get_uvs(tri_ptr, u1, v1, s1);
-//		p2->get_uvs(tri_ptr, u2, v2, s2);
+//CubitStatus SurfParamTool::circumcenter(double u0, double v0, 
+//						 double u1, double v1,
+//						 double u2, double v2,
+//						 CubitVector &center)
+////
+//// Calculates the center of the center of the circumellipse for the three points in parameter space
+//// this (u,v) should map back to the circumcenter of the circle of the three points in three-space.
+////
+//{
 //
-//		rv = refSurf->u_v_from_position(xyz_location, u, v);
-//		// determine sizing
-//		s = (area_coord.x()*s0) + (area_coord.y()*s1) + (area_coord.z()*s2);
+//	// first, lets calculate the circumcenter without the gradients to make sure the system works
 //
-//		uv_location.set(u,v,s);
-//	}
+//	// our method for finding a circumcenter utilizes the fact that the perpendicalar bisectors of each side 
+//	// of the triangle intersect at the circumcenter
+//
+//	// find the three bisectors of the sides
+//
+//	double u3 = u0 + (u1 - u0) * 0.5;	// midpoint of side 0-1
+//	double v3 = v0 + (v1 - v0) * 0.5;
+//
+//	double u4 = u3 + v0 - v1;	// point on the perp bisector of side 0-1
+//	double v4 = v3 + u1 - u0;
+//
+//	double u5 = u1 + (u2 - u1) * 0.5;	// midpoint of side 1-2
+//	double v5 = v1 + (v2 - v1) * 0.5;
+//
+//	double u6 = u5 + v1 - v2;	// point on the perp bisector of side 1-2
+//	double v6 = v5 + u2 - u1;
+//
+//	double u7 = u0 + (u2 - u0) * 0.5;	// midpoint of side 0-2
+//	double v7 = v0 + (v2 - v0) * 0.5;
+//
+//	double u8 = u7 + v0 - v2;
+//	double v8 = v7 + u2 - u0;
+//
+//	// intersect two bisectors to give a cirumcenter
+//
+//	double xc, yc;
+//	intersect2DLines(u3,v3,u4,v4,u5,v5,u6,v6,xc,yc);
+//	double xc2, yc2;
+//	intersect2DLines(u3,v3,u4,v4,u7,v7,u8,v8,xc2,yc2);
+//	double xc3, yc3;
+//	intersect2DLines(u5,v5,u6,v6,u7,v7,u8,v8,xc3,yc3);
+//
+//
+//
+//
+//	//// get derivitives of each point
+//
+//	//CubitVector du0, du1, du2, dv0, dv1, dv2, du, dv;
+//	//uv_derivitives (u0, v0, du0, dv0);
+//	//uv_derivitives (u1, v1, du1, dv1);
+//	//uv_derivitives (u2, v2, du2, dv2);
+//
+//	//// for now, average derivities first
+//
+//	//du = (du0 + du1 + du2) / 3.0; n
+//	//dv = (dv0 + dv1 + dv2) / 3.0;
+//
+//	//// Calculate the rotation angle to the principal axis
+//
+//	//double alpha = atan2( 2.0 * ( du.x()*dv.x() + du.y()*dv.y() ), (du.length_squared() - dv.length_squared())) * 0.5;
+//
+//	//// Calculate principal derivitives
+//
+//	//double cosa = acos(alpha);
+//	//double sina = asin(alpha);
+//	//CubitVector dup = cosa * du + sina * dv;
+//	//CubitVector dvp = -sina * du + cosa * dv;
+//
+//	////  
+//
+//
+//	return CUBIT_SUCCESS;
+//}
 
-	rv = refSurf->u_v_from_position(xyz_location, u, v);
+
+
+
+//EOF
+
+//- Class: TestParamTool
+//-------------------------------------------------------------------------
+// Filename      : TestParamTool.cpp
+//
+// Purpose       : This is the generic version of ParamTool when the
+//                 geometry engine has a sufficient parameterization.
+//                 It uses the tool's existing functions to get transform
+//                 between uv and xyz spaces.
+//
+// Creator       : Christopher Hynes
+//
+// Creation Date : 7/10/2002
+//
+// Owner         : Christopher Hynes
+//-------------------------------------------------------------------------
+
+#include "CastTo.hpp"
+#include "Surface.hpp"
+#include "DLIList.hpp" 
+
+//-------------------------------------------------------------------------
+// Function:    TestParamTool
+// Description: constructor
+// Author:      chynes
+// Date:        7/10/2002
+//-------------------------------------------------------------------------
+TestParamTool::TestParamTool() 
+{
+
+	//- update private variables
+//	refSurf = surf;
+
+  uRange = 1.0;
+  vRange = 4.0;
+  
+  xMin = -0.5;
+  yMin = -0.5;
+
+  xMax = 0.5;
+  yMax = 0.5;
+
+
+  zDepth = 0.5;  // constant z coordinate of test surface
+
+}
+
+//-------------------------------------------------------------------------
+// Function:    TestParamTool
+// Description: deconstructor
+// Author:      chynes
+// Date:        7/10/2002
+//-------------------------------------------------------------------------
+TestParamTool::~TestParamTool() {}
+
+//===================================================================================
+// Function: set_up_space (Public)
+// Description: sets up space of flattening
+// Author: chynes
+// Date: 7/10/02
+//===================================================================================
+CubitStatus TestParamTool::set_up_space(void)
+{
+	
+	CubitStatus rv = CUBIT_SUCCESS;
+
+	
+	return rv; 
+}
+
+//===================================================================================
+// Function: transform_to_uv (Public)
+// Description: same as title, the local sizing will be returned in the z coord 
+// Author: chynes
+// Date: 7/10/02
+//===================================================================================
+CubitStatus TestParamTool::transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location) 
+{
+  // calculate the u,v from the x,y
+
+  double u = (xyz_location.x()-xMin)/(xMax-xMin) * uRange;
+  double v = (xyz_location.y()-yMin)/(yMax-yMin) * vRange;
 	uv_location.set(u,v,1.0);
 
-	return rv;
+	return CUBIT_SUCCESS;
 }
 
 //===================================================================================
@@ -225,13 +280,22 @@
 // Author: chynes
 // Date: 7/10/02
 //===================================================================================
-CubitStatus SurfParamTool::transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location) 
+CubitStatus TestParamTool::transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location) 
 {
-	xyz_location = refSurf->position_from_u_v(uv_location.x(), uv_location.y());
+  double u = (xyz_location.x()-xMin)/(xMax-xMin) * uRange;
+  // get x,y from u,v
 
+  double x = uv_location.x()/uRange + xMin;
+  double y = uv_location.y()/vRange + yMin;
+
+  xyz_location.set(x,y,zDepth);
+
 	return CUBIT_SUCCESS;
 }
 
-
-
-//EOF
+CubitStatus TestParamTool::uv_derivitives( double u_param, double v_param, CubitVector &du, CubitVector &dv )
+{
+  du.set(1.0/uRange,0,0);
+  dv.set(0,1.0/vRange,0);
+  return CUBIT_SUCCESS;
+}

Modified: cgm/branches/cubit/geom/SurfParamTool.hpp
===================================================================
--- cgm/branches/cubit/geom/SurfParamTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SurfParamTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -24,7 +24,7 @@
 class CubitVector;
 template <class X> class DLIList;
 
-
+//! Transforms between a surface's uv parameter and xyz space. 
 class CUBIT_GEOM_EXPORT SurfParamTool : public ParamTool
 {
 public:
@@ -37,16 +37,64 @@
 	
 	CubitStatus set_up_space(void);
 
-	CubitStatus transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location);
+	CubitStatus transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location);
 
-	CubitStatus transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location);
+	CubitStatus transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location);
 
+	CubitStatus uv_derivitives( double u_param, double v_param, 
+                                    CubitVector &du, CubitVector &dv );
 
+	static CubitStatus circumcenter(double u0, double v0, 
+                                        double u1, double v1,
+                                        double u2, double v2,
+                                        CubitVector &center);  // temp function to be moved elsewhere
+
 private:
 
 	Surface *refSurf;
 	//- reference surface
 };
 
+class Surface;
+class CubitVector;
+template <class X> class DLIList;
+
+//! Transforms between a surface's uv parameter and xyz space. 
+class CUBIT_GEOM_EXPORT TestParamTool : public ParamTool
+{
+public:
+
+	//- constructor
+	TestParamTool();
+
+	//- deconstructor
+	~TestParamTool();
+	
+	CubitStatus set_up_space(void);
+
+	CubitStatus transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location);
+
+	CubitStatus transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location);
+
+	CubitStatus uv_derivitives( double u_param, double v_param, 
+                                    CubitVector &du, CubitVector &dv );
+
+	static CubitStatus circumcenter(double u0, double v0, 
+                                        double u1, double v1,
+                                        double u2, double v2,
+                                        CubitVector &center);  // temp function to be moved elsewhere
+
+private:
+
+//	Surface *refSurf;
+	//- reference surface
+
+  double uRange, vRange;
+  double zDepth;
+
+  double xMin, yMin, xMax, yMax;
+
+};
+
 #endif // ACIS_PARAM_TOOL_HPP
 

Modified: cgm/branches/cubit/geom/Surface.hpp
===================================================================
--- cgm/branches/cubit/geom/Surface.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/Surface.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -35,7 +35,6 @@
 template <class X> class DLIList;
 class ShellSM;
 
-
 class CUBIT_GEOM_EXPORT Surface : public GeometryEntity
 {
    public :
@@ -68,7 +67,10 @@
       //- Only valid for planar surfaces
       //- Finds the underlying plane's origin and normal (unit) vector
       //- Returns CubitFailure if not a plane.
-      
+
+      virtual void param_dir(CubitVector &unit_dir_in_world_space,
+        CubitVector &pos_on_surf, double &du, double &dv){}
+
       virtual CubitStatus closest_point_uv_guess(  
           CubitVector const& location,
           double& u_guess, double& v_guess,
@@ -324,6 +326,11 @@
       //R GeometryType (enum)
       //R- The enumerated type of the geometric representation
 
+      virtual GeometryType is_cylindrical()
+      {return UNDEFINED_SURFACE_TYPE;};
+      //R GeometryType (enum) 
+      //R- CYLINDRICAL_SURFACE_TYPE if true UNDEFINED_SURFACE_TYPE if false
+
       // Now handled at RefFace level.  -- j.k. Oct, 2003
       //virtual void reverse_sense() = 0;
       //- Switch the sense of this Surface wrt the RefFace that owns it.

Modified: cgm/branches/cubit/geom/SurfaceOverlapFacet.cpp
===================================================================
--- cgm/branches/cubit/geom/SurfaceOverlapFacet.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SurfaceOverlapFacet.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -5,7 +5,7 @@
 //- Created: January 26, 2003
 
 #include "SurfaceOverlapFacet.hpp"
-#include "GfxDebug.hpp"
+#include "GfxPreview.hpp"
 
 AnalyticGeometryTool* SurfaceOverlapFacet::agt = AnalyticGeometryTool::instance();
 
@@ -51,6 +51,24 @@
   return agt->MinTriangleTriangle( t, other_facet.t, s, t2, u, v );
 }
 
+CubitBoolean
+SurfaceOverlapFacet::facing( SurfaceOverlapFacet &other_facet )
+{
+    double norm1[3];
+    agt->Normal( t, norm1 );
+    double norm2[3];
+    agt->Normal( other_facet.t, norm2 );
+
+    // move to the origin
+    double o1[3];
+    o1[0] = other_facet.t.b.x-t.b.x;
+    o1[1] = other_facet.t.b.y-t.b.y;
+    o1[2] = other_facet.t.b.z-t.b.z;
+
+    double dot_p = agt->dot_vec(norm1,o1);
+    return (CubitBoolean)(dot_p >= 0.0);
+}
+
 double
 SurfaceOverlapFacet::angle( SurfaceOverlapFacet &other_facet )
 {
@@ -58,9 +76,9 @@
 }
 
 double
-SurfaceOverlapFacet::projected_overlap( SurfaceOverlapFacet &other_facet )
+SurfaceOverlapFacet::projected_overlap( SurfaceOverlapFacet &other_facet, CubitBoolean draw_overlap )
 {
-  double tmp_double = agt->ProjectedOverlap( t, other_facet.t );
+  double tmp_double = agt->ProjectedOverlap( t, other_facet.t, draw_overlap );
 
   if( tmp_double > 0.00 ) 
   {
@@ -98,9 +116,10 @@
                                     t.e1.y + t.b.y, 
                                     t.e1.z + t.b.z );    
 
-  GfxDebug::draw_line( point1, point2, color );
-  GfxDebug::draw_line( point2, point3, color );
-  GfxDebug::draw_line( point1, point3, color );
+  GfxPreview::draw_line( point1, point2, color );
+  GfxPreview::draw_line( point2, point3, color );
+  GfxPreview::draw_line( point1, point3, color );
+  
   return;
 }
 

Modified: cgm/branches/cubit/geom/SurfaceOverlapFacet.hpp
===================================================================
--- cgm/branches/cubit/geom/SurfaceOverlapFacet.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SurfaceOverlapFacet.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -35,8 +35,10 @@
   ~SurfaceOverlapFacet();
   
   double distance( SurfaceOverlapFacet &other_facet );
+  CubitBoolean facing( SurfaceOverlapFacet &other_facet );
   double angle( SurfaceOverlapFacet &other_facet );
-  double projected_overlap( SurfaceOverlapFacet &other_facet );
+  double projected_overlap( SurfaceOverlapFacet &other_facet, 
+                            CubitBoolean draw_overlap = CUBIT_FALSE );
 
   bool bbox_overlap( double tol, SurfaceOverlapFacet &other_facet ) 
   { return boundingBox.overlap( tol, other_facet.boundingBox ); }

Modified: cgm/branches/cubit/geom/SurfaceOverlapTool.cpp
===================================================================
--- cgm/branches/cubit/geom/SurfaceOverlapTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SurfaceOverlapTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -6,9 +6,11 @@
 
 #include "RefEntityFactory.hpp"
 #include "SurfaceOverlapTool.hpp"
+#include "RefVertex.hpp"
 #include "RefEdge.hpp"
 #include "RefFace.hpp"
 #include "Body.hpp"
+#include "CoEdge.hpp"
 #include "BodySM.hpp"
 #include "RefGroup.hpp"
 #include "GeometryModifyTool.hpp"
@@ -30,9 +32,12 @@
 #include "AbstractTree.hpp"
 
 #include "GMem.hpp"
-#include "GfxDebug.hpp"
 #include "SettingHandler.hpp"
 
+#include "GfxPreview.hpp"
+#include "GfxDebug.hpp"
+#include "CpuTimer.hpp"
+
 #define NO_FACETS_FOR_ABSTRACTTREE 10
 
 SurfaceOverlapTool* SurfaceOverlapTool::instance_ = 0;
@@ -50,6 +55,7 @@
 unsigned short SurfaceOverlapTool::facetAngTol = 15; // Seems to work pretty good
 CubitBoolean SurfaceOverlapTool::checkWithinBodies = CUBIT_FALSE;
 CubitBoolean SurfaceOverlapTool::checkAcrossBodies = CUBIT_TRUE;
+bool SurfaceOverlapTool::skipFacingSurfaces = CUBIT_FALSE; // skip the pair if the normals pass through eachother (normalType must == 2)
 
 // Constructor
 SurfaceOverlapTool* SurfaceOverlapTool::instance()
@@ -75,6 +81,7 @@
   imprintResults = CUBIT_FALSE;
   checkWithinBodies = CUBIT_FALSE;
   checkAcrossBodies = CUBIT_TRUE;
+  skipFacingSurfaces = CUBIT_FALSE;
 }
 
 // Destructor
@@ -83,82 +90,108 @@
    delete instance_;
 }
 
+CubitBoolean SurfaceOverlapTool::draw_overlapping_surface_pair( RefFace *ref_face_1,
+                                                        RefFace *ref_face_2)
+{
+  CubitBoolean abort = CUBIT_FALSE;
+  CubitBoolean draw_overlap = CUBIT_TRUE;
+  CubitBoolean overlap = check_overlap( ref_face_1, ref_face_2, 
+                                        abort, draw_overlap );
+
+  return overlap;
+}
+
 CubitStatus 
 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list, 
-                                               DLIList<RefEntity*> &faces_to_draw )
+                                               DLIList<RefEntity*> &faces_to_draw,
+                                               bool filter_slivers)
 {
    DLIList<RefFace*> list1, list2;
-   return find_overlapping_surfaces( ref_face_list, list1, list2, faces_to_draw, CUBIT_TRUE );
+   return find_overlapping_surfaces( ref_face_list, list1, list2, faces_to_draw, CUBIT_TRUE,
+     filter_slivers);
 }
 
 CubitStatus
 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<Body*> &body_list,
-                                               DLIList<RefEntity*> &faces_to_draw )
+                                               DLIList<RefEntity*> &faces_to_draw,
+                                               bool filter_slivers)
 {
   DLIList<RefFace*> list1, list2;
-  return find_overlapping_surfaces( body_list, list1, list2, faces_to_draw, CUBIT_TRUE );
+  return find_overlapping_surfaces( body_list, list1, list2, faces_to_draw, CUBIT_TRUE,
+    filter_slivers);
 }
 
+
 CubitStatus
 SurfaceOverlapTool::find_overlapping_surfaces( DLIList<BodySM*> &body_list,
                                               DLIList<Surface*> &surface_list1,
-                                              DLIList<Surface*> &surface_list2)
+                                              DLIList<Surface*> &surface_list2,
+                                              bool filter_slivers)
 {
-  int i,j;
-  DLIList<BodySM*> tmp_body_list = body_list;
+  //collect all the surfaces
+  DLIList<Surface*> surface_list;
+  int i;
+  for( i=body_list.size(); i--; )
+  {
+    BodySM *body_sm = body_list.get_and_step();
+    DLIList<Surface*> surfs;
+    body_sm->surfaces_ignore_virtual( surfs, false );
+//    body_sm->surfaces( surfs );
+    surface_list.merge_unique( surfs );
+  }
+
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  // Populate the Surface AbstractTree
+  AbstractTree<Surface*> *a_tree = new RTree<Surface*>( tolerance );
+  surface_list.reset();
+  for( i=surface_list.size(); i--; )
+  {
+    Surface *surface = surface_list.get_and_step();
+    a_tree->add( surface );
+  }
+
+  std::map<Surface*, DLIList<SurfaceOverlapFacet*>* > surface_facet_map;
   std::map<Surface*, double > surface_to_area_map;
-  std::map<Surface*, DLIList<SurfaceOverlapFacet*>* > surface_facet_map;
   std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* > a_tree_map;
-  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
 
-  for(i=tmp_body_list.size(); i--; )
+  surface_list.reset();
+  for( i=surface_list.size(); i--; )
   {
-    BodySM *tmp_body1 = tmp_body_list.pop();
-    CubitBox body_box1 = tmp_body1->bounding_box();
+    Surface *surf1 = surface_list.get_and_step();
 
-    tmp_body_list.reset();
-    for(j=tmp_body_list.size(); j--; )
-    {
-      BodySM *tmp_body2 = tmp_body_list.get_and_step();
+    BodySM *surf1_body = surf1->bodysm();
 
-      //determine if bodies are close enough to have overlapping curves
-      CubitBox body_box2 = tmp_body2->bounding_box();
+    // Remove this surface from AbstractTree so it is not found and never
+    // found again
+    a_tree->remove( surf1 );
 
-      if( body_box1.overlap( tolerance, body_box2 ) )
-      {
-        //check individual surfaces for bounding box interference
-        DLIList<Surface*> surfaces1, surfaces2;
-        tmp_body1->surfaces( surfaces1 );
-        tmp_body2->surfaces( surfaces2 );
-        
-        int ii;
-        for( ii=surfaces1.size(); ii--; )
-        {
-          Surface *surface1 = surfaces1.get_and_step();
+    // Find RefFaces from AbstractTree that are within range of this surface
+    CubitBox surf1_box = surf1->bounding_box();
+    DLIList<Surface*> close_surfaces;
+    a_tree->find( surf1_box, close_surfaces );
 
-          CubitBox surf1_bbox = surface1->bounding_box();
+    int j;
+    for( j=close_surfaces.size(); j--; )
+    {
+      Surface *surf2 = close_surfaces.get_and_step();
+      BodySM *surf2_body = surf2->bodysm();
 
-          int jj;
-          for( jj=surfaces2.size(); jj--; )
-          {
-            Surface *surface2 = surfaces2.get_and_step();
-            CubitBox surf2_bbox = surface2->bounding_box();
+      //don't check for overlapping surfaces within bodies
+      if( surf1_body == surf2_body )
+        continue;
 
-            if( surf1_bbox.overlap( tolerance, surf2_bbox ) == CUBIT_FALSE )
-              continue;
-
-            if( check_overlap( surface1, surface2, 
-                &surface_facet_map, &surface_to_area_map, &a_tree_map ) == CUBIT_TRUE )
-            {
-              surface_list1.append( surface1 );
-              surface_list2.append( surface2 );
-            }
-          }
-        }
+      if( check_overlap( surf1, surf2, 
+                         &surface_facet_map, 
+                         &surface_to_area_map, 
+                         &a_tree_map  ) == CUBIT_TRUE )
+      {
+        surface_list1.append( surf1 );
+        surface_list2.append( surf2 );
       }
     }
   }
-  
+
   //clean up maps;
   std::map<Surface*, AbstractTree<SurfaceOverlapFacet*>* >::iterator tree_iter; 
   tree_iter = a_tree_map.begin();
@@ -178,7 +211,9 @@
     //delete the list
     delete tmp_list;
   }
-  
+
+  delete a_tree;
+
   return CUBIT_SUCCESS;
 }
 
@@ -187,7 +222,8 @@
                                               DLIList<RefFace*> &ref_face_list1,
                                               DLIList<RefFace*> &ref_face_list2,
                                               DLIList<RefEntity*> &faces_to_draw,
-                                              CubitBoolean show_messages )
+                                              CubitBoolean show_messages,
+                                              bool filter_slivers)
 {
   CubitStatus status = CUBIT_SUCCESS;
 
@@ -239,7 +275,7 @@
     }
 
     status = find_overlapping_surfaces( ref_face_list, ref_face_list1,
-      ref_face_list2, faces_to_draw, list_pairs, prog_step );
+      ref_face_list2, faces_to_draw, list_pairs, prog_step, filter_slivers );
 
     if( show_messages && ref_face_list.size() > prog_step )
       AppUtil::instance()->progress_tool()->end();
@@ -270,7 +306,7 @@
       body_ptr->ref_faces( body_face_list );
 
       status = find_overlapping_surfaces( body_face_list, ref_face_list1,
-        ref_face_list2, faces_to_draw, list_pairs, -1 );
+        ref_face_list2, faces_to_draw, list_pairs, -1, filter_slivers );
 
       if( show_messages && body_list.size() > prog_step )
         AppUtil::instance()->progress_tool()->step();
@@ -316,7 +352,8 @@
                                               DLIList<RefFace*> &ref_face_list1,
                                               DLIList<RefFace*> &ref_face_list2,
                                               DLIList<RefEntity*> &faces_to_draw,
-                                              CubitBoolean show_messages)
+                                              CubitBoolean show_messages, 
+                                              bool filter_slivers)
 {
   CubitStatus status = CUBIT_SUCCESS;
 
@@ -350,7 +387,7 @@
     prog_step = -1;
 
   status = find_overlapping_surfaces( ref_face_list, ref_face_list1,
-    ref_face_list2, faces_to_draw, list_pairs, prog_step );
+    ref_face_list2, faces_to_draw, list_pairs, prog_step, filter_slivers );
 
   if( show_messages && ref_face_list.size() > prog_step )
     AppUtil::instance()->progress_tool()->end();
@@ -389,7 +426,8 @@
                                               DLIList<RefFace*> &ref_face_list2,
                                               DLIList<RefEntity*> &pair_list,
                                               CubitBoolean list_pairs,
-                                              int prog_step )
+                                              int prog_step,
+                                              bool filter_slivers)
 {
   int number_pairs = 0;
   CubitBoolean abort = CUBIT_FALSE;
@@ -442,8 +480,75 @@
 
       ref_face_ptr2 = close_ref_faces.get_and_step();
 
-      if( check_overlap( ref_face_ptr1, ref_face_ptr2, abort ) == CUBIT_TRUE )
+      bool overlap = check_overlap( ref_face_ptr1, ref_face_ptr2, abort );
+      if(overlap == CUBIT_TRUE && filter_slivers)
       {
+        RefFace *f1, *f2;
+        DLIList<RefEdge*> f1_edges, f2_edges, *f1_edge_list, *f2_edge_list;
+        ref_face_ptr1->ref_edges(f1_edges);
+        ref_face_ptr2->ref_edges(f2_edges);
+        if(f1_edges.size() > f2_edges.size())
+        {
+          f1 = ref_face_ptr2;
+          f2 = ref_face_ptr1;
+          f1_edge_list = &f2_edges;
+          f2_edge_list = &f1_edges;
+        }
+        else
+        {
+          f1 = ref_face_ptr1;
+          f2 = ref_face_ptr2;
+          f1_edge_list = &f1_edges;
+          f2_edge_list = &f2_edges;
+        }
+        int b;
+        for(b=f1_edge_list->size(); b>0 && overlap; b--)
+        {
+          RefEdge *cur_edge = f1_edge_list->get_and_step();
+          if(cur_edge->is_merged())
+          {
+            DLIList<RefFace*> face_list;
+            cur_edge->ref_faces(face_list);
+            if(face_list.is_in_list(f2))
+            {
+              CubitVector mid_pt;
+              cur_edge->mid_point(mid_pt);
+              CubitVector f1_norm = f1->normal_at(mid_pt); 
+              CubitVector f2_norm = f2->normal_at(mid_pt); 
+              DLIList<CoEdge*> f1_coedges, f2_coedges;
+              cur_edge->get_co_edges(f1_coedges, f1);
+              cur_edge->get_co_edges(f2_coedges, f2);
+              if(f1_coedges.size() == 1 && f2_coedges.size() == 1)
+              {
+                CoEdge *ce1 = f1_coedges.get();
+                CoEdge *ce2 = f2_coedges.get();
+                CubitVector curve_dir;
+
+                if( cur_edge->get_curve_ptr()->geometry_type() == STRAIGHT_CURVE_TYPE )
+                  cur_edge->get_point_direction(mid_pt, curve_dir);
+                else
+                  cur_edge->tangent( mid_pt, curve_dir );
+
+                CubitVector ce1_dir, ce2_dir;
+                if(ce1->get_sense() == CUBIT_REVERSED)
+                  ce1_dir = -curve_dir;
+                else
+                  ce1_dir = curve_dir;
+                if(ce2->get_sense() == CUBIT_REVERSED)
+                  ce2_dir = -curve_dir;
+                else
+                  ce2_dir = curve_dir;
+                CubitVector in_dir1 = f1_norm * ce1_dir;
+                CubitVector in_dir2 = f2_norm * ce2_dir;
+                if(in_dir1 % in_dir2 < 0.0)
+                  overlap = false;
+              }
+            }
+          }
+        }
+      }
+      if(overlap)
+      {
         if( abort == CUBIT_TRUE )
           goto done;
 
@@ -521,8 +626,6 @@
 
   if( facet_map == NULL || facet_iterator == facet_map->end() )
   {
-    int junk1, junk2, junk3;
-
     //for non-planar surfaces, facet wrt the smallest curve of the surface 
     double min_edge_length = 0.0;
 
@@ -538,7 +641,7 @@
       {
         min_edge_length = CUBIT_DBL_MAX; 
         double tmp_length; 
-        for( junk1=tmp_curves.size(); junk1--; )
+        for( i=tmp_curves.size(); i--; )
         {
           tmp_length = tmp_curves.get_and_step()->measure();
           if( tmp_length > min_length_threshold && tmp_length < min_edge_length )
@@ -553,8 +656,7 @@
 
     facet_list1 = new DLIList<SurfaceOverlapFacet*>;
     GMem surface_graphics;
-    surface1->get_geometry_query_engine()->get_graphics( surface1, junk1,
-                                junk2, junk3, &surface_graphics, 
+    surface1->get_geometry_query_engine()->get_graphics( surface1, &surface_graphics, 
                                 facetAngTol, facetAbsTol, min_edge_length );   
 
     GPoint* plist = surface_graphics.point_list();
@@ -594,8 +696,6 @@
 
   if( facet_map == NULL || facet_iterator == facet_map->end() )
   {
-    int junk1, junk2, junk3;
-
     //for non-planar surfaces, facet wrt the smallest curve of the surface 
     double min_edge_length = 0.0;
 
@@ -611,7 +711,7 @@
       {
         min_edge_length = CUBIT_DBL_MAX; 
         double tmp_length; 
-        for( junk1=tmp_curves.size(); junk1--; )
+        for( i=tmp_curves.size(); i--; )
         {
           tmp_length = tmp_curves.get_and_step()->measure();
           if( tmp_length > min_length_threshold && tmp_length < min_edge_length )
@@ -626,8 +726,7 @@
 
     facet_list2 = new DLIList<SurfaceOverlapFacet*>;
     GMem surface_graphics;
-    surface2->get_geometry_query_engine()->get_graphics( surface2, junk1,
-                                junk2, junk3, &surface_graphics, 
+    surface2->get_geometry_query_engine()->get_graphics( surface2, &surface_graphics, 
                                 facetAngTol, facetAbsTol, min_edge_length );
 
     GPoint* plist = surface_graphics.point_list();
@@ -742,50 +841,50 @@
   if( area_map )
   {
     std::map<Surface*, double>::iterator area_iter;
-    area_iter = area_map->find( surface1 );
+    area_iter = area_map->find( tmp_surf1);
     if( area_iter == area_map->end() )
     {
-      face1_area = surface1->measure();
-      area_map->insert( std::map<Surface*, double>::value_type( surface1, face1_area ) ); 
+      face1_area = tmp_surf1->measure();
+      area_map->insert( std::map<Surface*, double>::value_type( tmp_surf1, face1_area ) ); 
     }
     else
       face1_area = area_iter->second; 
 
-    area_iter = area_map->find( surface2 );
+    area_iter = area_map->find( tmp_surf2);
     if( area_iter == area_map->end() )
     {
-      face2_area = surface2->measure();
-      area_map->insert( std::map<Surface*, double>::value_type( surface2, face2_area )); 
+      face2_area = tmp_surf2->measure();
+      area_map->insert( std::map<Surface*, double>::value_type( tmp_surf2, face2_area )); 
     }
     else
       face2_area = area_iter->second; 
   }
   else
   {
-    face1_area = surface1->measure();
-    face2_area = surface2->measure();
+    face1_area = tmp_surf1->measure();
+    face2_area = tmp_surf2->measure();
   }
 
   bool sample_deviation = false; 
   Surface *larger_surface = NULL;
   //if the surfaces are non planar and one is much bigger than the other one...
   //adjust the tolerance some
-  if( (surface1->geometry_type() != PLANE_SURFACE_TYPE  &&
-       surface2->geometry_type() != PLANE_SURFACE_TYPE) )
+  if( (tmp_surf1->geometry_type() != PLANE_SURFACE_TYPE  &&
+       tmp_surf2->geometry_type() != PLANE_SURFACE_TYPE) )
   {
-    double length1 = surface1->bounding_box().diagonal().length();
-    double length2 = surface2->bounding_box().diagonal().length();
+    double length1 = tmp_surf1->bounding_box().diagonal().length();
+    double length2 = tmp_surf2->bounding_box().diagonal().length();
     
     double ratio = 0;
     if(length1 > length2)
     {
       ratio = length1/length2;
-      larger_surface = surface1;
+      larger_surface = tmp_surf1;
     }
     else
     {
       ratio = length2/length1;
-      larger_surface = surface2;
+      larger_surface = tmp_surf2;
     }
    
     if( ratio > 50 )
@@ -809,7 +908,7 @@
   if( sample_deviation )
   {
     DLIList<SurfaceOverlapFacet*> *tmp_facet_list = NULL;
-    if( larger_surface == surface1 )
+    if( larger_surface == tmp_surf1 )
       tmp_facet_list = facet_list1;
     else
       tmp_facet_list = facet_list2;
@@ -818,8 +917,10 @@
     for( i=tmp_facet_list->size(); i--; )
     {
       SurfaceOverlapFacet *tmp_facet = tmp_facet_list->get_and_step();
-      if( (i%7) == 0)
-      {
+        //we used to be lucky, where one seventh of the facets would give us a 
+        //decent tolerance...this doesn't work now....not robust enough
+//      if( (i%7) == 0)  // commenting this out....sometimes you haveto 
+//      {
         CubitVector point = tmp_facet->smallest_edge_midpoint(); 
         //determine distance between surface and centroid 
 
@@ -827,8 +928,10 @@
         larger_surface->closest_point_trimmed( point, tmp_point );  
         double tmp_distance = point.distance_between( tmp_point ); 
         if( tmp_distance > facet_compare_tol )
+        {
           facet_compare_tol = tmp_distance;
-      }
+        }
+//      }
     }
   }
   else
@@ -845,6 +948,11 @@
       facet_compare_tol *= 0.0025;
     }
   }
+  
+  //if the merge tolerance is a larger, use it
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+  if( tolerance > facet_compare_tol )
+    facet_compare_tol = tolerance;
 
   facet_list1->reset();
   for( i=facet_list1->size(); i--; )
@@ -871,22 +979,107 @@
       
       // normalType - 1=any, 2=opposite, 3=same
       //ang>=180.0-angt || ang<angt
-      if( (normalType==1 && ang>=opp_low && ang<=opp_high) ||
+      if( ((normalType==1 && ang>=opp_low && ang<=opp_high) ||
+          (normalType==1 && ang>=angleMin && ang<=angleMax) ||
+          (normalType==2 && ang>=opp_low && ang<=opp_high) ||
+          (normalType==3 && ang>=angleMin && ang<=angleMax)) && 
+          (normalType != 2 || !skipFacingSurfaces || !facet1->facing( *facet2 )))// check to make sure the surfaces are not facing 
+      {
+          // If triangle bounding boxes don't intersect - no overlap
+          if( facet1->bbox_overlap( facet_compare_tol, *facet2 ) )
+          {
+              // Check distance between triangles, must be within criteria
+              double dist = facet1->distance( *facet2 );
+              if( dist >= gapMin && dist <= facet_compare_tol )
+              {
+                  // Check for projected overlap
+                  // We want sum of area of ALL overlapping facets
+                  area += facet1->projected_overlap( *facet2 );
+                  if( area > tmp_overlapTolerance )
+                  {
+                      return CUBIT_TRUE;
+                  }                
+              }
+          }
+      }
+    }
+  }
+
+  return CUBIT_FALSE;
+}
+
+CubitBoolean 
+SurfaceOverlapTool::check_overlap( DLIList<SurfaceOverlapFacet*> *facet_list1,
+                                   DLIList<SurfaceOverlapFacet*> *facet_list2,
+                                   AbstractTree<SurfaceOverlapFacet*> *a_tree, 
+                                   CubitBoolean abort, 
+                                   CubitBoolean draw_overlap,
+                                   double *overlap_area ) 
+{
+  double area = 0;
+  double opp_low = 180.0 - angleMax;
+  double opp_high = 180.0 - angleMin;
+
+  facet_list1->reset();
+  int num_tri1 = facet_list1->size();
+  int i,j;
+  for( i=num_tri1; i--; )
+  {
+    // Cancel button pushed or cntrl-C
+    if (CubitMessage::instance()->Interrupt()) 
+    {
+      PRINT_INFO("Find overlap operation aborted.\n");
+      abort = CUBIT_TRUE;
+      return CUBIT_FALSE;
+    }
+
+    SurfaceOverlapFacet *facet1 = facet_list1->get_and_step();
+
+    DLIList<SurfaceOverlapFacet*> close_facets;
+    if( a_tree )
+    {
+      a_tree->find( facet1->bounding_box(), close_facets );
+      facet_list2 = &close_facets;
+    }
+    
+    facet_list2->reset();
+    for( j=facet_list2->size(); j--; )
+    {
+      // Cancel button pushed or cntrl-C
+      if (CubitMessage::instance()->Interrupt()) 
+      {
+        PRINT_INFO("Find overlap operation aborted.\n");
+        abort = CUBIT_TRUE;
+        return CUBIT_FALSE;
+      }
+
+      SurfaceOverlapFacet *facet2 = facet_list2->get_and_step();
+      
+      // Check angle between triangles, must be within criteria
+      double ang = facet1->angle( *facet2 ); 
+
+      // Allow overlap for angles close to 180 and 0 degrees
+      
+      // normalType - 1=any, 2=opposite, 3=same
+      //ang>=180.0-angt || ang<angt
+      if( ((normalType==1 && ang>=opp_low && ang<=opp_high) ||
         (normalType==1 && ang>=angleMin && ang<=angleMax) ||
         (normalType==2 && ang>=opp_low && ang<=opp_high) ||
-        (normalType==3 && ang>=angleMin && ang<=angleMax) )
+        (normalType==3 && ang>=angleMin && ang<=angleMax) ) &&
+        (normalType != 2 || !skipFacingSurfaces || !facet1->facing( *facet2 )))// check to make sure the surfaces are not facing )
       {
         // If triangle bounding boxes don't intersect - no overlap
-        if( facet1->bbox_overlap( facet_compare_tol, *facet2 ) )
+        if( facet1->bbox_overlap( gapMax, *facet2 ) )
         {
           // Check distance between triangles, must be within criteria
           double dist = facet1->distance( *facet2 );
-          if( dist >= gapMin && dist <= facet_compare_tol )
+          if( dist >= gapMin && dist <= gapMax )
           {
             // Check for projected overlap
             // We want sum of area of ALL overlapping facets
-            area += facet1->projected_overlap( *facet2 );
-            if( area > tmp_overlapTolerance )
+            area += facet1->projected_overlap( *facet2, draw_overlap );
+            if( area > overlapTolerance &&
+               (draw_overlap == CUBIT_FALSE && overlap_area == NULL ) )
             {
               return CUBIT_TRUE;
             }                
@@ -894,14 +1087,32 @@
         }
       }
     }
+  }  
+  if( draw_overlap == CUBIT_TRUE ) 
+  {
+    PRINT_INFO("Total overlapping area = %lf\n", area );
+
+    if( area > 0.0 )
+      return CUBIT_TRUE;
   }
+
+  if( overlap_area )
+  {
+    if( area > 0.0 )
+    {
+      *overlap_area = area;
+      return CUBIT_TRUE;
+    }
+  }
+
   return CUBIT_FALSE;
 }
 
-
 CubitBoolean
 SurfaceOverlapTool::check_overlap( RefFace *ref_face_ptr1, RefFace *ref_face_ptr2, 
-                                   CubitBoolean abort )
+                                   CubitBoolean abort, 
+                                   CubitBoolean draw_overlap,
+                                   double *overlap_area ) 
 {
   if( ref_face_ptr1 == ref_face_ptr2 )
     return CUBIT_FALSE;
@@ -913,12 +1124,9 @@
       (ref_face_ptr1->get_surface_ptr()->geometry_type() != 
        ref_face_ptr2->get_surface_ptr()->geometry_type() )) 
     return CUBIT_FALSE;
-
-  int i, j;
+ 
   AnalyticGeometryTool::instance();
   abort = CUBIT_FALSE;
-  double opp_low = 180.0 - angleMax;
-  double opp_high = 180.0 - angleMin;
 
   // Check for overlap between the found surfaces using the facets
   TDSurfaceOverlap *tdso_1;
@@ -1017,79 +1225,13 @@
     a_tree = tdso_2->get_facet_rtree();
   }
 
-  double area = 0;
+  bool surfs_overlap = check_overlap( facet_list1, facet_list2, a_tree,
+                                      abort, draw_overlap, overlap_area );
 
-  facet_list1->reset();
-  num_tri1 = facet_list1->size();
-  for( i=num_tri1; i--; )
-  {
-    // Cancel button pushed or cntrl-C
-    if (CubitMessage::instance()->Interrupt()) 
-    {
-      PRINT_INFO("Find overlap operation aborted.\n");
-      abort = CUBIT_TRUE;
-      return CUBIT_FALSE;
-    }
-
-    SurfaceOverlapFacet *facet1 = facet_list1->get_and_step();
-
-    DLIList<SurfaceOverlapFacet*> close_facets;
-    if( a_tree )
-    {
-      a_tree->find( facet1->bounding_box(), close_facets );
-      facet_list2 = &close_facets;
-    }
-    
-    facet_list2->reset();
-    for( j=facet_list2->size(); j--; )
-    {
-      // Cancel button pushed or cntrl-C
-      if (CubitMessage::instance()->Interrupt()) 
-      {
-        PRINT_INFO("Find overlap operation aborted.\n");
-        abort = CUBIT_TRUE;
-        return CUBIT_FALSE;
-      }
-
-      SurfaceOverlapFacet *facet2 = facet_list2->get_and_step();
-      
-      // Check angle between triangles, must be within criteria
-      double ang = facet1->angle( *facet2 ); 
-
-      // Allow overlap for angles close to 180 and 0 degrees
-      
-      // normalType - 1=any, 2=opposite, 3=same
-      //ang>=180.0-angt || ang<angt
-      if( (normalType==1 && ang>=opp_low && ang<=opp_high) ||
-        (normalType==1 && ang>=angleMin && ang<=angleMax) ||
-        (normalType==2 && ang>=opp_low && ang<=opp_high) ||
-        (normalType==3 && ang>=angleMin && ang<=angleMax) )
-      {
-        // If triangle bounding boxes don't intersect - no overlap
-        if( facet1->bbox_overlap( gapMax, *facet2 ) )
-        {
-          // Check distance between triangles, must be within criteria
-          double dist = facet1->distance( *facet2 );
-          if( dist >= gapMin && dist <= gapMax )
-          {
-            // Check for projected overlap
-            // We want sum of area of ALL overlapping facets
-            area += facet1->projected_overlap( *facet2 );
-            if( area > overlapTolerance )
-            {
-              return CUBIT_TRUE;
-            }                
-          }
-        }
-      }
-    }
-  }  
-  return CUBIT_FALSE;
+  return surfs_overlap;
 }
 
-
-void
-SurfaceOverlapTool::list_settings()
+void SurfaceOverlapTool::list_settings()
 {
   char on_off[2][4];
   strcpy( on_off[0], "Off" );
@@ -1477,73 +1619,81 @@
   return CUBIT_SUCCESS;
 }
 
-CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<BodySM*> &bodies,
+CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<Curve*> &curve_list,
                                 DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
-                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map)
+                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                std::multimap<BodySM*, CubitVector> &body_point_imprint_map)
 {
+  int i;
+
+  //put all the curves into a tree 
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  // Populate the Surface AbstractTree
+  AbstractTree<Curve*> *a_tree = new RTree<Curve*>( tolerance );
+  curve_list.reset();
+  for( i=curve_list.size(); i--; )
+  {
+    Curve *curve = curve_list.get_and_step();
+    a_tree->add( curve );
+  }
+
   std::map<Curve*, DLIList<CurveOverlapFacet*>* > facet_map;
   std::map<Curve*, DLIList<Curve*>* >::iterator list_iter; 
-  
-  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
 
-  int i,j;
-  bodies.reset();
-  DLIList<BodySM*> tmp_body_list = bodies;
-  for(i=tmp_body_list.size(); i--; )
+  curve_list.reset();
+  for( i=curve_list.size(); i--; )
   {
-    BodySM *tmp_body1 = tmp_body_list.pop();
-    CubitBox body_box1 = tmp_body1->bounding_box();
+    Curve *curve1= curve_list.get_and_step();
 
-    tmp_body_list.reset();
-    for(j=tmp_body_list.size(); j--; )
+    BodySM *curve1_body = curve1->bodysm();
+
+    // Remove this surface from AbstractTree so it is not found and never
+    // found again
+    a_tree->remove( curve1 );
+
+    // Find RefFaces from AbstractTree that are within range of this surface
+    CubitBox curve1_box = curve1->bounding_box();
+    DLIList<Curve*> close_curves;
+    a_tree->find( curve1_box, close_curves );
+
+    int j;
+    for( j=close_curves.size(); j--; )
     {
-      BodySM *tmp_body2 = tmp_body_list.get_and_step();
-
-      if( tmp_body2 == tmp_body1 )
+      Curve *curve2 = close_curves.get_and_step();
+      BodySM *curve2_body = curve2->bodysm();
+      
+      if( curve2_body == curve1_body )
         continue;
 
-      //determine if bodies are close enough to have overlapping curves
-      CubitBox body_box2 = tmp_body2->bounding_box();
-      int ii, jj;
+      std::multimap<BodySM*, CubitVector> tmp_body_point_imprint_map;
 
-      if( body_box1.overlap( tolerance, body_box2 ) )
+      if( check_overlap( curve1, curve2, &facet_map, &tmp_body_point_imprint_map  ) ) 
       {
-        //check individual curves for bounding box interference
-        DLIList<Curve*> curves1, curves2;
-        tmp_body1->curves( curves1 );
-        tmp_body2->curves( curves2 );
-       
-        for( ii=curves1.size(); ii--; )
+        //check to see if the curve1 is already overlapping with another curve 
+        list_iter = curve_to_list_map.find( curve1 );
+        if( list_iter != curve_to_list_map.end() )
         {
-          Curve *curve1 = curves1.get_and_step(); 
-
-          for( jj=curves2.size(); jj--; )
-          {
-            Curve *curve2 = curves2.get_and_step();
-           
-            if( check_overlap( curve1, curve2, &facet_map ) ) 
-            {
-              //check to see if the curve1 is already overlapping with another edge
-              list_iter = curve_to_list_map.find( curve1 );
-              if( list_iter != curve_to_list_map.end() )
-              {
-                DLIList<Curve*> *curve_list = list_iter->second;
-                curve_list->append( curve2 );
-              }
-              else
-              {
-                //list for curve 1 does not exist....make a new one
-                DLIList<Curve*> *curve_list = new DLIList<Curve*>;
-                overlapping_curve_lists.append( curve_list );
-                curve_list->append( curve1 );
-                curve_list->append( curve2 );
-                curve_to_list_map.insert( std::map<Curve*,
-                     DLIList<Curve*>*>::value_type( curve1, curve_list ));
-              }
-            }
-          }
+          DLIList<Curve*> *tmp_curve_list = list_iter->second;
+          tmp_curve_list->append( curve2 );
         }
+        else
+        {
+          //list for curve 1 does not exist....make a new one
+          DLIList<Curve*> *tmp_curve_list = new DLIList<Curve*>;
+          overlapping_curve_lists.append( tmp_curve_list );
+          tmp_curve_list->append( curve1 );
+          tmp_curve_list->append( curve2 );
+          curve_to_list_map.insert( std::map<Curve*,
+               DLIList<Curve*>*>::value_type( curve1, tmp_curve_list ));
+        }
       }
+      else
+      {
+        //append what's in body_point_imprint_map to one passed in
+        body_point_imprint_map.insert( tmp_body_point_imprint_map.begin(), 
+                                       tmp_body_point_imprint_map.end() ); 
+      }
     }
   }
 
@@ -1560,16 +1710,63 @@
     delete co_facet_list;
   }
 
+  delete a_tree;
+
   return CUBIT_SUCCESS;
 }
 
+CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<Surface*> &surf_list,
+                                DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
+                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                std::multimap<BodySM*, CubitVector> &body_point_imprint_map)
+{
+  //collect all the surfaces
+  DLIList<Curve*> curve_list;
+  int i;
+  for( i=surf_list.size(); i--; )
+  {
+    Surface *surf = surf_list.get_and_step();
+    DLIList<Curve*> curves;
+    surf->curves_ignore_virtual(curves, false);
+//    body_sm->curves( curves);
+    curve_list.merge_unique( curves );
+  }
+
+  return find_overlapping_curves(curve_list, overlapping_curve_lists, curve_to_list_map,
+    body_point_imprint_map);
+}
+
+CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<BodySM*> &body_list,
+                                DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
+                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                std::multimap<BodySM*, CubitVector> &body_point_imprint_map )
+{
+  //collect all the surfaces
+  DLIList<Curve*> curve_list;
+  int i;
+  for( i=body_list.size(); i--; )
+  {
+    BodySM *body_sm = body_list.get_and_step();
+    DLIList<Curve*> curves;
+    body_sm->curves_ignore_virtual(curves, false);
+//    body_sm->curves( curves);
+    curve_list.merge_unique( curves );
+  }
+
+  return find_overlapping_curves(curve_list, overlapping_curve_lists, curve_to_list_map,
+    body_point_imprint_map);
+
+}
+
 CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<Body*> &bodies,
-                                std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map )
+                                std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
+                                double maxgap /* =-1*/)
 {
-  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > facet_map; 
   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator list_iter; 
 
   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+  if (maxgap != -1 && maxgap != 0.0)
+      tolerance = maxgap;
 
   int i,j;
   DLIList<Body*> tmp_body_list = bodies;
@@ -1588,55 +1785,172 @@
 
       if( body_box1.overlap( tolerance, body_box2 ) )
       {
-        //check individual curves for bounding box interference
+        // create list of edges on each body.
+	    // put the edges in body2 in edges1 so edges1 contains
+		// the list of curves contained in the body listed first in the list
         DLIList<RefEdge*> edges1, edges2;
-        tmp_body1->ref_edges( edges1 );
-        tmp_body2->ref_edges( edges2 );
-       
-        int ii;
-        for( ii=edges1.size(); ii--; )
-        {
-          RefEdge *edge1 = edges1.get_and_step(); 
+        tmp_body1->ref_edges( edges2 );
+        tmp_body2->ref_edges( edges1 );
+		
+		//check individual curves for bounding box interference
+        if (!find_overlapping_curves(edges1, edges2, overlapping_edge_map, tolerance))
+			return CUBIT_FAILURE;
+      }
+    }
+  }
 
-          int jj;
-          for( jj=edges2.size(); jj--; )
-          {
-            RefEdge *edge2 = edges2.get_and_step();
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<RefFace*> &faces,
+                        std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
+                        double maxgap /*=-1*/)
+{
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  if (maxgap != -1 && maxgap != 0.0)
+      tolerance = maxgap;
+
+  // Populate the Surface AbstractTree
+  AbstractTree<RefFace*> *a_tree = new RTree<RefFace*>( tolerance );
+  faces.reset();
+  int i;
+  for( i=faces.size(); i--; )
+  {
+    RefFace* face = faces.get_and_step();
+    a_tree->add( face );
+  }
+
+  faces.reset();
+  for( i=faces.size(); i--; )
+  {
+    RefFace* face1 = faces.get_and_step();
+
+    Body *face1_body = face1->body();
+
+    // Remove this face from AbstractTree so it is not found and never
+    // found again
+    a_tree->remove( face1 );
+
+    // Find RefFaces from AbstractTree that are within range of this surface
+    CubitBox face1_box = face1->bounding_box();
+    DLIList<RefFace*> close_faces;
+    a_tree->find( face1_box, close_faces );
+
+    int j;
+    for( j=close_faces.size(); j--; )
+    {
+      RefFace *face2 = close_faces.get_and_step();
+      Body *face2_body = face2->body();
+
+      //don't check for overlapping faces within bodies
+      if( face1_body == face2_body )
+              continue;
+
+      DLIList<RefEdge*> edges1, edges2;
+      face1->ref_edges( edges1 );
+      face2->ref_edges( edges2 );
+
+      if (!find_overlapping_curves(edges1, edges2, overlapping_edge_map, tolerance))
+              return CUBIT_FAILURE;
             
-            if( check_overlap( edge1, edge2, &facet_map ) ) 
-            {
-               overlapping_edge_map.insert( std::multimap<RefEdge*, RefEdge*>
-                    ::value_type( edge1, edge2));
-            }
-          }
-        }
+    }
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<RefEdge*> &edgelist,
+				std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map, double maxgap /*=-1*/ )
+{
+  // for now, check every edge against every other edge
+  // (the helper function will skip edges if they are in the same body)
+
+  DLIList<RefEdge*> edgelist2 = edgelist;
+  return find_overlapping_curves(edgelist, edgelist2, overlapping_edge_map, maxgap);
+}
+
+CubitStatus SurfaceOverlapTool::find_overlapping_curves( DLIList<RefEdge*> &edges1, DLIList<RefEdge*> &edges2,
+                                              std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
+                                              double maxgap /*=-1*/)
+{
+  int i;
+  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > facet_map; 
+  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator list_iter; 
+
+  double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+
+  if (maxgap != -1 && maxgap != 0.0)
+      tolerance = maxgap;
+
+  for( i=edges1.size(); i--; )
+  {
+    RefEdge *edge1 = edges1.get_and_step(); 
+
+    int j;
+    for( j=edges2.size(); j--; )
+    {
+      RefEdge *edge2 = edges2.get_and_step();
+      
+      if( edge1 == edge2 )
+        continue;
+
+      bool pair_already_in_map = false;
+
+      std::multimap<RefEdge*, RefEdge*>::iterator it;
+      it = overlapping_edge_map.find( edge2 );
+      if( it != overlapping_edge_map.end() )
+        continue;
+
+      // check to see if this pair is already in the overlap map.
+      //  If it is, don't need to bother checking it for overlap
+     /* 
+      std::multimap<RefEdge*, RefEdge*>::iterator it;
+      std::pair< std::multimap<RefEdge*,RefEdge*>::iterator, std::multimap<RefEdge*,RefEdge*>::iterator > range;
+
+      range = overlapping_edge_map.equal_range(edge1);
+
+      for (it=range.first; it!=range.second; it++)
+      {
+        if ( (it->second == edge2) && (it->first == edge1) )
+                pair_already_in_map = true;
       }
+      if (pair_already_in_map)
+        continue; 
+
+      */
+
+      if( check_overlap( edge1, edge2, &facet_map, &tolerance ) ) 
+      {
+        overlapping_edge_map.insert( std::multimap<RefEdge*, RefEdge*>
+                      ::value_type( edge1, edge2));
+        //PRINT_INFO("Curve %d and %d overlap.\n", edge1->id(), edge2->id());
+        //PRINT_INFO("Insert Curve %d, Curve %d.\n", edge1->id(), edge2->id());
+      }
     }
   }
-
   //clean up facet map
   list_iter=facet_map.begin(); 
   for(; list_iter != facet_map.end(); list_iter++ )
   {
     DLIList<CurveOverlapFacet*> *co_facet_list = list_iter->second;
+    //delete all the facets in the list
+    for( i=co_facet_list->size(); i--; )
+            delete co_facet_list->get_and_step();
+    delete co_facet_list;
   }
 
   return CUBIT_SUCCESS;
 }
 
 CubitBoolean SurfaceOverlapTool::check_overlap( Curve *curve1, Curve *curve2, 
-  std::map<Curve*, DLIList<CurveOverlapFacet*>* > *facet_map ) 
+  std::map<Curve*, DLIList<CurveOverlapFacet*>* > *facet_map,
+  std::multimap<BodySM*,CubitVector> *body_point_imprint_map ) 
 {
   //if surfaces are not splines and are not of the same type, 
   //they won't overlap
   GeometryType curve1_type = curve1->geometry_type();
   GeometryType curve2_type = curve2->geometry_type();
 
-  if( ( curve1_type != SPLINE_CURVE_TYPE  &&
-        curve2_type != SPLINE_CURVE_TYPE) &&
-      (curve1_type != curve2_type )) 
-    return CUBIT_FALSE;
-
   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
 
   std::map<Curve*, DLIList<CurveOverlapFacet*>* >::iterator facet_iterator;
@@ -1652,11 +1966,15 @@
     double curve1_length = curve1->measure();
     double curve2_length = curve2->measure();
 
+/*
     if( curve1_length < curve2_length )
       min_overlap = curve1->measure() * 0.01;
     else 
       min_overlap = curve2->measure() * 0.01;
+      */
 
+    min_overlap = tolerance;
+
     DLIList<CurveOverlapFacet*> *facet_list1 = NULL;
     DLIList<CurveOverlapFacet*> *facet_list2 = NULL;
 
@@ -1669,8 +1987,7 @@
       facet_list1 = new DLIList<CurveOverlapFacet*>;
 
       GMem curve_graphics;
-      int junk;
-      curve1->get_geometry_query_engine()->get_graphics( curve1, junk, 
+      curve1->get_geometry_query_engine()->get_graphics( curve1, 
         &curve_graphics, 0.0 );
 
       GPoint *points = curve_graphics.point_list();
@@ -1705,8 +2022,7 @@
       facet_list2 = new DLIList<CurveOverlapFacet*>;
 
       GMem curve_graphics;
-      int junk;
-      curve2->get_geometry_query_engine()->get_graphics( curve2, junk, 
+      curve2->get_geometry_query_engine()->get_graphics( curve2, 
         &curve_graphics, 0.0 );
 
       GPoint *points = curve_graphics.point_list();
@@ -1737,38 +2053,153 @@
       DLIList<CurveOverlapFacet*> *tmp_list = facet_list1;
       facet_list1 = facet_list2;
       facet_list2 = tmp_list;
+      Curve *tmp_curve = curve1;
+      curve1 = curve2;
+      curve2 = tmp_curve;
     }
-
+    
+    CubitVector curv1_start_pt;
+    CubitVector curv2_start_pt;
+    CubitVector curv1_end_pt;
+    CubitVector curv2_end_pt;
+    
     facet_list1->reset();
     facet_list2->reset();
+    //get start/end facet points on curves
+    if( body_point_imprint_map )
+    {
+      curv1_start_pt = facet_list1->get()->start_point();
+      curv2_start_pt = facet_list2->get()->start_point();
+      facet_list1->last();
+      facet_list2->last();
+      curv1_end_pt = facet_list1->get()->end_point();
+      curv2_end_pt = facet_list2->get()->end_point();
+    }
+    
+    facet_list1->reset();
+    facet_list2->reset();
     int kk;
     double total_overlap = 0.0;
     bool overlap = false;
     //now determine if enough curve facets overlap
 
-    for( kk=facet_list1->size(); kk--; )
+    int list_size1 = facet_list1->size();
+    for( kk=list_size1; kk--; )
     {
       CurveOverlapFacet *curr_facet = facet_list1->get_and_step();
       if( curr_facet->length() < GEOMETRY_RESABS )
         continue;
 
+      //if 'curr_facet' is the first or last facet in curve1,
+      //check to see if the start/end point is on curve2, and not coincident
+      //with the start/end point of curve2.  If so, it's a case where you need
+      //to imprint this start/end point onto the body of curve2.
+      if( body_point_imprint_map )
+      {
+        if( kk == list_size1-1 ) //first facet in curve1
+        {
+          CubitVector closest_point;
+          curve2->closest_point_trimmed( curr_facet->start_point(), closest_point );
+          if( curv2_start_pt.distance_between( curr_facet->start_point() ) > tolerance &&  
+                curv2_end_pt.distance_between( curr_facet->start_point() ) > tolerance &&  
+               closest_point.distance_between( curr_facet->start_point() ) < tolerance )
+          {
+            BodySM *tmp_body_sm = curve2->bodysm();
+            body_point_imprint_map->insert( std::multimap<BodySM*, 
+                                            CubitVector>::value_type(
+                                            tmp_body_sm, closest_point)); 
+          }
+        }
+        if( kk == 0 ) //last facet in curve1 
+        {
+          CubitVector closest_point;
+          curve2->closest_point_trimmed( curr_facet->end_point(), closest_point );
+          if( curv2_start_pt.distance_between( curr_facet->end_point() ) > tolerance &&  
+                curv2_end_pt.distance_between( curr_facet->end_point() ) > tolerance &&  
+               closest_point.distance_between( curr_facet->end_point() ) < tolerance ) 
+          {
+            //insert into vertex-volume imprint map
+            BodySM *tmp_body_sm = curve2->bodysm();
+            body_point_imprint_map->insert( std::multimap<BodySM*, 
+                                            CubitVector>::value_type(
+                                            tmp_body_sm, closest_point)); 
+          }
+        }
+      } 
+
       //do bounding boxes of facets overlap?
       int jj;
-      for( jj=facet_list2->size(); jj--; )
+      int list_size2 = facet_list2->size();
+      for( jj=list_size2; jj--; )
       {
         CurveOverlapFacet *other_facet = facet_list2->get_and_step();
 
         if( curr_facet->bbox_overlap( tolerance, other_facet ) )
         {
-          if( curr_facet->facet_to_facet_distance( other_facet ) < tolerance )
+          double distance_between_facets = curr_facet->facet_to_facet_distance( other_facet );
+          if( distance_between_facets < tolerance )
           {
             if( other_facet->length() < GEOMETRY_RESABS ) 
               continue;
 
-            //are facets parallel within some tolerance angle?
-            double angle = curr_facet->angle( other_facet ); 
-            if( angle < 1 || fabs(180-angle ) < 1 )
+            //if 'other_facet' is the first or last facet in curve1,
+            //check to see if the start/end point is on curve1, and not coincident
+            //with the start/end point of curve1.  If so, it's a case where you need
+            //to imprint this start/end point onto the body of curve1.
+            if( body_point_imprint_map  )
             {
+              if( jj == list_size2-1 ) //first facet in curve1
+              {
+                CubitVector closest_point;
+                curve1->closest_point_trimmed( other_facet->start_point(), closest_point );
+                
+                if( curv1_start_pt.distance_between( other_facet->start_point() ) > tolerance &&  
+                      curv1_end_pt.distance_between( other_facet->start_point() ) > tolerance &&  
+                     closest_point.distance_between( other_facet->start_point() ) < tolerance )
+                {
+                  //insert into vertex-volume imprint map
+                  BodySM *tmp_body_sm = curve1->bodysm();
+                  body_point_imprint_map->insert( std::multimap<BodySM*, 
+                                                  CubitVector>::value_type(
+                                                  tmp_body_sm, closest_point )); 
+                }
+              }
+              if( jj == 0 ) //last facet in curve1 
+              {
+                CubitVector closest_point;
+                curve1->closest_point_trimmed( other_facet->end_point(), closest_point );
+                if( curv1_start_pt.distance_between( other_facet->end_point() ) > tolerance &&  
+                      curv1_end_pt.distance_between( other_facet->end_point() ) > tolerance &&  
+                     closest_point.distance_between( other_facet->end_point() ) < tolerance )
+                {
+                  //insert into vertex-volume imprint map
+                  BodySM *tmp_body_sm = curve1->bodysm();
+                  body_point_imprint_map->insert( std::multimap<BodySM*, 
+                                                  CubitVector>::value_type(
+                                                  tmp_body_sm, closest_point )); 
+                }
+              }
+            }
+
+            //get the long and short facet edge
+            double curr_facet_length = curr_facet->length();
+            double other_facet_length = other_facet->length();
+            CurveOverlapFacet *long_facet = ( curr_facet_length > other_facet_length ?
+                                             curr_facet : other_facet );
+            CurveOverlapFacet *short_facet = curr_facet;
+            if( long_facet == curr_facet )
+              short_facet = other_facet;
+
+            //make sure both endpoints of the smaller facet edge lie within a radius
+            //or merge tolerance to an infinite line defined by longer facet edge
+            CubitVector direction = long_facet->end_point() - long_facet->start_point();
+            double dist1 = short_facet->start_point().distance_from_infinite_line(
+                                          long_facet->start_point(), direction );
+            double dist2 = short_facet->end_point().distance_from_infinite_line(
+                                          long_facet->start_point(), direction );
+
+            if( dist1 <= tolerance && dist2 <= tolerance )
+            {
               double overlap_tolerance = 
                 curr_facet->length() < other_facet->length() ? curr_facet->length():
                 other_facet->length();
@@ -1852,10 +2283,11 @@
       curve1->closest_point( mid_point1, dummy_vec, NULL, &curvature1 );
       curve2->closest_point( mid_point2, dummy_vec, NULL, &curvature2 );
       
-      double rad1 = curvature1.length();
-      double rad2 = curvature2.length();
+      double rad1 = 1/curvature1.length();
+      double rad2 = 1/curvature2.length();
 
-      if( fabs( rad1 - rad2 ) > 0.001 )
+      //if( fabs( rad1 - rad2 ) > 0.001 )
+      if( fabs( rad1 - rad2 ) > tolerance )
         return CUBIT_FALSE; 
     }
     else
@@ -1868,9 +2300,10 @@
 }
 
 CubitBoolean SurfaceOverlapTool::check_overlap( RefEdge *edge1, RefEdge *edge2, 
-  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > *facet_map ) 
+  std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > *facet_map,
+  double *overlap_tol ) 
 {
-  //if surfaces are not splines and are not of the same type, 
+  //if edges are not splines and are not of the same type, 
   //they won't overlap
   if( (edge1->get_curve_ptr()->geometry_type() != SPLINE_CURVE_TYPE  &&
        edge2->get_curve_ptr()->geometry_type() != SPLINE_CURVE_TYPE) &&
@@ -1878,7 +2311,15 @@
        edge2->get_curve_ptr()->geometry_type() )) 
     return CUBIT_FALSE;
 
+  // we don't want to consider edges from the same body
+  if (edge1->body() == edge2->body())
+	  return CUBIT_FALSE;
+
+
   double tolerance = GeometryQueryTool::get_geometry_factor()*GEOMETRY_RESABS;
+  if( overlap_tol )
+    tolerance = *overlap_tol;
+    
 
   std::map<RefEdge*, DLIList<CurveOverlapFacet*>* >::iterator facet_iterator;
   CubitBox edge_box1 = edge1->bounding_box(); 
@@ -2060,7 +2501,9 @@
       //if curvatures are more than 10% off 
       double curvature_diff = fabs( rad1 - rad2 );
 
-      if( rad1 || rad2 ) 
+      if( (rad1 || rad2 ) && 
+         (rad1 > GEOMETRY_RESABS ||   //radii must be of significance even look at  
+          rad2 > GEOMETRY_RESABS ))
       {
         if( curvature_diff/( (fabs(rad1) + fabs(rad2))/2 ) > 0.1 )
           return CUBIT_FALSE;
@@ -2074,4 +2517,3 @@
   
   return CUBIT_TRUE;
 }
-

Modified: cgm/branches/cubit/geom/SurfaceOverlapTool.hpp
===================================================================
--- cgm/branches/cubit/geom/SurfaceOverlapTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/SurfaceOverlapTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -17,29 +17,43 @@
 template <class X> class DLIList;
 class RefFace;
 
+//! Tool to find surfaces and curves that overlap.
 class CUBIT_GEOM_EXPORT SurfaceOverlapTool
 {
 
 public :   
 
+   //! From the specified surfaces, find surfaces that overlap. 
    CubitStatus find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list, 
-                                          DLIList<RefEntity*> &faces_to_draw );
+                                          DLIList<RefEntity*> &faces_to_draw,
+                                          bool filter_slivers = false );
+
+   //! From the specified bodies, find surfaces that overlap. 
    CubitStatus find_overlapping_surfaces( DLIList<Body*> &body_list,
-                                          DLIList<RefEntity*> &faces_to_draw );
+                                          DLIList<RefEntity*> &faces_to_draw,
+                                          bool filter_slivers = false );
+
+   //! From the specified surfaces, find surfaces that overlap. 
    CubitStatus find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list,
                                           DLIList<RefFace*> &ref_face_list1,
                                           DLIList<RefFace*> &ref_face_list2,
                                           DLIList<RefEntity*> &faces_to_draw,
-                                          CubitBoolean show_messages = CUBIT_FALSE);
+                                          CubitBoolean show_messages = CUBIT_FALSE,
+                                          bool filter_slivers = false);
+
+   //! From the specified bodies, find surfaces that overlap. 
    CubitStatus find_overlapping_surfaces( DLIList<Body*> &body_list,
                                           DLIList<RefFace*> &ref_face_list1,
                                           DLIList<RefFace*> &ref_face_list2,
                                           DLIList<RefEntity*> &faces_to_draw,
-                                          CubitBoolean show_messages = CUBIT_FALSE);
+                                          CubitBoolean show_messages = CUBIT_FALSE,
+                                          bool filter_slivers = false);
 
+   //! From the specified bodies, find surfaces that overlap. 
    CubitStatus find_overlapping_surfaces( DLIList<BodySM*> &body_list,
                                           DLIList<Surface*> &surface_list1,
-                                          DLIList<Surface*> &surface_list2 );
+                                          DLIList<Surface*> &surface_list2,
+                                          bool filter_slivers = false );
 
    // Searches for surfaces that overlap each other and are good
    // candidates for imprinting.  It can even find those with gaps
@@ -55,20 +69,78 @@
    // overlap...", and groupResults, listPairs and displayPairs will be
    // used, otherwise they will be false (default).
 
+   //! From the specified surfaces, find overlapping curves.
+   CubitStatus find_overlapping_curves( DLIList<Surface*> &surf_list,
+                                DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
+                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                std::multimap<BodySM*, CubitVector> &body_point_imprint_map);
+
+   //! From the specified curves, find those that overlap. 
+   CubitStatus find_overlapping_curves( DLIList<Curve*> &curve_list,
+                                DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
+                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                std::multimap<BodySM*, CubitVector> &body_point_imprint_map);
+
+   //! From the specified bodies, find curves that overlap. 
    CubitStatus find_overlapping_curves( DLIList<Body*> &bodies,
-                   std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map );
+                   std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
+                   double maxgap = -1);
+
+   //! From the specified bodies, find curves that overlap. 
    CubitStatus find_overlapping_curves( DLIList<BodySM*> &bodies,
                                 DLIList< DLIList<Curve*> *> &overlapping_curve_lists,
-                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map );
+                                std::map<Curve*, DLIList<Curve*>* > &curve_to_list_map,
+                                std::multimap<BodySM*, CubitVector> &body_vertex_imprint_map);
 
+   //! From the specified surfaces, find curves that overlap. 
+   CubitStatus find_overlapping_curves( DLIList<RefFace*> &faces,
+				        std::multimap<RefEdge*, 
+                        RefEdge*> &overlapping_edge_map,
+                        double maxgap = -1);
+
+
+   //! From the specified curves, find curves that overlap. 
+   CubitStatus find_overlapping_curves( DLIList<RefEdge*> &edgelist,
+				        std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
+                        double maxgap = -1);
+
+   //! From the specified curves, find curves that overlap. 
+   CubitStatus find_overlapping_curves( DLIList<RefEdge*> &edges1, DLIList<RefEdge*> &edges2,
+					std::multimap<RefEdge*, RefEdge*> &overlapping_edge_map,
+                    double maxgap = -1);
+
+   //! Checks to see if two curves overlap.  Reuses graphic facets.
    CubitBoolean check_overlap( RefEdge *edge1, RefEdge *edge2, 
-               std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > *facet_map );
+               std::map<RefEdge*, DLIList<CurveOverlapFacet*>* > *facet_map, 
+               double *overlap_tol = NULL );
 
+   //! Checks to see if two surfaces overlap.
+   CubitBoolean check_overlap( RefFace *ref_face_ptr1,
+                               RefFace *ref_face_ptr2,
+                               CubitBoolean abort,
+                               CubitBoolean draw_overlap = CUBIT_FALSE,
+                               double *overlap_area = NULL );
+
+   //! Checks to see if two curves overlap.  Reuses graphic facets.
    CubitBoolean check_overlap( Curve *curve1, Curve *curve2, 
-               std::map<Curve*, DLIList<CurveOverlapFacet*>* > *facet_map );
+               std::map<Curve*, DLIList<CurveOverlapFacet*>* > *facet_map, 
+               std::multimap<BodySM*, CubitVector > *body_point_imprint_map = NULL );
 
+   //! Checks to see the two groups of facets overlap. 
+   CubitBoolean check_overlap( DLIList<SurfaceOverlapFacet*> *facet_list1,
+                               DLIList<SurfaceOverlapFacet*> *facet_list2,
+                               AbstractTree<SurfaceOverlapFacet*> *a_tree, 
+                               CubitBoolean abort, 
+                               CubitBoolean draw_overlap,
+                               double *overlap_area );
+
+   //! Draws the overlapping surface pair.
+   CubitBoolean draw_overlapping_surface_pair( RefFace *ref_face_1,
+                                               RefFace *ref_face_2);
+
+
+   //! List the settings used for surface overlap detection
    void list_settings();
-     // List the settings used for surface overlap detection
 
    unsigned short get_facet_ang_tol();
    void set_facet_ang_tol( unsigned short angle_tol );
@@ -130,7 +202,8 @@
 
    static CubitBoolean get_check_across_bodies();
    static void set_check_across_bodies( CubitBoolean setting );
-
+   CubitBoolean get_skip_facing_surfaces();
+   void set_skip_facing_surfaces( CubitBoolean setting );
    static SurfaceOverlapTool* instance();
      // Returns a static pointer to unique instance of this class.
    
@@ -141,19 +214,18 @@
    
 private :
 
+
   CubitStatus find_overlapping_surfaces( DLIList<RefFace*> &ref_face_list,
                                          DLIList<RefFace*> &ref_face_list1,
                                          DLIList<RefFace*> &ref_face_list2,
                                          DLIList<RefEntity*> &pair_list,
                                          CubitBoolean list_pairs,
-                                         int prog_step );
+                                         int prog_step,
+                                         bool filter_slivers = false);
   // Private workhorse function for finding the overlapping surfaces. Here 
   // pair_list is a list of all the surfaces that were found that overlap.
   // If prog_step == -1 it does not step the progress bar. 
 
-   CubitBoolean check_overlap( RefFace *ref_face_ptr1,
-                               RefFace *ref_face_ptr2,
-                               CubitBoolean abort );
    CubitBoolean check_overlap( Surface *surface1,
                                Surface *surface2,
               std::map<Surface*, DLIList<SurfaceOverlapFacet*>* > *facet_map,
@@ -189,19 +261,65 @@
    SurfaceOverlapTool();
      //- Constructor for the SurfaceOverlapTool object
 
+   /*! The angular tolerance indicates the maximum angle between 
+       normals of adjacent surface facets. The default angular 
+       tolerance is 15° - consider using a value of 5° . This will 
+       generate a more accurate facetted representation of the 
+       geometry for overlap detection.  */
+   static  unsigned short facetAngTol;
+
+  /*!  The distance tolerance means the maximum actual distance 
+       between the generated facets and the surface. This value is 
+       by default ignored by the facetter - consider specifying a 
+       reasonable value here for more accurate results */
    static  double facetAbsTol;
-   static  unsigned short facetAngTol;
+
+   /*! The overlap algorithm will search for surfaces that are 
+   within a distance from the gapMin to gapMax. */
    static  double gapMin;
    static  double gapMax;
+
+   //@{
+   /*! Angle comparison for determining if facets are coplanar.  If
+   they are within angleMin and angleMax they are considered to be 
+   coplanar. */
    static  double angleMin;
    static  double angleMax;
+   //@}
+  
+   //! Searches for overlapping surface that have surface normals
+   //! in any, opposite, or the same direction.
    static  int normalType; // 1=any, 2=opposite, 3=same
+  
+   //! Controls if surfaces are put in a group or not.
    static  CubitBoolean groupResults;
+   
+   //! Prints out the lists of overlapping surface pairs.
    static  CubitBoolean listPairs;
+
+   //! Draws the lists of overlapping surface pairs.
    static  CubitBoolean displayPairs;
+  
+   //! Imprint overlapping surfaces parts onto one another. 
    static  CubitBoolean imprintResults;
+  
+   //! The area threshold that 2 surfaces have to actually overlap.
+   //! Prevents detection of sliver overlaps. 
    static  double overlapTolerance;
+
+   //! if the normalType is 2 skip surfaces that face each other
+   static CubitBoolean skipFacingSurfaces;
+
+   //! By default this tool will not search for overlapping 
+   //! pairs within bodies - only between different bodies. 
+   //! Turn this setting on to search for pairs within bodies. 
+   //! Note however that this will slow the algorithm down. 
    static  CubitBoolean checkWithinBodies;
+  
+   //! If true, by default, will try to find surfaces of body A
+   //! that overlap surfaces of body B.  Setting this flag to 
+   //! false will make the tool only check for surfaces that 
+   //! overlap in the same body. 
    static  CubitBoolean checkAcrossBodies;
 };
 
@@ -251,38 +369,30 @@
 void SurfaceOverlapTool::set_overlap_tolerance( double val )
 {overlapTolerance=val;}
 
-#ifdef CAT
 inline
 int SurfaceOverlapTool::get_normal_type()
 {return normalType;}
-#endif
 inline
 void SurfaceOverlapTool::set_normal_type( int type )
 {normalType=type;}
 
-#ifdef CAT
 inline
 CubitBoolean SurfaceOverlapTool::get_group_results()
 {return groupResults;}
-#endif
 inline
 void SurfaceOverlapTool::set_group_results( CubitBoolean setting )
 {groupResults=setting;}
 
-#ifdef CAT
 inline
 CubitBoolean SurfaceOverlapTool::get_list_pairs()
 {return listPairs;}
-#endif
 inline
 void SurfaceOverlapTool::set_list_pairs( CubitBoolean setting )
 {listPairs=setting;}
 
-#ifdef CAT
 inline
 CubitBoolean SurfaceOverlapTool::get_display_pairs()
 {return displayPairs;}
-#endif
 inline
 void SurfaceOverlapTool::set_display_pairs( CubitBoolean setting )
 {displayPairs=setting;}
@@ -304,7 +414,12 @@
 inline
 void SurfaceOverlapTool::set_check_across_bodies( CubitBoolean setting )
 {checkAcrossBodies=setting;}  
-
+inline
+CubitBoolean SurfaceOverlapTool::get_skip_facing_surfaces()
+{return skipFacingSurfaces;}
+inline
+void SurfaceOverlapTool::set_skip_facing_surfaces( CubitBoolean setting )
+{skipFacingSurfaces=setting;}  
 #endif
 
 

Modified: cgm/branches/cubit/geom/TDSplitSurface.cpp
===================================================================
--- cgm/branches/cubit/geom/TDSplitSurface.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/TDSplitSurface.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -877,3 +877,17 @@
 
   return CUBIT_SUCCESS;
 }
+
+//================================================================================
+// Description: This class holds data on vertices for split across extend
+// Author     : Steve Storm
+// Date       : 10/7/2007
+//================================================================================
+TDSplitSurfaceExtend::TDSplitSurfaceExtend()
+{
+  successFlg = CUBIT_FALSE;
+}
+
+TDSplitSurfaceExtend::~TDSplitSurfaceExtend()
+{
+}

Modified: cgm/branches/cubit/geom/TDSplitSurface.hpp
===================================================================
--- cgm/branches/cubit/geom/TDSplitSurface.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/TDSplitSurface.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -413,4 +413,41 @@
 inline CubitBoolean TDSplitSurface::is_d_collapsed()
 { return sideD->is_collapsed(); }
 
+
+//================================================================================
+// Description: This class holds data on vertices for split across extend
+// Author     : Steve Storm
+// Date       : 10/7/2007
+//================================================================================
+class CUBIT_GEOM_EXPORT TDSplitSurfaceExtend : public ToolData
+{
+public:
+
+  TDSplitSurfaceExtend();
+  //- Constructor
+
+  ~TDSplitSurfaceExtend();
+  //- Destructor
+
+  void set_success();
+  //- This indicates we successfully extended from this vertex
+
+  CubitBoolean is_success();
+  //- Did we successfully extend from this vertex?
+
+  static int is_split_surface_extend(const ToolData* td)
+     {return (CAST_TO(td, const TDSplitSurfaceExtend) != NULL);}
+
+private:
+
+  CubitBoolean successFlg;
+};
+
+inline void
+TDSplitSurfaceExtend::set_success()
+{ successFlg = CUBIT_TRUE; }
+
+inline CubitBoolean
+TDSplitSurfaceExtend::is_success()
+{ return successFlg; }
 #endif // TD_SPLIT_SURFACE_HPP

Modified: cgm/branches/cubit/geom/TDUniqueId.cpp
===================================================================
--- cgm/branches/cubit/geom/TDUniqueId.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/TDUniqueId.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -86,23 +86,19 @@
 	//- it is a match, erase it by iterator.  This will leave the other entry with
 	//- the similar key in the list, which is necessary for save/restore, and remove the 
 	//- deactivated geometry due to the merge.
-	int map_count = unique_id_list().count(uniqueId);
-	if( map_count == 1 )
-		unique_id_list().erase(uniqueId);
-	else if( map_count > 1 )
-	{
-		std::pair<TDUIDList::iterator, TDUIDList::iterator> 
-			bounds_pair = unique_id_list().equal_range(uniqueId);
 
-    TDUIDList::iterator
-			it = bounds_pair.first, upper = bounds_pair.second;
-		
-		while( (*it).second != this && it != upper ) 
-			it++;
-		
-		if( it != upper )
-			unique_id_list().erase( it );
-	}
+  std::pair<TDUIDList::iterator, TDUIDList::iterator>
+    bounds_pair = unique_id_list().equal_range(uniqueId);
+
+  TDUIDList::iterator it;
+  for(it = bounds_pair.first; it != bounds_pair.second; ++it)
+  {
+    if(it->second == this)
+    {
+      unique_id_list().erase( it );
+      break;
+    }
+  }
 }
     
 int TDUniqueId::get_unique_id(ToolDataUser *owner,
@@ -133,7 +129,6 @@
     return 0;
 
   if ((*it).first == temp_id) {
-
       // the lower bound key is equal to temp_id, so this id is in the list
 
       // look for duplicate id's, return one that's directly related
@@ -191,16 +186,29 @@
 void TDUniqueId::clear_copy_map()
 {
   //remove TDs off of entities
-  
   COPYUIDMap::iterator iter = mapForCopying.begin();
   for(; iter != mapForCopying.end(); iter++ )
   {
-    ToolDataUser *td_user = find_td_unique_id( (*iter).second );
+    DLIList<ToolDataUser*> tool_data_users;
+    int num_tool_datas = find_td_unique_id( (*iter).second, tool_data_users );
+    
+    for( ; num_tool_datas--; ) 
+    {
+      ToolDataUser *td_user = tool_data_users.get_and_step();
+
       //make sure the pointer isn't null
-    if(td_user)
-      td_user->remove_TD(TDUniqueId::is_unique_id);
-  }
+      ToolData *tool_data = NULL;
+      if(td_user)
+        tool_data = td_user->remove_TD(TDUniqueId::is_unique_id);
+      
+      //delete the TDUniqueId as well
+      if( tool_data )
+        delete tool_data;
 
+      td_user = find_td_unique_id( (*iter).second );
+    } 
+  } 
+
   //clear out the map 
   if (mapForCopying.empty()) return;
     mapForCopying.erase(mapForCopying.begin(), mapForCopying.end());

Modified: cgm/branches/cubit/geom/TopologyBridge.cpp
===================================================================
--- cgm/branches/cubit/geom/TopologyBridge.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/TopologyBridge.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -291,6 +291,91 @@
   }
 }  
 
+void TopologyBridge::curves_ignore_virtual( DLIList<Curve*>& curves, bool unique )
+{
+  int i;
+  if(dynamic_cast<BodySM*>(this))
+  {
+    DLIList<TopologyBridge*> lumps;
+    this->get_children_virt(lumps);
+    for(i=lumps.size(); i>0; i--)
+      lumps.get_and_step()->curves_ignore_virtual(curves, unique);
+  }
+  else if(dynamic_cast<Lump*>(this))
+  {
+    DLIList<TopologyBridge*> shells;
+    this->get_children_virt(shells);
+    for(i=shells.size(); i>0; i--)
+      shells.get_and_step()->curves_ignore_virtual(curves, unique);
+  }
+  else if(dynamic_cast<ShellSM*>(this))
+  {
+    DLIList<TopologyBridge*> surfs;
+    this->get_children_virt(surfs);
+    for(i=surfs.size(); i>0; i--)
+      surfs.get_and_step()->curves_ignore_virtual(curves, unique);
+  }
+  else if(dynamic_cast<Surface*>(this))
+  {
+    DLIList<TopologyBridge*> loops;
+    this->get_children_virt(loops);
+    for(i=loops.size(); i>0; i--)
+      loops.get_and_step()->curves_ignore_virtual(curves, unique);
+  }
+  else if(dynamic_cast<LoopSM*>(this))
+  {
+    DLIList<TopologyBridge*> coedges;
+    this->get_children_virt(coedges);
+    for(i=coedges.size(); i>0; i--)
+      coedges.get_and_step()->curves_ignore_virtual(curves, unique);
+  }
+  else if(dynamic_cast<CoEdgeSM*>(this))
+  {
+    DLIList<TopologyBridge*> tmp_curves;
+    this->get_children_virt(tmp_curves);
+    for(i=tmp_curves.size(); i>0; i--)
+      tmp_curves.get_and_step()->curves_ignore_virtual(curves, unique);
+  }
+  else if(dynamic_cast<Curve*>(this))
+  {
+    curves.append(dynamic_cast<Curve*>(this));
+  }
+  if(unique)
+    curves.uniquify_ordered();
+}
+
+void TopologyBridge::surfaces_ignore_virtual( DLIList<Surface*>& surfaces, bool unique )
+{
+  int i;
+  if(dynamic_cast<BodySM*>(this))
+  {
+    DLIList<TopologyBridge*> lumps;
+    this->get_children_virt(lumps);
+    for(i=lumps.size(); i>0; i--)
+      lumps.get_and_step()->surfaces_ignore_virtual(surfaces, unique);
+  }
+  else if(dynamic_cast<Lump*>(this))
+  {
+    DLIList<TopologyBridge*> shells;
+    this->get_children_virt(shells);
+    for(i=shells.size(); i>0; i--)
+      shells.get_and_step()->surfaces_ignore_virtual(surfaces, unique);
+  }
+  else if(dynamic_cast<ShellSM*>(this))
+  {
+    DLIList<TopologyBridge*> surfs;
+    this->get_children_virt(surfs);
+    for(i=surfs.size(); i>0; i--)
+      surfs.get_and_step()->surfaces_ignore_virtual(surfaces, unique);
+  }
+  else if(dynamic_cast<Surface*>(this))
+  {
+    surfaces.append(dynamic_cast<Surface*>(this));
+  }
+  if(unique)
+    surfaces.uniquify_ordered();
+}
+
 void TopologyBridge::curves( DLIList<Curve*>& curves, bool unique )
 {
   DLIList<TopologyBridge*> related;

Modified: cgm/branches/cubit/geom/TopologyBridge.hpp
===================================================================
--- cgm/branches/cubit/geom/TopologyBridge.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/TopologyBridge.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -194,8 +194,10 @@
   void lumps(DLIList<Lump*> &lumps,bool unique = true);
   void shellsms(DLIList<ShellSM*> &shellsms,bool unique = true);
   void surfaces(DLIList<Surface*> &surfaces,bool unique = true);
+  void surfaces_ignore_virtual(DLIList<Surface*> &surfaces,bool unique = true);
   void loopsms(DLIList<LoopSM*> &loopsms,bool unique = true);
-  void curves(DLIList<Curve*> &curves,bool unique = true);
+  void curves(DLIList<Curve*> &curves, bool unique = true);
+  void curves_ignore_virtual(DLIList<Curve*> &curves, bool unique = true);
   void coedgesms(DLIList<CoEdgeSM*> &coedgesms,bool unique = true);
   void points(DLIList<Point*> &points,bool unique = true);
     //- topology traversal of TB's; implemented based on native traversal

Modified: cgm/branches/cubit/geom/facet/FacetCurve.cpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetCurve.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetCurve.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -238,12 +238,17 @@
 //-------------------------------------------------------------------------
 double FacetCurve::length_from_u( double parameter1, double parameter2 )
 {
-  if( periodic )
-  {
-    adjust_periodic_parameter( parameter1 );
-    adjust_periodic_parameter( parameter2 );
-  }
-  return curveFacetEvalTool->length_from_u( parameter1, parameter2 );   
+
+    //Don't perform the periodic adjustment so that
+    // this function will satisfy the properties of
+    // the function as defined in RefEdge.hpp.
+    // Also, take the fabs of the arc length for the same reason.
+  //if( periodic )
+  //{
+  //  adjust_periodic_parameter( parameter1 );
+  //  adjust_periodic_parameter( parameter2 );
+  //}
+  return fabs(curveFacetEvalTool->length_from_u( parameter1, parameter2 ));   
 }
 
 //-------------------------------------------------------------------------

Modified: cgm/branches/cubit/geom/facet/FacetLoop.cpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetLoop.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetLoop.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -66,6 +66,27 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : The purpose of this function is to see if a loop is an external
+//                  or internal loop of a surface.
+//
+// Special Notes : 
+//
+// Creator       : Jonathan Bugman
+//
+// Creation Date : 9/9/2008
+//-------------------------------------------------------------------------
+CubitBoolean FacetLoop::is_external()
+{
+		  PRINT_ERROR( "This command is not supported with this engine.\n");
+          return CUBIT_FAILURE;
+}
+
+LoopType FacetLoop::loop_type()
+{
+  return LOOP_TYPE_UNKNOWN;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : The purpose of this function is to append a
 //                 attribute to the GE. The name is attached to the
 //                 underlying solid model entity this one points to.

Modified: cgm/branches/cubit/geom/facet/FacetLoop.hpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetLoop.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetLoop.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -45,6 +45,14 @@
   virtual ~FacetLoop() ;
     //- The destructor
   
+  virtual CubitBoolean is_external() ;
+    //R CubitBoolean
+    //R- CUBIT_TRUE/CUBIT_FALSE
+    //- Returns CUBIT_TRUE if the Loop is an external Loop and CUBIT_FALSE
+    //- otherwise.
+  
+  virtual LoopType loop_type() ;
+
   virtual void append_simple_attribute_virt(CubitSimpleAttrib*);
     //R void
     //I 

Modified: cgm/branches/cubit/geom/facet/FacetModifyEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetModifyEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetModifyEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -70,24 +70,24 @@
 // do nothing in some very rare cases.  From Steven Engelhardt's Weblog.
 
 #define MODIFY_CHECK_RETURN_NULL \
-do {if(!modifyEnabled){ \
+do {if(!modifyEnabled){                                                               \
     PRINT_INFO("Facet-based geometry modification is a beta capability.\n");\
     PRINT_ERROR("This capability is currently disabled.\n");\
-    PRINT_INFO("To enable this capability, issue the command 'set facet_modify on'. \n");\
+    PRINT_INFO("To enable this capability, issue the command 'set developer commands on'. \n");\
     return NULL;} }while(0)
 
 #define MODIFY_CHECK_RETURN_VOID \
 do {if(!modifyEnabled){ \
     PRINT_INFO("Facet-based geometry modification is a beta capability.\n");\
     PRINT_ERROR("This capability is currently disabled.\n");\
-    PRINT_INFO("To enable this capability, issue the command 'set facet_modify on'. \n");\
+    PRINT_INFO("To enable this capability, issue the command 'set developer commands on'. \n");\
     return;} }while(0)
 
 #define MODIFY_CHECK_RETURN_FAILURE \
 do {if(!modifyEnabled){ \
     PRINT_INFO("Facet-based geometry modification is a beta capability.\n");\
     PRINT_ERROR("This capability is currently disabled.\n");\
-    PRINT_INFO("To enable this capability, issue the command 'set facet_modify on'. \n");\
+    PRINT_INFO("To enable this capability, issue the command 'set developer commands on'. \n");\
     return CUBIT_FAILURE;} }while(0)
 //===============================================================================
 // Function   : FacetModifyEngine
@@ -170,6 +170,20 @@
 //===============================================================================
 // Function   : make_Curve
 // Member Type: PUBLIC
+// Description: make a curve using point_tangents to describe curvature
+// Author     : John Fowler
+// Date       : 10/02
+//===============================================================================
+Curve* FacetModifyEngine::make_Curve( DLIList<CubitVector*>& point_list,
+                   DLIList<CubitVector*>& point_tangents) const
+{
+    PRINT_ERROR("Option not supported for mesh based geometry.\n");
+    return (Curve*)NULL;
+}
+
+//===============================================================================
+// Function   : make_Curve
+// Member Type: PUBLIC
 // Description: make a curve
 // Author     : John Fowler
 // Date       : 10/02
@@ -216,6 +230,21 @@
 }
 
 //===============================================================================
+// Function   : make_extended_sheet
+// Member Type: PUBLIC
+// Description: make an extended sheet from a set of surfaces
+// Author     : 
+// Date       : 
+//===============================================================================
+BodySM* FacetModifyEngine::make_extended_sheet( DLIList<Surface*> & /*surface_list*/,
+                                 CubitBox * /*clip_box_ptr*/,
+                                 bool /*preview*/ ) const
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return (BodySM*) NULL;
+}
+
+//===============================================================================
 // Function   : make_Surface
 // Member Type: PUBLIC
 // Description: make a surface
@@ -609,6 +638,17 @@
   return body_ptr;
 }
 
+CubitStatus FacetModifyEngine::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
+{
+   PRINT_INFO("This functionality is not implemented for faceted geometry.\n");
+   return CUBIT_FAILURE;
+}
+
 void FacetModifyEngine::set_sphere_eval_data
 (
     ChollaEngine *cholla_ptr,
@@ -896,15 +936,182 @@
 // Function   : brick
 // Member Type: PUBLIC
 // Description: create a brick with facets given center axes and extension
-// Author     : John Fowler
-// Date       : 10/02
+// Author     : Steve Owen
+// Date       : 1/09
 //===============================================================================
-BodySM* FacetModifyEngine::brick( const CubitVector &/*center*/, 
-                                  const CubitVector* /*axes[3]*/,
-                                  const CubitVector &/*extension*/) const
+BodySM* FacetModifyEngine::brick( const CubitVector &center, 
+                                  const CubitVector axes[3],
+                                  const CubitVector &extension) const
 {
-  PRINT_ERROR("Option not supported for mesh based geometry.\n");
-  return (BodySM*) NULL;
+  
+	
+  MODIFY_CHECK_RETURN_NULL;
+  CubitStatus rv = CUBIT_SUCCESS;
+  CubitVector uvec, vvec, wvec, corner, mid;
+  DLIList <CubitFacet *>facet_list;
+  DLIList <CubitPoint *>point_list;
+  CubitPoint *new_point;
+  CubitFacet *facet_ptr;
+  int i, numpoints, numtris;
+  double feature_angle;
+  int interp_order;
+  CubitBoolean smooth_non_manifold, split_surfaces;
+  BodySM *body_ptr = NULL;
+  std::vector<CubitPoint *> points;
+  
+  numpoints = 14;
+  numtris = 24;
+  
+	uvec = extension.x() * axes[0];
+	vvec = extension.y() * axes[1];
+	wvec = extension.z() * axes[2];
+  
+	corner = center - uvec - vvec - wvec; 
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);
+	
+	corner = center + uvec - vvec - wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);
+	
+	corner = center + uvec - vvec + wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);
+  
+	corner = center - uvec - vvec + wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point); 
+	
+	corner = center - uvec + vvec - wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);
+	
+	corner = center + uvec + vvec - wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);
+	
+	corner = center + uvec + vvec + wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);  
+	
+	corner = center - uvec + vvec + wvec;
+  new_point = (CubitPoint *) new CubitPointData( corner.x(),corner.y(),corner.z() ); 
+  points.push_back(new_point);   
+	
+	mid = center - wvec;
+  new_point = (CubitPoint *) new CubitPointData( mid.x(), mid.y(), mid.z() ); 
+  points.push_back(new_point);
+	
+	mid = center + uvec;
+  new_point = (CubitPoint *) new CubitPointData( mid.x(), mid.y(), mid.z() ); 
+  points.push_back(new_point);  
+  
+	mid = center + wvec;
+  new_point = (CubitPoint *) new CubitPointData( mid.x(), mid.y(), mid.z() ); 
+  points.push_back(new_point);  
+	
+	mid = center - uvec;
+  new_point = (CubitPoint *) new CubitPointData( mid.x(), mid.y(), mid.z() ); 
+  points.push_back(new_point); 
+  
+	mid = center - vvec;
+  new_point = (CubitPoint *) new CubitPointData( mid.x(), mid.y(), mid.z() ); 
+  points.push_back(new_point); 
+  
+	mid = center + vvec;
+  new_point = (CubitPoint *) new CubitPointData( mid.x(), mid.y(), mid.z() ); 
+  points.push_back(new_point);   
+  
+  for ( i = 0; i < numpoints; i++ ) {
+    point_list.append(points[i]);
+  }    
+  
+  // bottom face      
+  facet_ptr = new CubitFacetData( points[0],points[1], points[12] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[1],points[2], points[12] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[2],points[3], points[12] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[3],points[0], points[12] );
+  // back face
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[1],points[0], points[8] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[5],points[1], points[8] );
+  facet_list.append( facet_ptr );  
+  facet_ptr = new CubitFacetData( points[4],points[5], points[8] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[0],points[4], points[8] );
+  facet_list.append( facet_ptr );
+  // left face
+  facet_ptr = new CubitFacetData( points[0],points[3], points[11] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[3],points[7], points[11] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[7],points[4], points[11] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[4],points[0], points[11] );
+  facet_list.append( facet_ptr ); 
+  // top face
+  facet_ptr = new CubitFacetData( points[7],points[6], points[13] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[6],points[5], points[13] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[5],points[4], points[13] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[4],points[7], points[13] );
+  facet_list.append( facet_ptr ); 
+  // right face
+  facet_ptr = new CubitFacetData( points[1],points[5], points[9] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[5],points[6], points[9] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[6],points[2], points[9] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[2],points[1], points[9] );
+  facet_list.append( facet_ptr ); 
+  // front face  
+  facet_ptr = new CubitFacetData( points[3],points[2], points[10] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[2],points[6], points[10] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[6],points[7], points[10] );
+  facet_list.append( facet_ptr );
+  facet_ptr = new CubitFacetData( points[7],points[3], points[10] );
+  facet_list.append( facet_ptr );   
+  
+  points.clear(); //  clear out the points vector since we are through with it.
+  
+  feature_angle = 100.0;
+  interp_order = 0;
+  smooth_non_manifold = CUBIT_TRUE;
+  split_surfaces = CUBIT_FALSE;
+  
+  ChollaEngine *cholla_ptr = NULL;
+  FacetModifyEngine *fme = const_cast<FacetModifyEngine *> (this);
+  rv = fme->build_cholla_surfaces( facet_list,
+																	point_list,
+																	feature_angle,
+																	interp_order,
+																	smooth_non_manifold,
+																	split_surfaces,
+																	cholla_ptr );
+  if ( rv == CUBIT_SUCCESS )
+  {
+		finish_facet_Body( cholla_ptr,
+											NULL,
+											feature_angle,
+											interp_order,
+											body_ptr);
+		if ( cholla_ptr )
+		{
+			cholla_ptr->delete_me();
+			delete cholla_ptr;
+		}
+		
+  }
+  return body_ptr;
 }
 
 //===============================================================================
@@ -1322,7 +1529,8 @@
     status = fbint->dofacetboolean_subtract(tool_body,from_bodies,new_bodies,
                                             keep_old,to_be_deleted,op);
     delete fbint;
-    FacetQueryEngine::instance()->delete_solid_model_entities(tool_body);    
+    if( keep_old == false )
+      FacetQueryEngine::instance()->delete_solid_model_entities(tool_body);    
   }
 
   for ( i = 0; i < from_bodies.size(); i++ ) {
@@ -1435,6 +1643,7 @@
 CubitStatus     FacetModifyEngine::imprint( DLIList<BodySM*> &body_list,
                                            DLIList<Curve*> &ref_edge_list,
                                            DLIList<BodySM*>& new_body_list,
+                                           DLIList<TopologyBridge*> &temporary_bridges,
                                            bool keep_old,
                                            bool show_messages) const
 {
@@ -1483,6 +1692,7 @@
 //===============================================================================
 CubitStatus     FacetModifyEngine::imprint( DLIList<Surface*> &/*ref_face_list*/,
                                            DLIList<Curve*> &/*ref_edge_list*/,
+                                           DLIList<TopologyBridge*> &temporary_bridges,
                                            DLIList<BodySM*>& /*new_body_list*/,
                                            bool /*keep_old_body*/ ) const
 {
@@ -1500,7 +1710,10 @@
 CubitStatus     FacetModifyEngine::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
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -1518,7 +1731,9 @@
                                            DLIList<BodySM*>& /*new_body_list*/,
                                            bool keep_old, /* keep old body */
                                           DLIList<TopologyBridge*> *new_tbs,
-                                          DLIList<TopologyBridge*> *att_tbs ) const
+                                          DLIList<TopologyBridge*> *att_tbs,
+                                          double *tol_in,
+                                          bool clean_up_slivers) const
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -1575,7 +1790,6 @@
   return CUBIT_FAILURE;
 }
 
-
 //===============================================================================
 // Function   : intersect
 // Member Type: PUBLIC
@@ -1695,6 +1909,11 @@
   
 }
 
+void FacetModifyEngine::get_possible_invalid_tbs(DLIList<TopologyBridge*> &bridges_in,
+                             DLIList<TopologyBridge*> &bridges_out)
+{
+}
+
 //===============================================================================
 // Function   : unite
 // Member Type: PUBLIC
@@ -1844,6 +2063,25 @@
   return CUBIT_FAILURE;
 }
 
+CubitStatus FacetModifyEngine::sweep_to_body( DLIList<Curve*> curve_list,
+                                               BodySM *target_body,
+                                               CubitVector distance,
+                                               DLIList<BodySM*> &new_bodies,
+                                               bool unite ) const
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus FacetModifyEngine::sweep_to_body( Surface *source_surface,
+                                               BodySM *target_body,
+                                               CubitVector distance,
+                                               DLIList<BodySM*> &new_bodies ) const
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
 //HEADER- Webcut-related functions
 
 //===============================================================================
@@ -1857,8 +2095,10 @@
                               const CubitVector &v1,
                               const CubitVector &v2,
                               const CubitVector &v3,
+                              DLIList<BodySM*>& neighbor_imprint_list,
                               DLIList<BodySM*>& results_list,
-                              bool imprint ) const
+                              ImprintType imprint_type,
+                              bool /*preview*/) const
 {
 
   MODIFY_CHECK_RETURN_FAILURE;
@@ -1980,8 +2220,10 @@
 //===============================================================================
 CubitStatus    FacetModifyEngine::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
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -1997,8 +2239,10 @@
 CubitStatus    FacetModifyEngine::webcut_across_translate( DLIList<BodySM*>& /*body_list*/,
                                                           Surface* /*plane_surf1*/,
                                                           Surface* /*plane_surf2*/,
+                                                          DLIList<BodySM*>& /*neighbor_imprint_list*/,
                                                           DLIList<BodySM*>& /*results_list*/,
-                                                          bool /*imprint*/ ) const
+                                                          ImprintType imprint_type,
+                                                          bool /*preview*/) const
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2013,8 +2257,10 @@
 //===============================================================================
 CubitStatus FacetModifyEngine::webcut_with_sheet(DLIList<BodySM*> & /*webcut_body_list*/,
                                                  BodySM * /*sheet_body*/,
+                                                 DLIList<BodySM*>& /*neighbor_imprint_list*/,
                                                  DLIList<BodySM*> & /*new_bodies*/,
-                                                 bool /*imprint*/ )
+                                                 ImprintType imprint_type,
+                                                 bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2027,11 +2273,13 @@
 // Author     : John Fowler
 // Date       : 10/02
 //===============================================================================
-CubitStatus FacetModifyEngine::webcut_with_extended_surf(DLIList<BodySM*> & /*webcut_body_list*/,
-                                                         Surface * /*extend_from*/,
+CubitStatus FacetModifyEngine::webcut_with_extended_sheet(DLIList<BodySM*> & /*webcut_body_list*/,
+                                                         DLIList<Surface*> & /*surface_list*/,
+                                                         DLIList<BodySM*>& /*neighbor_imprint_list*/,
                                                          DLIList<BodySM*> & /*new_bodies*/,
                                                          int & /*num_cut*/,
-                                                         bool /*imprint*/ )
+                                                         ImprintType imprint_type,
+                                                         bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2048,8 +2296,10 @@
                                             double radius,
                                             const CubitVector &axis,
                                             const CubitVector &center,
+                                            DLIList<BodySM*>& neighbor_imprint_list,
                                             DLIList<BodySM*>& results_list,
-                                            bool imprint )
+                                            ImprintType imprint_type,
+                                            bool /*preview*/ )
 {
 
   MODIFY_CHECK_RETURN_FAILURE;
@@ -2136,8 +2386,10 @@
                                       const CubitVector &/*center*/,
                                       const CubitVector* /*axes[3]*/, 
                                       const CubitVector &/*extension*/,
+                                      DLIList<BodySM*> &/*neighbor_imprint_list*/,
                                       DLIList<BodySM*> &/*results_list*/,
-                                      bool /*imprint*/ )
+                                      ImprintType imprint_type,
+                                      bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2156,8 +2408,10 @@
                                           const CubitVector* /*axes[2]*/,
                                           double /*width*/, 
                                           double /*height*/,
+                                          DLIList<BodySM*> &/*neighbor_imprint_list*/,
                                           DLIList<BodySM*> &/*results_list*/,
-                                          bool /*imprint*/ )
+                                          ImprintType imprint_type,
+                                          bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2173,8 +2427,10 @@
 CubitStatus FacetModifyEngine::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*/)
+                                              ImprintType imprint_type,
+                                              bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2244,6 +2500,21 @@
   return CUBIT_SUCCESS;
 }
 
+//===============================================================================
+// Function   : separate_surfaces
+// Member Type: PUBLIC
+// Description: Separates surfaces from sheet bodies into separate bodies.
+//              Connected surfaces will remain connected but be placed in a new
+//              body. NOT IMPLEMENTED
+// Author     : 
+// Date       : 
+//===============================================================================
+CubitStatus FacetModifyEngine::separate_surfaces( DLIList<Surface*> &surf_list,
+                                                  DLIList<BodySM*> &new_bodies )
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
 
 //===============================================================================
 // Function   : reverse_body
@@ -2310,12 +2581,18 @@
 // Date       : 10/02
 //===============================================================================
 CubitStatus  FacetModifyEngine::regularize_entity( GeometryEntity * /*old_entity_ptr*/,  
-                                                      BodySM *& /*new_body_ptr*/ )
+                                                      BodySM *& /*new_body_ptr*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
 }
 
+CubitStatus  FacetModifyEngine::test_regularize_entity( GeometryEntity *)
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
 //===============================================================================
 // Function   : offset_curves
 // Member Type: PUBLIC
@@ -2334,6 +2611,21 @@
 }
 
 //===============================================================================
+// Function   : split_curve
+// Member Type: PUBLIC
+// Description: 
+// Author     : Alex Hays
+// Date       : 9/08
+//===============================================================================
+CubitStatus  FacetModifyEngine::split_curve( Curve* curve_to_split,
+											const CubitVector& split_location,
+											DLIList<Curve*>& created_curves )
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
+//===============================================================================
 // Function   : trim_curve
 // Member Type: PUBLIC
 // Description: 
@@ -2350,16 +2642,17 @@
 }
 
 //===============================================================================
-// Function   : create_body_from_surfs
+// Function   : create_solid_bodies_from_surfs
 // Member Type: PUBLIC
 // Description: 
 // Author     : Steve Owen
 // Date       : 9/11/03
 //===============================================================================
-CubitStatus FacetModifyEngine::create_body_from_surfs(DLIList<Surface*> & ref_face_list,
-                                                      BodySM *& new_body,
+CubitStatus FacetModifyEngine::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
 {
   //MODIFY_CHECK_RETURN_FAILURE;
   
@@ -2427,10 +2720,24 @@
                                                surface_list,
                                                file_format );
 
+  BodySM *new_body = NULL;
   if (rv == CUBIT_SUCCESS)
   {
     surf_ptr = surface_list.get();
     new_body = surf_ptr->bodysm();
+
+    if( sheet == false ) 
+    {
+      CubitVector centroid;
+      double volume = 0.0;
+      new_body->mass_properties( centroid, volume);
+      if( volume <= 0.0 )
+      {
+        FacetQueryEngine::instance()->delete_solid_model_entities(new_body);
+        PRINT_INFO("Failing...Resulting body has no volume.\n");
+        return CUBIT_FAILURE; 
+      }
+    }
   
     // delete the old model
   
@@ -2460,6 +2767,9 @@
     new_body = NULL;
   }
 
+  if( new_body  )
+    new_bodies.append( new_body );
+
   return CUBIT_SUCCESS;
 }
 
@@ -2665,6 +2975,31 @@
 }
 
 //=============================================================================
+// Function   : tweak_bend
+// Member Type: PUBLIC
+// Description: Bend solid bodies based on a bend radius and angle
+// Author     : 
+// Date       : 
+//=============================================================================
+CubitStatus FacetModifyEngine::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
+{
+	PRINT_ERROR("Option not supported for mesh based geometry.\n");
+	return CUBIT_FAILURE;
+}
+
+//=============================================================================
 // Function   : tweak_chamfer
 // Member Type: PUBLIC
 // Description: Chamfer curves on solid bodies.  The left and right offsets are
@@ -2813,6 +3148,8 @@
 //=============================================================================
 CubitStatus FacetModifyEngine::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
@@ -2831,6 +3168,8 @@
 //=============================================================================
 CubitStatus FacetModifyEngine::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
@@ -2850,7 +3189,6 @@
 CubitStatus FacetModifyEngine::tweak_remove( DLIList<Surface*> & /*surface_list*/,
                                              DLIList<BodySM*> & /*new_bodysm_list*/,
                                              CubitBoolean /*extend_adjoining*/,
-                                             CubitBoolean /*keep_surface*/,
                                              CubitBoolean /*keep_old_body*/,
                                              CubitBoolean /*preview*/ ) const
 {
@@ -2886,6 +3224,8 @@
 CubitStatus FacetModifyEngine::tweak_target( DLIList<Surface*> & /*surface_list*/,
                                              DLIList<Surface*> & /*target_surf_list*/,
                                              DLIList<BodySM*> & /*new_bodysm_list*/,
+                                             CubitBoolean /*extend_flg*/,
+                                             CubitPlane * /*limit_plane*/,
                                              CubitBoolean /*reverse_flg*/,
                                              CubitBoolean /*keep_old_body*/,
                                              CubitBoolean /*preview*/ ) const
@@ -2905,9 +3245,12 @@
 CubitStatus FacetModifyEngine::tweak_target( DLIList<Curve*> & /*curve_list*/,
                                              DLIList<Surface*> & /*target_surf_list*/, 
                                              DLIList<BodySM*> & /*new_bodysm_list*/,
+                                             CubitBoolean /*extend_flg*/,
+                                             CubitPlane * /*limit_plane*/,
                                              CubitBoolean /*reverse_flg*/,
                                              CubitBoolean /*keep_old_body*/,
-                                             CubitBoolean /*preview*/ ) const
+                                             CubitBoolean /*preview*/,
+                                             double /*max_area_increase = 0*/ ) const
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -2925,16 +3268,41 @@
 //=============================================================================
 CubitStatus FacetModifyEngine::tweak_target( DLIList<Curve*> & /*curve_list*/,
                                              DLIList<Curve*> & /*target_curve_list*/, 
-                                             DLIList<BodySM*> & /*new_bodysm_list*/, 
+                                             DLIList<BodySM*> & /*new_bodysm_list*/,
+                                             CubitBoolean /*extend_flg*/,
+                                             CubitPlane * /*limit_plane*/,
                                              CubitBoolean /*reverse_flg*/,
                                              CubitBoolean /*keep_old_body*/,
+                                             CubitBoolean /*preview*/,
+                                             double /*max_area_increase = 0*/ ) const
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
+//=============================================================================
+// 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     :
+// Date       :
+//=============================================================================
+CubitStatus FacetModifyEngine::tweak_target( Point * /*point_ptr*/,
+                                             DLIList<Surface*> & /*modify_surface_list*/,
+                                             CubitVector & /*target_loc*/,
+                                             BodySM *& /*new_bodysm_ptr*/,
+                                             CubitBoolean /*keep_old_body*/,
                                              CubitBoolean /*preview*/ ) const
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
 }
 
-
 CubitStatus FacetModifyEngine::remove_curve_slivers( BodySM* /*body*/, 
                                                      double /*lengthlimit*/ ) const
 {
@@ -2982,11 +3350,28 @@
                                                       BodySM*& /*new_body*/, 
                                                       double /*offset_distance*/ ) const
 {
-   PRINT_ERROR("Function not implemented in this engine.\n");
+   PRINT_ERROR("Function not implemented in Facet engine.\n");
    return CUBIT_FAILURE;
 }
 
 //================================================================================
+// Description: Creates an offset sheet.
+// Author     : 
+// Date       :
+//================================================================================
+CubitStatus
+FacetModifyEngine::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
+{
+  PRINT_ERROR("Function not implemented in Facet engine.\n");
+  return CUBIT_FAILURE;
+}
+
+//================================================================================
 // Description: Creates an offset body.
 // Author     : Tyronne Lim
 // Date       : 08/18/03
@@ -3005,7 +3390,8 @@
 // Date       : 08/18/03
 //================================================================================
 CubitStatus FacetModifyEngine::create_skin_surface( DLIList<Curve*>& /*curves*/, 
-                                                    BodySM*& /*new_body*/ ) const
+                                                    BodySM*& /*new_body*/,
+                                                    DLIList<Curve*>& /*guides*/) const
 {
    PRINT_ERROR("Function not implemented in this engine.\n");
    return CUBIT_FAILURE;
@@ -3065,6 +3451,13 @@
    return CUBIT_FAILURE;
 }
 
+CubitStatus FacetModifyEngine::create_surface( DLIList<Point*> & /*points*/,
+                                               BodySM *& /*new_body*/ ) const
+{
+   PRINT_ERROR("Function not implemented in this engine.\n");
+   return CUBIT_FAILURE;
+}
+
 //================================================================================
 // Description: Creates a weld surface.
 // Author     : Tyronne Lim
@@ -3081,6 +3474,17 @@
    return CUBIT_FAILURE;
 }
 
+
+CubitStatus FacetModifyEngine::stitch( DLIList<BodySM*> &bodies_to_stitch,
+                                       DLIList<BodySM*> &new_bodies,
+                                       bool tighten_gaps,
+                                       double tolerance )const 
+{
+   PRINT_ERROR("Function not implemented in this engine.\n");
+   return CUBIT_FAILURE;
+}
+
+
 //================================================================================
 //    Facet-based geometry entities
 //    Methods for building specific facet-based geometry entities
@@ -3624,6 +4028,7 @@
     rv = cholla_ptr->create_geometry( use_feature_angle, feature_angle, 
                                       interp_order, smooth_non_manifold, 
                                       split_surfaces );
+    
   }
   return rv;
 }
@@ -3811,6 +4216,8 @@
       ChollaPoint *fpm1_ptr = fpoint_list.get_and_step();
       CubitPoint *start_point, *end_point;
       chcurv_ptr->get_ends( start_point, end_point );
+      assert(start_point != NULL);
+      assert(end_point != NULL);
       if (fpm0_ptr->get_facets() != start_point)
       {
         ChollaPoint *temp_ptr;
@@ -4803,8 +5210,10 @@
                                  bool up_to_next, 
                                  Surface *stop_surf, 
                                  Curve *curve_to_sweep_along, 
+                                 DLIList<BodySM*> &/*neighbor_imprint_list*/,
                                  DLIList<BodySM*> &results_list,
-                                 CubitBoolean imprint)
+                                 ImprintType imprint_type,
+                                 bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -4817,8 +5226,10 @@
                                  bool through_all, 
                                  Surface *stop_surf, 
                                  Curve *curve_to_sweep_along, 
+                                 DLIList<BodySM*> &/*neighbor_imprint_list*/,
                                  DLIList<BodySM*> &results_list,
-                                 CubitBoolean imprint)
+                                 ImprintType imprint_type,
+                                 bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -4832,8 +5243,10 @@
                                  double angle, 
                                  Surface *stop_surf, 
                                  bool up_to_next, 
+                                 DLIList<BodySM*> &/*neighbor_imprint_list*/,
                                  DLIList<BodySM*> &results_list,
-                                 CubitBoolean imprint)
+                                 ImprintType imprint_type,
+                                 bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -4846,8 +5259,10 @@
                                  const CubitVector &sweep_axis, 
                                  double angle, 
                                  Surface *stop_surf, 
+                                 DLIList<BodySM*> &/*neighbor_imprint_list*/,
                                  DLIList<BodySM*> &results_list,
-                                 CubitBoolean imprint)
+                                 ImprintType imprint_type,
+                                 bool /*preview*/)
 {
   PRINT_ERROR("Option not supported for mesh based geometry.\n");
   return CUBIT_FAILURE;
@@ -4867,4 +5282,32 @@
   return CUBIT_FAILURE;
 }
 
+CubitStatus FacetModifyEngine::tolerant_imprint( DLIList<Surface*> &surfs_in,
+      DLIList<BodySM*> &new_bodysm_list)  const
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus FacetModifyEngine::tolerant_imprint_surface_with_curves( 
+                                                   Surface * /*surface_to_imprint*/,
+                                                   DLIList<Curve*> & /*curves*/,
+                                                   DLIList<TopologyBridge*> &temporary_bridges,
+                                                   BodySM *& /*new_body*/, 
+                                                   DLIList<TopologyBridge*> *new_tbs,
+                                                   DLIList<TopologyBridge*> *att_tbs) const 
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus FacetModifyEngine::curve_surface_intersection( Surface * /*surface*/, 
+                                                           Curve* /*curve*/,
+                                                           DLIList<Curve*> &/*new_curves*/ ) const
+{
+  PRINT_ERROR("Option not supported for mesh based geometry.\n");
+  return CUBIT_FAILURE;
+}
+
+
 // EOF

Modified: cgm/branches/cubit/geom/facet/FacetModifyEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetModifyEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetModifyEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -68,6 +68,10 @@
   virtual ~FacetModifyEngine();
   //- virtual destructor
   
+  virtual bool supports_interoperability() { return false; }
+    //- Returns whether intermixing of real and virtual geometry operations
+    //- is supported for the current geometry kernel.
+
   virtual Point* make_Point( CubitVector const& point) const ;
   
   virtual Curve* make_Curve(Curve *curve_ptr) const;
@@ -93,10 +97,17 @@
     Point const* point2_ptr,
     CubitVector const* intermediate_point_ptr,
     CubitSense sense) const;
+
+  virtual Curve* make_Curve( DLIList<CubitVector*>& point_list,
+                             DLIList<CubitVector*>& point_tangents) const;
   
   
   virtual Surface* make_Surface( Surface *old_surface_ptr,
     CubitBoolean extended_from = CUBIT_FALSE) const;
+
+  virtual BodySM* make_extended_sheet( DLIList<Surface*> &surface_list,
+                                       CubitBox *clip_box = NULL,
+                                       bool preview = false ) const;
   
   virtual Surface* make_Surface( GeometryType surface_type,
     DLIList<Curve*>& curve_list,
@@ -157,25 +168,32 @@
   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=CUBIT_TRUE) const;
   
   virtual CubitStatus imprint( DLIList<Surface*> &ref_face_list,
     DLIList<Curve*> &ref_edge_list,
+    DLIList<TopologyBridge*> &temporary_bridges,
     DLIList<BodySM*>& new_body_list,
     bool keep_old_body ) const;
 
   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;
   
   virtual CubitStatus imprint( DLIList<BodySM*> &body_list,
     DLIList<CubitVector*> &vector_list,
     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;
   
   virtual CubitStatus imprint_projected_edges( DLIList<Surface*> &ref_face_list,
     DLIList<Curve*> &ref_edge_list,
@@ -194,7 +212,18 @@
     DLIList<Curve*> &ref_edge_list_in,
     DLIList<Curve*> &ref_edge_list_new,
     bool print_error = true ) const;
-  
+ 
+  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 curve_surface_intersection( Surface *surface, 
+                                                  Curve* curve,
+                                                  DLIList<Curve*> &new_curves ) const;
+
   virtual CubitStatus intersect(BodySM* tool_body_ptr,
     DLIList<BodySM*> &from_bodies,
     DLIList<BodySM*> &new_bodies,
@@ -209,7 +238,10 @@
   
   virtual CubitStatus unite(DLIList<BodySM*> &bodies, 
                             DLIList<BodySM*> &newBodies,
-    bool keep_old = CUBIT_FALSE) const;
+                            bool keep_old = CUBIT_FALSE) const;
+
+  virtual void get_possible_invalid_tbs(DLIList<TopologyBridge*> &bridges_in,
+                             DLIList<TopologyBridge*> &bridges_out);
   
   virtual CubitStatus thicken(DLIList<BodySM*>& bodies, 
     DLIList<BodySM*>& new_bodies,
@@ -256,6 +288,19 @@
     double draft_angle = 0.0,
     int draft_type = 0,
     bool rigid = CUBIT_FALSE ) 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;
  
 
     virtual CubitStatus webcut_with_sweep_surfaces(
@@ -268,8 +313,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);
 
     virtual CubitStatus webcut_with_sweep_curves(
                           DLIList<BodySM*> &blank_bodies,
@@ -278,8 +325,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);
 
     virtual CubitStatus webcut_with_sweep_curves_rotated(
                           DLIList<BodySM*> &blank_bodies,
@@ -288,8 +337,10 @@
                           const CubitVector &sweep_axis,
                           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);
 
     virtual CubitStatus webcut_with_sweep_surfaces_rotated(
                             DLIList<BodySM*> &blank_bodies,
@@ -299,65 +350,84 @@
                             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); 
 
   //HEADER- Webcut-related functions
   virtual CubitStatus webcut(DLIList<BodySM*>& webcut_body_list,
     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;
   
   virtual CubitStatus webcut(DLIList<BodySM*>& webcut_body_list,
     BodySM const* tool_body,
+    DLIList<BodySM*>& neighbor_imprint_list,
     DLIList<BodySM*>& results_list,
-    bool imprint = false ) const;
+    ImprintType imprint_type = NO_IMPRINT,
+    bool preview = false) const;
   
   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;
   
   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);
   
-  virtual CubitStatus webcut_with_extended_surf(DLIList<BodySM*> &webcut_body_list,
-    Surface *extend_from,
+  virtual CubitStatus webcut_with_extended_sheet(DLIList<BodySM*> &webcut_body_list,
+    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);
   
   virtual CubitStatus webcut_with_cylinder(DLIList<BodySM*> &webcut_body_list,
     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,
+    bool preview = false);
   
   virtual CubitStatus webcut_with_brick( DLIList<BodySM*>& webcut_body_list, 
     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,
+    bool preview = false);
   
   virtual CubitStatus webcut_with_planar_sheet( DLIList<BodySM*>& webcut_body_list,
     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);
   
   virtual CubitStatus webcut_with_curve_loop(DLIList<BodySM*> &webcut_body_list,
     DLIList<Curve*> &ref_edge_list,
     DLIList<BodySM*>& results_list,
-    bool imprint = false );
+    DLIList<BodySM*>& neighbor_imprint_list,
+    ImprintType imprint_type = NO_IMPRINT,
+    bool preview = false);
   
   virtual CubitStatus section( DLIList<BodySM*> &section_body_list,
     const CubitVector &point_1,
@@ -370,6 +440,9 @@
   
   virtual CubitStatus split_body( BodySM *body_ptr,
     DLIList<BodySM*> &new_bodies );
+
+  virtual CubitStatus separate_surfaces( DLIList<Surface*> &surf_list,
+                                         DLIList<BodySM*> &new_bodies );
   
   virtual CubitStatus reverse_body( BodySM *body_to_reverse );
   
@@ -381,6 +454,7 @@
   
   virtual CubitStatus regularize_entity(GeometryEntity *old_entity_ptr,  
                                            BodySM *&new_body_ptr);
+  virtual CubitStatus test_regularize_entity( GeometryEntity *old_refentity_ptr);
   
   virtual CubitStatus offset_curves( DLIList<Curve*>& ref_edge_list, 
                                      DLIList<Curve*>& result_curve_list,
@@ -390,15 +464,20 @@
   
   virtual CubitStatus scale ( BodySM *&body, const CubitVector& factors );
 
+  virtual CubitStatus  split_curve( Curve* curve_to_split,
+										const CubitVector& split_location,
+										DLIList<Curve*>& created_curves );
+  
   virtual Curve* trim_curve( Curve* trim_curve, 
                              const CubitVector& trim_vector,
                              const CubitVector& keep_vector,
                              bool keep_old = false );
   
-  virtual CubitStatus create_body_from_surfs(DLIList<Surface*> &ref_face_list,
-    BodySM *&new_body,
-    bool keep_old = false,
-    bool heal = false) const;
+  virtual CubitStatus create_solid_bodies_from_surfs(DLIList<Surface*> &ref_face_list,
+                                                     DLIList<BodySM*> &new_bodies,
+                                                     bool keep_old = false,
+                                                     bool heal = true,
+                                                     bool sheet = false ) const;
   
   virtual Curve* create_arc_three( Point* ref_vertex1, 
                                    Point* ref_vertex2,
@@ -468,6 +547,22 @@
 					       BodySM *body_to_trim_to,
 					       BodySM *&midsurface_body ) const;
   
+  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 ) 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,
@@ -540,26 +635,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
@@ -578,6 +676,8 @@
   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;
@@ -587,9 +687,12 @@
   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 surface_area_increase_allowed = 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.
@@ -598,13 +701,30 @@
   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 surface_area_increase_allowed = 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.
     */
+
+  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, double lengthlimit ) const;
 
@@ -621,9 +741,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,
@@ -646,12 +781,21 @@
   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*> &points,
+                                      BodySM *&new_body ) const;
+
   virtual CubitStatus create_weld_surface( CubitVector &root,
                                            Surface *ref_face1, double leg1, Surface *ref_face2, double leg2,
                                            BodySM *&new_body ) const;
 
+  virtual CubitStatus stitch( DLIList<BodySM*> &bodies_to_stitch,
+                              DLIList<BodySM*> &new_bodies,
+                              bool tighten_gaps,
+                              double tolerance )const; 
+
+
   //--------------------------------------------------------------
    //- Methods for building specific facet-based geometry entities
    //--------------------------------------------------------------
@@ -814,6 +958,15 @@
     // From the facet surface list, create geometric surface,
     // loops and coedges for each surface in the list  
 
+    virtual CubitStatus tolerant_imprint(DLIList<Surface*> &surfs_in,
+      DLIList<BodySM*> &new_bodysm_list) const;
+    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; 
+
     CubitStatus tolerant_imprint( DLIList<BodySM*> &bodies_in,
                                   DLIList<BodySM*> &new_bodies,
                                    DLIList<TopologyBridge*> *new_tbs = NULL,

Modified: cgm/branches/cubit/geom/facet/FacetParamTool.cpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetParamTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetParamTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -191,7 +191,7 @@
 // Author: chynes
 // Date: 7/10/02
 //===================================================================================
-CubitStatus FacetParamTool::transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location) 
+CubitStatus FacetParamTool::transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location) 
 {
 	DLIList<CubitFacet *> facet_list; 
 	FacetEvalTool *fetool;
@@ -252,7 +252,7 @@
 // Author: chynes
 // Date: 7/10/02
 //===================================================================================
-CubitStatus FacetParamTool::transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location) 
+CubitStatus FacetParamTool::transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location) 
 {
 	CubitStatus rv = CUBIT_SUCCESS;
 	CubitFacet *tri_ptr;
@@ -328,7 +328,7 @@
 // Date: 7/10/02
 //===================================================================================
 CubitStatus FacetParamTool::
-locate_point_in_uv(FacetSurface *surf, CubitVector &the_point, CubitFacet *&tri_ptr) 
+locate_point_in_uv(FacetSurface *surf, const CubitVector &the_point, CubitFacet *&tri_ptr) 
 {
 	CubitStatus rv = CUBIT_SUCCESS;
 
@@ -392,7 +392,7 @@
 // Date: 7/10/02
 //===================================================================================
 CubitStatus FacetParamTool::
-exhaustive_locate_point_in_uv(FacetSurface *surf, CubitVector &the_point, CubitFacet *&tri_ptr) 
+exhaustive_locate_point_in_uv(FacetSurface *surf, const CubitVector &the_point, CubitFacet *&tri_ptr) 
 {
 	CubitStatus rv = CUBIT_SUCCESS;
 

Modified: cgm/branches/cubit/geom/facet/FacetParamTool.hpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetParamTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetParamTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -32,13 +32,13 @@
 
   CubitStatus set_up_space(void);
 
-  CubitStatus transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location);
+  CubitStatus transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location);
 
-  CubitStatus transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location);
+  CubitStatus transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location);
 
-  CubitStatus locate_point_in_uv(FacetSurface *surf, CubitVector &the_point, CubitFacet *&tri_ptr);
+  CubitStatus locate_point_in_uv(FacetSurface *surf, const CubitVector &the_point, CubitFacet *&tri_ptr);
 
-  CubitStatus exhaustive_locate_point_in_uv(FacetSurface *surf, CubitVector &the_point, CubitFacet *&tri_ptr); 
+  CubitStatus exhaustive_locate_point_in_uv(FacetSurface *surf, const CubitVector &the_point, CubitFacet *&tri_ptr); 
 
 #ifdef BOYD14
   CubitStatus export_facets(int numn, int numf, double *points, int *facets);

Modified: cgm/branches/cubit/geom/facet/FacetQueryEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetQueryEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetQueryEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -414,13 +414,13 @@
 // Date       :
 //================================================================================
 CubitStatus FacetQueryEngine::get_graphics( Surface* surface_ptr,
-                                                     int& number_triangles,
-                                                     int& number_points,
-                                                     int& number_facets,
                                                      GMem* gMem,
                                                      unsigned short ,
                                                      double, double ) const
 {
+  if( !gMem )
+    return CUBIT_FAILURE;
+
     //  get the FacetSurface.
   int i;
   FacetSurface *facet_surf_ptr = CAST_TO(surface_ptr,FacetSurface);
@@ -434,16 +434,13 @@
 
     // set return values, and if GMem is NULL return
     // (caller just wanted to know the counts.)
-  number_facets = surface_facets.size() * 4;
-  number_points = surface_points.size();
-  number_triangles = surface_facets.size();
-  if( !gMem )
-    return CUBIT_SUCCESS;
+  int number_points = surface_points.size();
+  int number_triangles = surface_facets.size();
 
 
     // Allocate space in GMem
-  gMem->allocate_tri(surface_facets.size());
-  gMem->fListCount = number_facets;
+  gMem->allocate_tri(number_triangles);
+  gMem->fListCount = surface_facets.size() * 4;
   gMem->pointListCount = number_points;
 
     // Copy points to GMem
@@ -483,7 +480,6 @@
 // Date       :
 //================================================================================
 CubitStatus FacetQueryEngine::get_graphics( Curve* curve_ptr,
-                                            int& num_points,
                                             GMem* gMem,
                                             double /*tolerance*/ ) const
 {
@@ -497,12 +493,14 @@
   facet_curv_ptr->get_points(curve_points);
   curve_points.reset();
   curve_facets.reset();
-  num_points = curve_points.size();
+  int num_points = curve_points.size();
   GPoint *new_point_list = new GPoint[num_points];
   int *new_facet_list = new int [number_facets*3];
   int ii;
+  CubitPoint *cur_pnt;
   for ( ii = 0; ii < num_points; ii++ )
   {
+    cur_pnt = curve_points.get();
     new_point_list[ii].x = curve_points.get()->x();
     new_point_list[ii].y = curve_points.get()->y();
     new_point_list[ii].z = curve_points.get()->z();
@@ -1748,7 +1746,7 @@
                                                  CubitBoolean free_surfaces)
 {
   errno = 0;
-  FILE *file_ptr = fopen(file_name, "r");
+  FILE *file_ptr = fopen(file_name, "rb");
   if (!file_ptr)
   {
     PRINT_ERROR("Cannot open file: %s (%s)\n", file_name, strerror(errno) );
@@ -2296,18 +2294,169 @@
   return CUBIT_SUCCESS;
 }
 
-CubitStatus FacetQueryEngine::fire_ray(BodySM *,
-                                          const CubitVector &,
-                                          const CubitVector &,
-                                          DLIList<double>&,
-                                          DLIList<GeometryEntity*> *) const
+CubitStatus FacetQueryEngine::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
 {
-  PRINT_ERROR("FacetQueryEngine::fire_ray not yet implemented.\n");
-  return CUBIT_FAILURE;
+  
+  TopologyBridge *bridge_ptr;
+  int i, j;
+  bool hit = false;
+
+  DLIList<double> tmp_ray_params;
+  DLIList<FacetSurface*> at_surface_list;
+  DLIList<FacetCurve*> at_curve_list;
+  DLIList<FacetPoint*> at_point_list;
+
+  if( ray_radius == 0.0 )
+	  ray_radius = get_sme_resabs_tolerance();
+  
+  at_entity_list.reset();
+  for (i=0; i<at_entity_list.size(); i++)
+  {
+	  hit = false;
+	  bridge_ptr = at_entity_list.get_and_step();
+
+	  //determine which type of geometry we have. body, lump, face, curve?
+	  if (CAST_TO(bridge_ptr, FacetBody))
+	  {
+		  FacetBody* f_body = CAST_TO(bridge_ptr, FacetBody);
+		  DLIList<Surface*> surface_list;
+		  f_body->surfaces(surface_list);
+	  }
+	  else if (CAST_TO(bridge_ptr, FacetLump))
+	  {
+		  FacetLump* f_lump = CAST_TO(bridge_ptr, FacetLump);
+		  PRINT_INFO("Found FacetLump.\n");
+		  DLIList<FacetSurface*> f_surface_list;
+		  f_lump->get_surfaces(f_surface_list);
+		  at_surface_list.merge_unique(f_surface_list);
+	  }
+	  else if (CAST_TO(bridge_ptr, Surface))
+	  {
+		  FacetSurface* f_surface = CAST_TO(bridge_ptr, FacetSurface);
+		  
+		  DLIList<CubitFacet*> facet_list;
+		  DLIList<CubitPoint*> point_list;
+		  f_surface->get_my_facets(facet_list, point_list);
+
+		  //PRINT_INFO("There are %d facets.\n", facet_list.size());
+
+		  //RTree<CubitFacet*> rtree(ray_radius);
+		  //for (j=0; j<facet_list.size(); j++)
+			//  rtree.add(facet_list.get_and_step();
+		  
+		  //DLIList<CubitFacet*> facet_list1;
+		  //CubitBox range_box();
+		  //make range box for the ray
+		  //rtree.find(range_box, facet_list1);
+
+		  CubitVector* intersection_pt = new CubitVector();		
+	      double distance;
+
+		  for (j=0; j<facet_list.size(); j++)
+		  {
+			  if (hit)
+				  break;
+
+			  CubitFacet* facet = facet_list.get_and_step();
+
+			  // Find intersection of ray with triangle
+			  int rv = FacetEvalTool::intersect_ray(origin, direction, facet, intersection_pt, distance);
+
+			  switch (rv)
+			  {
+			  case -1:
+				  //PRINT_INFO("Facet is degenerate (segment or point).\n");
+				  break;
+			  case 0:
+				  //PRINT_INFO("Ray does not intersect the facet.\n");
+				  break;
+			  case 1:
+				  {
+					  hit = true;
+					  if (hit_entity_list)
+						  hit_entity_list->append(bridge_ptr);
+					  ray_params.append(distance);
+					  //PRINT_INFO("Ray intersects facet at %f, %f, %f.\n", intersection_pt->x(), intersection_pt->y(), intersection_pt->z());
+					
+					  continue;
+				  }
+			  case 2:
+				  //PRINT_INFO("Ray is in same plane as the facet.\n");
+				  break;
+			  }
+		  }
+          if (intersection_pt)
+              delete intersection_pt;
+	  
+	  }
+	  else if (CAST_TO(bridge_ptr, Curve))
+	  {
+		  FacetCurve* f_curve = CAST_TO(bridge_ptr, FacetCurve);
+		  DLIList<CubitFacetEdge*> facet_edge_list;
+		  f_curve->get_facets(facet_edge_list);
+
+		  //PRINT_INFO("There are %d facetedges.\n", facet_edge_list.size());
+          CubitVector* intersection_pt = new CubitVector();		
+          double distance;
+
+          for (j=0; j<facet_edge_list.size(); j++)
+		  {
+			  if (hit)
+				  break;
+
+			  CubitFacetEdge* facet_edge = facet_edge_list.get_and_step();
+
+			  int rv = FacetEvalTool::intersect_ray(origin, direction, facet_edge, intersection_pt, distance);
+
+			  switch (rv)
+			  {
+			  case -1:
+				  //PRINT_INFO("Facet is degenerate (segment or point).\n");
+				  break;
+			  case 0:
+				  //PRINT_INFO("Ray does not intersect the facet edge.\n");
+				  break;
+			  case 1:
+				  {
+					  hit = true;
+					  if (hit_entity_list)
+						  hit_entity_list->append(bridge_ptr);
+					  ray_params.append(distance);
+					  //PRINT_INFO("Ray intersects facet at %f, %f, %f.\n", intersection_pt->x(), intersection_pt->y(), intersection_pt->z());
+					
+					  continue;
+				  }
+			  case 2:
+				  //PRINT_INFO("Ray is parallel to the facet.\n");
+				  break;
+			  }
+
+		  }
+          if (intersection_pt)
+              delete intersection_pt;
+	  }
+	  else if (CAST_TO(bridge_ptr, FacetPoint))
+	  {
+		  FacetPoint* f_point = CAST_TO(bridge_ptr, FacetPoint);
+		  at_point_list.append_unique(f_point);
+	  }
+	  else
+		  ;//PRINT_INFO("Cast error in FacetQueryEngine::fire_ray.\n");
+
+  }
+
+  return CUBIT_SUCCESS;
 }
-  //- fire a ray at the specified body, returning the entities hit and
-  //- the parameters along the ray; return CUBIT_FAILURE if error
+  //- fire a ray at the specified entities, returning the parameters
+  //- (distances) along the ray and optionally the entities hit
 
+
 double FacetQueryEngine::get_sme_resabs_tolerance() const
 {
   PRINT_ERROR("FacetQueryEngine::get_sme_resabs_tolerance not yet implemented.\n");
@@ -2456,7 +2605,10 @@
 
   unsigned int dummy_int=0;
 
-  while (isspace(line[dummy_int])&& dummy_int<strlen(line)) dummy_int++;
+  // One of the functions called by isspace() has an assert that can fail in debug mode if 
+  // line[dummy_int] is negative so check for it here.
+  while (line[dummy_int] > -1 && isspace(line[dummy_int]) && dummy_int < strlen(line)) 
+    dummy_int++;
 
   if (strlen(line)-dummy_int>5)
   {
@@ -3266,7 +3418,10 @@
       DLIList <Surface *> shell_surfaces;
       DLIList <CubitPoint *> mypoint_list;
       facet_list_ptr = shell_facet_list.get_and_step();
-      rv = FacetModifyEngine::instance()->build_facet_surface( NULL,
+      if(facet_list_ptr == NULL)
+        rv = CUBIT_FAILURE;
+      else
+        rv = FacetModifyEngine::instance()->build_facet_surface( NULL,
                                *facet_list_ptr, mypoint_list,
                                feature_angle, interp_order,
                                smooth_non_manifold,
@@ -3389,13 +3544,30 @@
     return CUBIT_FAILURE;
   }
 
-  int n = sscanf(line, "%d %d", &npoints, &nfacets);
-  if (n < 1 || n > 2 && file_format == CUBIT_FACET_FILE )
+  int n;
+  char type_header[8];
+  CubitBoolean is_off_file = CUBIT_FALSE;
+  n = sscanf( line, "%s", type_header );
+  if( !strcmp( type_header, "OFF" ) || 
+      !strcmp( type_header, "off" ) )
   {
-    PRINT_ERROR("Format error in facet file %s on line %d\n", file_name, iline);
-    fclose( fp );
-    return CUBIT_FAILURE;
+    PRINT_INFO( "Reading OFF file...\n" );
+    fgets(line, 128, fp);
+    iline++;
+    is_off_file = CUBIT_TRUE;
   }
+  
+  n = sscanf(line, "%d %d", &npoints, &nfacets);
+  if( !is_off_file )
+  {
+    if (n < 1 || n > 2 && file_format == CUBIT_FACET_FILE )
+    {
+      PRINT_ERROR("Format error in facet file %s on line %d\n", file_name, iline);
+      fclose( fp );
+      return CUBIT_FAILURE;
+    }
+  }
+
   if (npoints <= 0)
   {
     PRINT_ERROR("Expecting number of nodes in facet file %s on line %d\n", file_name, iline);
@@ -3434,15 +3606,30 @@
       fclose( fp );
       return CUBIT_FAILURE;
     }
-
-    n = sscanf(line, "%d %lf %lf %lf", &id, &xx, &yy, &zz );
-    if (n != 4)
+    if( is_off_file )
     {
-      PRINT_ERROR("Format error in facet file %s on line %d\n", file_name, iline);
-      PRINT_INFO("  Expecting 1 integer and 3 doubles, but instead read %d values\n", n);
-      fclose( fp );
-      return CUBIT_FAILURE;
+      n = sscanf( line, "%lf %lf %lf", &xx, &yy, &zz );
+      id = ii;
+      if (n != 3)
+      {
+        PRINT_ERROR("Format error in OFF file %s on line %d\n", file_name, iline);
+        PRINT_INFO("  Expecting 3 doubles, but instead read %d values\n", n);
+        fclose( fp );
+        return CUBIT_FAILURE;
+      }
     }
+    else
+    {
+      n = sscanf(line, "%d %lf %lf %lf", &id, &xx, &yy, &zz );
+      if (n != 4)
+      {
+        PRINT_ERROR("Format error in facet file %s on line %d\n", file_name, iline);
+        PRINT_INFO("  Expecting 1 integer and 3 doubles, but instead read %d values\n", n);
+        fclose( fp );
+        return CUBIT_FAILURE;
+      }
+    }
+    
     new_point = (CubitPoint *) new CubitPointData( xx, yy, zz );
     new_point->set_id( id );
     add_hash_point( new_point );
@@ -3523,28 +3710,56 @@
     }
     else
     {
-      n = sscanf(line, "%d %d %d %d %d", &id, &conn[4*ii], &conn[4*ii+1],
-                 &conn[4*ii+2], &conn[4*ii+3] );
+//       if( is_off_file )
+//       {
+//         n = sscanf( line, "%d %d %d %d", &id, &conn[4*ii], &conn[4*ii+1],
+//                     &conn[4*ii+2], &conn[4*ii+3] );
+//         if (n < 4 || n > 5)
+//         {
+//           PRINT_ERROR("Format error in OFF file %s on line %d reading facets\n", file_name, iline);
+//           PRINT_INFO("  Expecting 4 or 5 integers, but instead read %d values\n", n);
+//           PRINT_INFO("  For example:  <facet_size> <i0> <i1> <i2> [<i3>]\n");
+//           fclose( fp );
+//           return CUBIT_FAILURE;
+//         } 
 
-      if (n < 4 || n > 5)
-      {
-        PRINT_ERROR("Format error in facet file %s on line %d reading facets\n", file_name, iline);
-        PRINT_INFO("  Expecting 4 or 5 integers, but instead read %d values\n", n);
-        PRINT_INFO("  For example:  <id> <i0> <i1> <i2> [<i3>]\n");
-        fclose( fp );
-        return CUBIT_FAILURE;
-      }
-
-        // for triangles -- duplicate the point
-      if (n==4)
-      {
-        conn[4*ii+3] = conn[4*ii+2];
-        ntri++;
-      }
-      else
-      {
-        nquad++;
-      }
+//           // for triangles -- duplicate the point
+// //        if( n==3 )
+//         if( id==3 )
+//         {
+//           conn[4*ii+3] = conn[4*ii+2];
+//           ntri++;
+//         }
+//         else
+//         {
+//           nquad++;
+//         }
+//       }
+//       else
+//       {
+        n = sscanf(line, "%d %d %d %d %d", &id, &conn[4*ii], &conn[4*ii+1],
+                   &conn[4*ii+2], &conn[4*ii+3] );
+        
+        if (n < 4 || n > 5)
+        {
+          PRINT_ERROR("Format error in facet file %s on line %d reading facets\n", file_name, iline);
+          PRINT_INFO("  Expecting 4 or 5 integers, but instead read %d values\n", n);
+          PRINT_INFO("  For example:  <id> <i0> <i1> <i2> [<i3>]\n");
+          fclose( fp );
+          return CUBIT_FAILURE;
+        }
+      
+          // for triangles -- duplicate the point
+        if (n==4)
+        {
+          conn[4*ii+3] = conn[4*ii+2];
+          ntri++;
+        }
+        else
+        {
+          nquad++;
+        }
+//       }
     }
   }
 
@@ -4756,6 +4971,9 @@
   return CUBIT_FAILURE;
 }
 
+
+
+
 //===============================================================================
 // Function   : bodies_overlap
 // Member Type: PUBLIC
@@ -4788,4 +5006,11 @@
     */
 }
 
+CubitBoolean FacetQueryEngine::volumes_overlap (Lump * /*lump_ptr_1*/,
+                                                Lump * /*lump_ptr_2*/ ) const
+{
+  PRINT_ERROR("Currently, Cubit is unable to determine overlap for Facet-based geometry.\n");
+  return CUBIT_FALSE;
+}
+
 //EOF

Modified: cgm/branches/cubit/geom/facet/FacetQueryEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetQueryEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetQueryEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -56,19 +56,9 @@
 class BodySM;
 
 class GeometryEntity;
-class BodySM;
-class Lump;
-class ShellSM;
-class Surface;
-class LoopSM;
-class Curve;
-class CoEdgeSM;
-class Point;
-class TopologyEntity;
 class CubitBox;
 class CubitString;
 
-class OtherSolidModelingEntity;
 class FacetLump;
 class FacetShell;
 class FacetLoop;
@@ -78,11 +68,6 @@
 class FacetCurve;
 class FacetPoint;
 
-class RefEntity;
-class RefVertex;
-class RefEdge;
-class RefFace;
-class Loop;
 class CubitFacet;
 class CubitQuadFacet;
 class CubitFacetEdge;
@@ -182,15 +167,11 @@
   Body* copy_body( Body *body_ptr );
 
   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;
   virtual CubitStatus get_graphics( Curve* curve_ptr,
-                                    int& num_points,
                                     GMem* gMem = NULL,
                                     double tolerance = 0.0 ) const;
     //R CubitStatus
@@ -245,7 +226,7 @@
                                         DLIList<CubitVector*>& intersection_list,
                                         CubitBoolean bounded = CUBIT_FALSE );
 
-  virtual CubitStatus entity_extrema( DLIList<GeometryEntity*> &ref_entity_list, 
+  virtual CubitStatus entity_extrema( DLIList<GeometryEntity*> &entity_list, 
                                       const CubitVector *dir1, 
                                       const CubitVector *dir2,
                                       const CubitVector *dir3, 
@@ -314,13 +295,22 @@
   virtual CubitStatus delete_solid_model_entities( Curve* curve_ptr ) const;
   virtual CubitStatus delete_solid_model_entities( Point* point_ptr ) const;
 
-  virtual CubitStatus fire_ray(BodySM *body,
-                               const CubitVector &ray_point,
-                               const CubitVector &unit,
-                               DLIList<double>& ray_params,
-                               DLIList<GeometryEntity*> *entity_list = NULL) const;
-    //- fire a ray at the specified body, returning the entities hit and
-    //- the parameters along the ray; return CUBIT_FAILURE if error
+  virtual CubitStatus 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=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.  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).
+    //- NOTE: returned entities hit might be "hidden" beneath virtual entities.
+    //-       To resolve to visible entities, use "get_visible_ents_for_hits"
+    //-       in GeometryQueryTool.
 
   virtual double get_sme_resabs_tolerance() const; // Gets solid modeler's resolution absolute tolerance
   virtual double set_sme_resabs_tolerance( double new_resabs );
@@ -484,6 +474,8 @@
                                    DLIList<FacetSurface*>& output_patch );
   virtual CubitBoolean bodies_overlap (BodySM *body_ptr_1,
                                        BodySM *body_ptr_2 ) const;
+  virtual CubitBoolean volumes_overlap (Lump *lump_ptr_1,
+                                        Lump *lump_ptr_2 ) const;
   //R CubitBoolean
   //R- CUBIT_TRUE if the two bodies overlap, CUBIT_FALSE if they don't
   //R- overlap.  If the bodies are touching the function

Modified: cgm/branches/cubit/geom/facet/FacetboolInterface.cpp
===================================================================
--- cgm/branches/cubit/geom/facet/FacetboolInterface.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facet/FacetboolInterface.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -147,11 +147,12 @@
     CubitFacet *facet_ptr;
     if(mydebug)
       GfxDebug::clear();
-    for ( k = 0; k < coordsout.size(); k += 3 ) {    
+    for ( k = 0; k < coordsout.size(); k += 3 ) 
+    {    
       facet_ptr = new CubitFacetData( points[coordsout[k]],
                                       points[coordsout[k+1]],
                                       points[coordsout[k+2]] ); 
-      int *cptr = new int[3];
+      int cptr[3];
       cptr[0] = curveindex[k];
       cptr[1] = curveindex[k+1];
       cptr[2] = curveindex[k+2];
@@ -254,7 +255,7 @@
       facet_ptr = new CubitFacetData( points[coordsout2[k]],
                                       points[coordsout2[k+1]],
                                       points[coordsout2[k+2]] );
-      int *cptr = new int[3];
+      int cptr[3];
       cptr[0] = curveindex2[k];
       cptr[1] = curveindex2[k+1];
       cptr[2] = curveindex2[k+2];
@@ -873,7 +874,7 @@
       facet_ptr = new CubitFacetData( points[coordsout[k]],
                                       points[coordsout[k+1]],
                                       points[coordsout[k+2]] );
-      int *cptr = new int[3];
+      int cptr[3];
       cptr[0] = curveindex[k];
       cptr[1] = curveindex[k+1];
       cptr[2] = curveindex[k+2];
@@ -1371,7 +1372,7 @@
       facet_ptr = new CubitFacetData( points[coordsout[k]],
                                       points[coordsout[k+1]],
                                       points[coordsout[k+2]] );
-      int *cptr = new int[3];
+      int cptr[3];
       cptr[0] = curveindex[k];
       cptr[1] = curveindex[k+1];
       cptr[2] = curveindex[k+2];
@@ -1509,7 +1510,7 @@
       facet_ptr = new CubitFacetData( points[coordsout1[k]],
                                       points[coordsout1[k+1]],
                                       points[coordsout1[k+2]] );
-      int *cptr = new int[3];
+      int cptr[3];
       cptr[0] = curveindex1[k];
       cptr[1] = curveindex1[k+1];
       cptr[2] = curveindex1[k+2];
@@ -1569,7 +1570,7 @@
       facet_ptr = new CubitFacetData( points[coordsout2[k]],
                                       points[coordsout2[k+1]],
                                       points[coordsout2[k+2]] );
-      int *cptr = new int[3];
+      int cptr[3];
       cptr[0] = curveindex2[k];
       cptr[1] = curveindex2[k+1];
       cptr[2] = curveindex2[k+2];

Modified: cgm/branches/cubit/geom/facetbool/FBRetriangulate.cpp
===================================================================
--- cgm/branches/cubit/geom/facetbool/FBRetriangulate.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/facetbool/FBRetriangulate.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -306,7 +306,6 @@
   vy2 = verts[my_tri->v2]->coord[1];
   vz2 = verts[my_tri->v2]->coord[2];
 
-  dpe_orig = my_tri->edge_list.end();
   dpe = my_tri->edge_list.begin();
   while ( dpe != my_tri->edge_list.end() ) {
     edge = *dpe;
@@ -350,12 +349,13 @@
 //  in what follows.  Erasing elements from a vector is inefficient, but
 //  this shouldn't happen often.
   dpe = my_tri->edge_list.begin();
+  dpe_orig = my_tri->edge_list.end();
 
   while ( dpe != dpe_orig ) {
     edge = *dpe;
     if ( edge->edge_type == BDRY_EDGE ) {
-      my_tri->edge_list.erase(dpe);
-      dpe_orig -= 1;
+      dpe = my_tri->edge_list.erase(dpe);
+      dpe_orig = my_tri->edge_list.end();
     } else {
       dpe++;
     }

Modified: cgm/branches/cubit/geom/parallel/Makefile.am
===================================================================
--- cgm/branches/cubit/geom/parallel/Makefile.am	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/parallel/Makefile.am	2010-01-06 19:22:14 UTC (rev 3423)
@@ -27,6 +27,7 @@
     AcisMemFile.cpp \
     CABodies.cpp \
     CGMMemFile.cpp \
+    ParallelGeomTool.cpp \
     ProcData.cpp \
     TDParallel.cpp
 
@@ -37,6 +38,7 @@
     AcisMemFile.hpp \
     CABodies.cpp \
     CGMMemFile.hpp \
+    ParallelGeomTool.hpp \
     ProcData.hpp \
     TDParallel.hpp
 

Added: cgm/branches/cubit/geom/testing/AngleCalc.cpp
===================================================================
--- cgm/branches/cubit/geom/testing/AngleCalc.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/AngleCalc.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,65 @@
+
+
+#include "stdio.h"
+
+#include "GeometryQueryTool.hpp"
+#include "GeometryModifyTool.hpp"
+#include "RefEdge.hpp"
+#include "RefVertex.hpp"
+#include "CoEdge.hpp"
+#include "RefFace.hpp"
+#include "CubitDefines.h"
+#include "CubitBox.hpp"
+
+#include "TestUtilities.hpp"
+
+int AngleCalc(int argc, char* argv[])
+{
+  Body* brick = GeometryModifyTool::instance()->brick(1,2,4);
+  if(!brick)
+  {
+    printf("failed to make brick\n");
+    return 1;
+  }
+
+  // compute angles at each vertex and be sure they are 90 degrees
+  DLIList<RefFace*> faces;
+  GeometryQueryTool::instance()->ref_faces(faces);
+
+  bool errors = false;
+
+  for(int i=0; i<faces.size(); i++)
+  {
+    // get loops
+    DLIList<DLIList<CoEdge*>*> loops;
+    RefFace* face = faces.get_and_step();
+    face->co_edge_loops(loops);
+
+    for(int j=0; j<loops.size(); j++)
+    {
+      for(int k=0; k<loops[j]->size(); k++)
+      {
+        CoEdge* edge1 = loops[j]->next(k);
+        CoEdge* edge2 = loops[j]->next(k+1);
+
+        double angle = GeometryQueryTool::instance()->geometric_angle(edge1, edge2);
+        angle = angle * (180/CUBIT_PI);
+        if(fabs(90 - angle) > 0.01)
+        {
+          RefEdge* redge1 = edge1->get_ref_edge_ptr();
+          RefEdge* redge2 = edge2->get_ref_edge_ptr();
+          RefVertex* vert = redge1->common_ref_vertex(redge2);
+
+          printf("wrong angle at vertex (%f) %i with surface %i\n", 
+              angle, vert->id(), face->id());
+          errors = true;
+        }
+
+      }
+      delete loops[j];
+    }
+  }
+
+  return errors ? 1 : 0;
+}
+

Added: cgm/branches/cubit/geom/testing/CMakeLists.txt
===================================================================
--- cgm/branches/cubit/geom/testing/CMakeLists.txt	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/CMakeLists.txt	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,82 @@
+
+# test suite to test cgm apis
+# this test suite attempts to work for all cgm ports
+PROJECT(CGM_TESTS)
+
+
+# a list of tests
+# each testname has a testname.cpp file that implements 
+# a "int testname(int, char**)" as its entry point
+# testname(int, char**) returns 0 on success
+# when testname(int, char**) is called, cgm has already been initialized
+# and is ready to use with active ports already set
+SET(CGM_TESTS
+    AngleCalc
+    CreateGeometry
+    ReadIgesFile
+    GraphicsData
+   )
+
+ 
+# CGM_PORTS contains an identifier for the port to use
+# these identifiers are recognized in cgm_test.cpp
+IF(CGM_ACIS)
+  SET(CGM_PORTS ${CGM_PORTS} "acis")
+  INCLUDE(${cubit_acis_SOURCE_DIR}/UseACIS.cmake)
+  ADD_DEFINITIONS(-DCGM_ACIS)
+  INCLUDE_DIRECTORIES(${cubit_acis_SOURCE_DIR} ${ACIS_INCLUDE_DIR})
+  SET(PORT_LIBS ${PORT_LIBS} cubit_ACIS gtcAttrib)
+  IF(NOT WIN32 AND BUILD_64)
+    SET(SKIP_ReadIgesFile-acis 1)
+  ENDIF(NOT WIN32 AND BUILD_64)
+ENDIF(CGM_ACIS)
+IF(CGM_SMLIB)
+  SET(CGM_PORTS ${CGM_PORTS} "smlib")
+  INCLUDE(${cubit_smlib_SOURCE_DIR}/UseSMLib.cmake)
+  INCLUDE_DIRECTORIES(${cubit_smlib_SOURCE_DIR} ${SMLIB_INCLUDE_DIR})
+  ADD_DEFINITIONS(-DCGM_SMLIB)
+  SET(PORT_LIBS ${PORT_LIBS} cubit_smlib)
+ENDIF(CGM_SMLIB)
+
+
+# functions that'll start/end cgm
+# CREATE_TEST_SOURCELIST will insert the function calls into the test driver
+SET(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "  start_cgm(ac,av);")
+SET(CMAKE_TESTDRIVER_AFTER_TESTMAIN "  end_cgm(ac,av);")
+CREATE_TEST_SOURCELIST(TEST_SRCS cgm_test_driver.cpp ${CGM_TESTS} 
+                       EXTRA_INCLUDE "cgm_test.hpp")
+
+SET(DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data")
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/TestConfig.h.in
+               ${CMAKE_CURRENT_BINARY_DIR}/TestConfig.h @ONLY)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+SET(TEST_SRCS
+  ${TEST_SRCS}
+  cgm_test.cpp
+  cgm_test.hpp
+  TestUtilities.cpp
+  TestUtilities.hpp
+  TestConfig.h
+  )
+
+ADD_EXECUTABLE(cgm_test ${TEST_SRCS})
+TARGET_LINK_LIBRARIES(cgm_test ${PORT_LIBS} cubit_geom cubit_util)
+
+GET_TARGET_PROPERTY(cgm_test_exe cgm_test LOCATION)
+
+# add all the tests for each port
+FOREACH(port ${CGM_PORTS})
+  MESSAGE("adding tests for ${port}")
+  FOREACH(test ${CGM_TESTS})
+    IF(NOT SKIP_${test}-${port})
+      ADD_TEST(
+        cgm-${test}-${port} ${cgm_test_exe} ${test} 
+        -E ${port}
+      )
+    ENDIF(NOT SKIP_${test}-${port})
+  ENDFOREACH(test)
+ENDFOREACH(port)
+

Added: cgm/branches/cubit/geom/testing/CreateGeometry.cpp
===================================================================
--- cgm/branches/cubit/geom/testing/CreateGeometry.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/CreateGeometry.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,230 @@
+
+
+#include "stdio.h"
+
+#include "GeometryQueryTool.hpp"
+#include "GeometryModifyTool.hpp"
+#include "CubitDefines.h"
+#include "CubitBox.hpp"
+
+#include "Body.hpp"
+#include "RefEdge.hpp"
+#include "RefVertex.hpp"
+
+#include "TestUtilities.hpp"
+
+
+static int test_brick()
+{
+  Body* brick = GeometryModifyTool::instance()->brick(1,2,4);
+  if(!brick)
+  {
+    printf("failed to make brick\n");
+    return 1;
+  }
+  if(!cubit_box_identical(brick->bounding_box(), 
+        CubitBox(CubitVector(-0.5,-1,-2), CubitVector(0.5,1,2)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+  return 0;
+}
+
+static int test_oriented_brick()
+{
+  CubitVector center(1, 2, 4);
+  CubitVector axes[3] = {
+    CubitVector(1, 0, .2),
+    CubitVector(0, 1, .4),
+    CubitVector(0.1, 0, 1)
+  };
+  CubitVector extension(3, 5, 7);
+
+  Body* brick = GeometryModifyTool::instance()->brick(center, axes, extension);
+  if(!brick)
+  {
+    printf("failed to make brick\n");
+    return 1;
+  }
+  if(!cubit_box_identical(brick->bounding_box(), 
+        CubitBox(CubitVector(-3.577819, -5.210785, -4.768732),
+          CubitVector(5.577819, 9.210785, 12.768732)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+  return 0;
+}
+
+static int test_sphere()
+{
+  Body* sphere = GeometryModifyTool::instance()->sphere(1);
+  if(!sphere)
+  {
+    printf("failed to make sphere\n");
+    return 1;
+  }
+  if(!cubit_box_identical(sphere->bounding_box(), 
+        CubitBox(CubitVector(-1,-1,-1), CubitVector(1,1,1)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+  return 0;
+}
+
+static int test_torus()
+{
+  printf("making torus\n");
+  Body* torus = GeometryModifyTool::instance()->torus(1, .2);
+  if(!torus)
+  {
+    printf("failed to make torus\n");
+    return 1;
+  }
+  if(!cubit_box_identical(torus->bounding_box(), 
+        CubitBox(CubitVector(-1.2,-1.2,-0.2), CubitVector(1.2,1.2,0.2)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+  return 0;
+}
+
+static int test_planar_sheet()
+{
+  CubitVector axes[2] = {
+    CubitVector(1,0,0),
+    CubitVector(.1,.9,0)
+    };
+  
+  Body* body = GeometryModifyTool::instance()->planar_sheet(CubitVector(1,1,1),
+      axes, 2, 3);
+
+  if(!body)
+  {
+    printf("failed to make planar sheet\n");
+    return 1;
+  }
+  if(!cubit_box_identical(body->bounding_box(), 
+        CubitBox(CubitVector(-0.165647,-0.490826,1.0), 
+        CubitVector(2.165647,2.490826,1.0)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+
+
+  body = GeometryModifyTool::instance()->planar_sheet(
+      CubitVector(0,0,0),
+      CubitVector(1,0,0),
+      CubitVector(1,1,0),
+      CubitVector(0,1,.2)
+      );
+
+  if(body)
+  {
+    printf("should have failed to make planar sheet out of non-planar points\n");
+    return 1;
+  }
+  
+  body = GeometryModifyTool::instance()->planar_sheet(
+      CubitVector(0,0,0),
+      CubitVector(0,0,0),
+      CubitVector(1,1,0),
+      CubitVector(0,1,0)
+      );
+  
+  if(body)
+  {
+    printf("should have failed to make planar sheet with coincident input points\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+static int test_arc()
+{
+  RefVertex* pt1 = GeometryModifyTool::instance()->make_RefVertex(CubitVector(0,0,0));
+  RefVertex* pt2 = GeometryModifyTool::instance()->make_RefVertex(CubitVector(1,1,0));
+  RefVertex* pt3 = GeometryModifyTool::instance()->make_RefVertex(CubitVector(2,0,0));
+
+  RefEdge* arc = GeometryModifyTool::instance()->create_arc_three(pt1, pt2, pt3, false);
+  if(!arc)
+  {
+    printf("failed to make arc\n");
+    return 1;
+  }
+  if(!cubit_box_identical(arc->bounding_box(), 
+        CubitBox(CubitVector(0, 0, 0), CubitVector(2, 1, 0)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+
+  // previously free curves at end points must be consumed
+  DLIList<RefVertex*> all_verts;
+  GeometryQueryTool::instance()->ref_vertices(all_verts);
+  if(all_verts.size() != 3)
+  {
+    printf("vertices not consumed properly with curve creation\n");
+    return 1;
+  }
+
+  GeometryQueryTool::instance()->delete_RefVertex(pt2);
+
+  RefVertex* pt4 = GeometryModifyTool::instance()->make_RefVertex(CubitVector(1,-1,0));
+  RefEdge* arc2 = GeometryModifyTool::instance()->create_arc_three(pt1, pt4, pt3, true);
+  
+  if(!cubit_box_identical(arc2->bounding_box(), 
+        CubitBox(CubitVector(0, -1, 0), CubitVector(2, 1, 0)), 
+        GEOMETRY_RESABS*2.0, true))
+  {
+    printf("boxes not identical\n");
+    return 1;
+  }
+  
+  all_verts.clean_out();
+  GeometryQueryTool::instance()->ref_vertices(all_verts);
+  if(all_verts.size() != 4)
+  {
+    printf("vertices not consumed properly with curve creation\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+int CreateGeometry(int argc, char* argv[])
+{
+  int ret = 0;
+  
+  ret |= test_brick();
+  GeometryQueryTool::instance()->delete_geometry();
+
+  ret |= test_oriented_brick();
+  GeometryQueryTool::instance()->delete_geometry();
+
+  ret |= test_sphere();
+  GeometryQueryTool::instance()->delete_geometry();
+
+  ret |= test_torus();
+  GeometryQueryTool::instance()->delete_geometry();
+
+  ret |= test_planar_sheet();
+  GeometryQueryTool::instance()->delete_geometry();
+
+  ret |= test_arc();
+  GeometryQueryTool::instance()->delete_geometry();
+  
+  return ret;
+}
+

Added: cgm/branches/cubit/geom/testing/GraphicsData.cpp
===================================================================
--- cgm/branches/cubit/geom/testing/GraphicsData.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/GraphicsData.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,127 @@
+
+
+#include "stdio.h"
+
+#include "GMem.hpp"
+#include "GeometryQueryTool.hpp"
+#include "GeometryModifyTool.hpp"
+#include "GeometryQueryEngine.hpp"
+#include "RefEdge.hpp"
+#include "RefFace.hpp"
+#include "CubitDefines.h"
+#include "CubitBox.hpp"
+
+#include "TestUtilities.hpp"
+
+int GraphicsData(int argc, char* argv[])
+{
+  GeometryModifyTool::instance()->brick(10,10,10);
+
+  GeometryQueryEngine* engine = GeometryQueryTool::instance()->get_gqe();
+
+  if(!engine)
+  {
+    printf("no engine\n");
+    return 1;
+  }
+ 
+  CubitBox uninit_box;
+  
+  CubitBox model_bbox(
+      CubitVector(-5, -5, -5),
+      CubitVector(5, 5, 5)
+      );
+
+
+  DLIList<RefEdge*> edges;
+  GeometryQueryTool::instance()->ref_edges(edges);
+
+  // expect 24 edges
+  if(edges.size() != 12)
+  {
+    printf("wrong edge count\n");
+    return 1;
+  }
+
+  // get graphics data for the curves
+
+  CubitBox g_curves = uninit_box;
+  GMem gmem;
+  for(int i=0; i<edges.size(); i++)
+  {
+    RefEdge* edge = edges.get_and_step();
+    if(engine->get_graphics(edge->get_curve_ptr(), &gmem) != CUBIT_SUCCESS || 
+        gmem.pointListCount == 0)
+    {
+      printf("got no edge facet data for edge %i\n", edge->id());
+    }
+    else
+    {
+      for(int j=0; j<gmem.pointListCount; j++)
+      {
+        const GPoint& pt = gmem.point_list()[j];
+        g_curves |= CubitVector(pt.x, pt.y, pt.z);
+      }
+    }
+  }
+
+  printf("curve bbox range = %f %f %f\n",
+      g_curves.x_range(), g_curves.y_range(), g_curves.z_range());
+
+  if(!cubit_box_identical(g_curves, model_bbox, GEOMETRY_RESABS))
+  {
+    printf("didn't get accurate facet data for curves\n");
+    return 1;
+  }
+
+  
+  CubitBox g_surfaces = uninit_box;
+  DLIList<RefFace*> faces;
+  GeometryQueryTool::instance()->ref_faces(faces);
+
+  // expect 6 edges
+  if(faces.size() != 6)
+  {
+    printf("wrong face count\n");
+    return 1;
+  }
+
+  // get graphics data for the surfaces
+  for(int i=0; i<faces.size(); i++)
+  {
+    RefFace* face = faces.get_and_step();
+    if(engine->get_graphics(face->get_surface_ptr(), &gmem) != CUBIT_SUCCESS || 
+        gmem.pointListCount == 0 || gmem.fListCount == 0)
+    {
+      printf("got no face facet data for face %i\n", face->id());
+    }
+    else
+    {
+      const GPoint* pts = gmem.point_list();
+      const int* facets = gmem.facet_list();
+      int facet_size = gmem.fListCount;
+      for(int j=0; j<facet_size;)
+      {
+        int num = facets[j++]; 
+        for(int k=0; k<num; k++)
+        {
+          const GPoint& pt = pts[facets[j++]];
+          g_surfaces |= CubitVector(pt.x, pt.y, pt.z);
+        }
+      }
+    }
+  }
+  
+  printf("surface bbox range = %f %f %f\n",
+      g_surfaces.x_range(), g_surfaces.y_range(), g_surfaces.z_range());
+  
+  if(!cubit_box_identical(g_surfaces, model_bbox, GEOMETRY_RESABS))
+  {
+    printf("didn't get accurate facet data for surfaces\n");
+    return 1;
+  }
+
+
+  return 0;
+}
+

Added: cgm/branches/cubit/geom/testing/Makefile.am
===================================================================
--- cgm/branches/cubit/geom/testing/Makefile.am	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/Makefile.am	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,24 @@
+BASE_TESTS = AngleCalc.engine \
+             GreateGeometry.engine \
+             ReadIgesFile.engine \
+             GraphicsData.engine
+
+TESTS=
+if build_ACIS
+  TESTS += $(BASE_TESTS:.engine=.acis)
+endif
+if build_OCC
+  TESTS += $(BASE_TESTS:.engine=.occ)
+endif
+
+
+SUFFIXES += .acis .occ
+check_PROGRAMS = $(TESTS) cgm_test
+cgm_test_SOURCES = cgm_test.cpp \
+                   cgm_test.hpp \
+                   TestUtilities.hpp \
+                   TestUtilities.cpp \
+                   TestConfig.h
+
+%.acis %.occ: cgm_test_script
+	cp -f cgm_test_script $@

Added: cgm/branches/cubit/geom/testing/ReadIgesFile.cpp
===================================================================
--- cgm/branches/cubit/geom/testing/ReadIgesFile.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/ReadIgesFile.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,22 @@
+
+#include "stdio.h"
+#include "TestUtilities.hpp"
+
+#include "GeometryQueryTool.hpp"
+
+int ReadIgesFile(int argc, char* argv[])
+{
+
+  std::string file = data_file("brick.iges");
+
+  CubitStatus stat = GeometryQueryTool::instance()->import_solid_model(file.c_str(), "IGES");
+
+  if(stat != CUBIT_SUCCESS)
+  {
+    printf("failed to read iges file %s\n", file.c_str());
+    return 1;
+  }
+
+  return 0;
+}
+

Added: cgm/branches/cubit/geom/testing/TestConfig.h.in
===================================================================
--- cgm/branches/cubit/geom/testing/TestConfig.h.in	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/TestConfig.h.in	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,8 @@
+
+#ifndef TEST_CONFIG_HPP
+#define TEST_CONFIG_HPP
+
+static const char* DataDir = "@DATA_DIR@";
+
+#endif
+

Added: cgm/branches/cubit/geom/testing/TestUtilities.cpp
===================================================================
--- cgm/branches/cubit/geom/testing/TestUtilities.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/TestUtilities.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,39 @@
+
+
+#include "TestUtilities.hpp"
+#include "TestConfig.h"
+
+std::string data_file(char* filename)
+{
+  return DataDir + std::string("/") + std::string(filename);
+}
+
+
+bool cubit_box_identical(const CubitBox& box1, const CubitBox& box2, double tol,
+    bool print_data)
+{
+  if(print_data)
+  {
+    printf("box 1 {(%f %f %f), (%f %f %f)}\n",
+            box1.minimum().x(), 
+            box1.minimum().y(), 
+            box1.minimum().z(), 
+            box1.maximum().x(), 
+            box1.maximum().y(), 
+            box1.maximum().z()
+            );
+    printf("box 2 {(%f %f %f), (%f %f %f)}\n",
+            box2.minimum().x(), 
+            box2.minimum().y(), 
+            box2.minimum().z(), 
+            box2.maximum().x(), 
+            box2.maximum().y(), 
+            box2.maximum().z()
+            );
+  }
+  
+  return box1.maximum().within_tolerance(box2.maximum(), tol) && 
+         box1.minimum().within_tolerance(box2.minimum(), tol);
+}
+
+

Added: cgm/branches/cubit/geom/testing/TestUtilities.hpp
===================================================================
--- cgm/branches/cubit/geom/testing/TestUtilities.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/TestUtilities.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,18 @@
+
+#ifndef TEST_UTILITIES_HPP
+#define TEST_UTILITIES_HPP
+
+#include "CubitBox.hpp"
+#include <string>
+
+// function to get the path to a data file in the data directory
+std::string data_file(char* filename);
+
+// compare if 2 CubitBoxes are identical
+bool cubit_box_identical(const CubitBox& box1, const CubitBox& box2, double tol,
+    bool print_data = false);
+
+
+
+#endif
+

Added: cgm/branches/cubit/geom/testing/cgm_test.cpp
===================================================================
--- cgm/branches/cubit/geom/testing/cgm_test.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/cgm_test.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,83 @@
+
+
+#include "cgm_test.hpp"
+
+#include "AppUtil.hpp"
+#include "TextProgressTool.hpp"
+#include "CGMApp.hpp"
+#include "GeometryQueryTool.hpp"
+#include "GeometryModifyTool.hpp"
+
+#ifdef CGM_SMLIB
+#include "SMLibQueryEngine.hpp"
+#include "SMLibModifyEngine.hpp"
+#endif
+
+#ifdef CGM_ACIS
+#include "AcisQueryEngine.hpp"
+#include "AcisModifyEngine.hpp"
+#endif
+
+
+static std::string cgm_port;
+
+void start_cgm(int argc, char** argv)
+{
+  for(int i=0; i<argc; i++)
+  {
+    // get library name
+    if(std::string(argv[i]) == "-E" && i+1 < argc)
+    {
+      cgm_port = argv[i+1];
+    }
+  }
+
+
+  // init util
+  AppUtil::instance()->startup(argc, argv);
+  AppUtil::instance()->progress_tool(new TextProgressTool());
+
+  // init cgm
+  CGMApp::instance()->startup(argc, argv);
+
+  GeometryQueryEngine* query_engine = NULL;
+  GeometryModifyEngine* modify_engine = NULL;
+  printf("using %s engine\n", cgm_port.c_str());
+
+  // find the engine
+  if(0)
+  {
+    // nothing here
+  }
+#ifdef CGM_ACIS
+  else if(cgm_port == "acis")
+  {
+    query_engine = AcisQueryEngine::instance();
+    modify_engine = AcisModifyEngine::instance();
+  }
+#endif
+#ifdef CGM_SMLIB
+  else if(cgm_port == "smlib")
+  {
+    query_engine = SMLibQueryEngine::instance();
+    modify_engine = SMLibModifyEngine::instance();
+  }
+#endif
+
+  if(query_engine == NULL || modify_engine == NULL)
+  {
+    printf("no engine set with -E flag\n");
+    exit(1);
+  }
+}
+
+void end_cgm(int argc, char** argv)
+{
+  CGMApp::instance()->shutdown();
+  CGMApp::delete_instance();
+
+  // close down util module
+  AppUtil::instance()->shutdown();
+  AppUtil::delete_instance();
+}
+

Added: cgm/branches/cubit/geom/testing/cgm_test.hpp
===================================================================
--- cgm/branches/cubit/geom/testing/cgm_test.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/cgm_test.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,13 @@
+
+
+#ifndef CGM_TEST_H
+#define CGM_TEST_H
+
+// function to initialize cgm
+void start_cgm(int argc, char** argv);
+// function to shutdown cgm
+void end_cgm(int argc, char** argv);
+
+
+#endif // CGM_TEST_H
+

Added: cgm/branches/cubit/geom/testing/cgm_test_script
===================================================================
--- cgm/branches/cubit/geom/testing/cgm_test_script	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/cgm_test_script	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,6 @@
+#!/bin.sh
+
+name="$0"
+test=`expr $name : '\(.*\)\.'`
+engine=`expr $name : '.*\.\(.*\)'
+cgm_test $test -E $engine

Added: cgm/branches/cubit/geom/testing/data/brick.iges
===================================================================
--- cgm/branches/cubit/geom/testing/data/brick.iges	                        (rev 0)
+++ cgm/branches/cubit/geom/testing/data/brick.iges	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,58 @@
+ACIS data in IGES format                                                S      1
+
+1H,,1H;,10HCubit 7.1b,7HUnknown,4HACIS,17H*IGES writer V5.2,32,308,15,  G      1
+
+308,15,7HUnknown,1.,2,2HMM,1,1.,15H20020710.130033,0.002,               G      2
+
+2886.7513459481,7Hcjstimp,9HCLINTONNT,10,0,15H20020710.130033;          G      3
+
+     128       1       0       1       0       0       0       000000001D      1
+
+     128       0       4       2       1                               0D      2
+
+     128       3       0       1       0       0       0       000000001D      3
+
+     128       0       4       2       1                               0D      4
+
+     128       5       0       1       0       0       0       000000001D      5
+
+     128       0       4       2       1                               0D      6
+
+     128       7       0       1       0       0       0       000000001D      7
+
+     128       0       4       2       1                               0D      8
+
+     128       9       0       1       0       0       0       000000001D      9
+
+     128       0       4       2       1                               0D     10
+
+     128      11       0       1       0       0       0       000000001D     11
+
+     128       0       4       2       1                               0D     12
+
+128,1,1,1,1,0,0,1,0,0,0.,0.,10.,10.,0.,0.,10.,10.,1.,1.,1.,1.,         1P      1
+
+-5.,-5.,5.,5.,-5.,5.,-5.,5.,5.,5.,5.,5.,0.,10.,0.,10.;                 1P      2
+
+128,1,1,1,1,0,0,1,0,0,-10.,-10.,0.,0.,0.,0.,10.,10.,1.,1.,1.,          3P      3
+
+1.,5.,-5.,-5.,-5.,-5.,-5.,5.,5.,-5.,-5.,5.,-5.,-10.,0.,0.,10.;         3P      4
+
+128,1,1,1,1,0,0,1,0,0,-10.,-10.,0.,0.,0.,0.,10.,10.,1.,1.,1.,          5P      5
+
+1.,-5.,-5.,5.,-5.,-5.,-5.,5.,-5.,5.,5.,-5.,-5.,-10.,0.,0.,10.;         5P      6
+
+128,1,1,1,1,0,0,1,0,0,-10.,-10.,0.,0.,0.,0.,10.,10.,1.,1.,1.,          7P      7
+
+1.,-5.,-5.,-5.,-5.,-5.,5.,-5.,5.,-5.,-5.,5.,5.,-10.,0.,0.,10.;         7P      8
+
+128,1,1,1,1,0,0,1,0,0,-10.,-10.,0.,0.,0.,0.,10.,10.,1.,1.,1.,          9P      9
+
+1.,-5.,5.,-5.,-5.,5.,5.,5.,5.,-5.,5.,5.,5.,-10.,0.,0.,10.;             9P     10
+
+128,1,1,1,1,0,0,1,0,0,-10.,-10.,0.,0.,0.,0.,10.,10.,1.,1.,1.,         11P     11
+
+1.,5.,-5.,5.,5.,-5.,-5.,5.,5.,5.,5.,5.,-5.,-10.,0.,0.,10.;            11P     12
+
+S      1G      3D     12P     12                                        T      1
+


Property changes on: cgm/branches/cubit/geom/testing/data/brick.iges
___________________________________________________________________
Added: svn:executable
   + *

Modified: cgm/branches/cubit/geom/virtual/CMakeLists.txt
===================================================================
--- cgm/branches/cubit/geom/virtual/CMakeLists.txt	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CMakeLists.txt	2010-01-06 19:22:14 UTC (rev 3423)
@@ -50,6 +50,7 @@
     RemoveBlends.cpp
     SegmentedCurve.cpp
     SimplifyTool.cpp
+    SplitCompositeSurfaceTool.cpp
     SubCurve.cpp
     SubEntitySet.cpp
     SubSurface.cpp

Modified: cgm/branches/cubit/geom/virtual/CollapseCurveTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CollapseCurveTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CollapseCurveTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -27,9 +27,14 @@
 #include "Point.hpp"
 #include "Loop.hpp"
 #include "RefFace.hpp"
+#include "Body.hpp"
 #include "PartitionTool.hpp"
 #include "CompositeTool.hpp"
 #include "CollapseCurveTool.hpp"
+#include "GeometryModifyTool.hpp"
+#include "SplitCompositeSurfaceTool.hpp"
+#include "CubitUndo.hpp"
+//#include "InteropTool.hpp"
 
 /*
 */
@@ -46,9 +51,10 @@
   return instance_;
 }
 
-CubitStatus CollapseCurveTool::collapse_curve(DLIList <RefEdge*> ref_edge_list, 
+CubitStatus CollapseCurveTool::collapse_curve_only_virtual(DLIList <RefEdge*> ref_edge_list, 
                                               DLIList<RefVertex*> ref_vertex_list,
-                                              int ignore_surfaces)
+                                              int ignore_surfaces,
+                                              double *small_curve_size)
 {
   CubitStatus result = CUBIT_SUCCESS;
 
@@ -82,6 +88,11 @@
   CubitVector position_on_left_curve(0,0,0), position_on_right_curve(0,0,0);
   CubitVector discard_pos(0,0,0), keep_pos(0,0,0);
 
+  bool undo_state = CubitUndo::get_undo_enabled();
+  if( undo_state )
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  CubitUndo::set_undo_enabled(false);
+
   if(edge_to_collapse == NULL)
   {
     PRINT_ERROR("No curve was found to collapse.\n");
@@ -120,7 +131,7 @@
       finished = 1;
     }
   }
-
+  
   if(!finished)
   {
     // Get the valency of the keep and discard vertices.
@@ -208,6 +219,32 @@
     }
   }
 
+  if(!finished && small_curve_size)
+  {
+    // Check if the edges attached to the discard vertex are longer 
+    // than the small curve size.
+    DLIList<RefEdge*> tmp_edges;
+    discard_vertex->ref_edges(tmp_edges);
+    if(tmp_edges.move_to(edge_to_collapse))
+      tmp_edges.extract();
+    int y;
+    bool all_edges_long_enough = true;
+    for(y=tmp_edges.size(); y && all_edges_long_enough; y--)
+    {
+      RefEdge *cur_edge = tmp_edges.get_and_step();
+      if(cur_edge->get_arc_length() <= *small_curve_size)
+        all_edges_long_enough = false;
+    }
+    if(!all_edges_long_enough)
+    {
+      PRINT_ERROR("Cannot collapse curve %d to vertex %d--not all of the curves attached to\n"
+            "vertex %d are longer than the small_curve_size.  Try collapsing to vertex %d instead.\n",
+            edge_to_collapse->id(), keep_vertex->id(), discard_vertex->id(), discard_vertex->id());
+      result = CUBIT_FAILURE;
+      finished = 1;
+    }
+  }
+
   // Look at all of the coedges on the curve being collapsed and
   // throw out any that are on nonmanifold surfaces.  The collapse
   // curve may be on a boundary of a merged surface.  This is ok
@@ -290,6 +327,9 @@
     // keep vertex looking at the discard vertex.
     Loop *left_loop = enter_coedge->get_loop_ptr();
     Loop *right_loop = exit_coedge->get_loop_ptr();
+    DLIList<SenseEntity*> left_sense_entities, right_sense_entities;
+    left_loop->get_sense_entity_list(left_sense_entities);
+    right_loop->get_sense_entity_list(right_sense_entities);
 
     // We need to get these two coedges because the chains defined by the "next" and 
     // "previous" pointers in the CoEdge objects are not circular (you can have a NULL
@@ -322,9 +362,10 @@
     DLIList<RefEdge*> right_face_edges;
     left_common_face->ref_edges(left_face_edges);
     right_common_face->ref_edges(right_face_edges);
-    if(left_face_edges.size() < 3 || right_face_edges.size() < 3)
+    if(left_face_edges.size() < 3 || right_face_edges.size() < 3 ||
+      left_sense_entities.size() < 3 || right_sense_entities.size() < 3)
     {
-      PRINT_ERROR("Cannot collapse a curve that bounds a face with only two edges.\n");
+      PRINT_ERROR("Cannot collapse a curve that bounds a face or loop with only two edges.\n");
       finished = 1;
     }
     else
@@ -528,7 +569,6 @@
       // the collapse edge and isn't nonmanifold.
       DLIList<CoEdge*> side_edge_coedges;
       side_edge->co_edges(side_edge_coedges);
-      RefFace *adjacent_face = NULL;
       DLIList<RefFace*> possible_adj_faces;
 
       // First loop through and get all of the potential faces.
@@ -875,19 +915,1051 @@
     }
   }
 
-  if(result == CUBIT_FAILURE)
+  CubitUndo::set_undo_enabled(undo_state);
+
+  return result;
+}
+
+CubitStatus CollapseCurveTool::collapse_curve(DLIList <RefEdge*> ref_edge_list, 
+                                              DLIList<RefVertex*> ref_vertex_list,
+                                              int ignore_surfaces,
+                                              double *small_curve_size)
+{
+  CubitStatus result = CUBIT_SUCCESS;
+
+  RefEdge *edge_to_collapse = ref_edge_list.get();
+  RefVertex *keep_vertex = NULL;
+  RefVertex *discard_vertex = NULL;
+  CoEdge *exit_coedge = NULL;
+  CoEdge *enter_coedge = NULL;
+  DLIList<RefEdge*> curves_to_partition;
+  DLIList<RefFace*> surfaces_to_partition;
+  DLIList<CubitVector> partition_positions;
+  DLIList<CubitVector> keep_vecs;
+  DLIList<CubitVector> partition_curve_vecs;
+  DLIList<RefFace*> adjacent_surfaces;
+  DLIList<double> angles;
+  DLIList<double> arc_lengths;
+  DLIList<RefEdge*> ref_edges_on_discard_vertex;
+  DLIList<RefEdge*> ref_edges_on_keep_vertex;
+  DLIList<RefVertex*> new_partition_vertices;
+  DLIList<RefEdge*> new_partition_edges;
+  RefEdge *close_edge = NULL;
+  RefEdge *far_edge = NULL;
+  DLIList<RefEdge*> edges_to_composite;
+  int keep_vertex_specified = 0;
+  int discard_valency = 0;
+  int keep_valency = 0;
+  int finished = 0;
+  double arc_length = 0;
+  double u = 0, v = 0;
+  CubitVector left_vec(0,0,0), right_vec(0,0,0);
+  CubitVector position_on_left_curve(0,0,0), position_on_right_curve(0,0,0);
+  CubitVector discard_pos(0,0,0), keep_pos(0,0,0);
+  Body *the_body;
+
+  bool undo_state = CubitUndo::get_undo_enabled();
+  if( undo_state )
+      CubitUndo::save_state_with_cubit_file( ref_edge_list );
+  CubitUndo::set_undo_enabled(false);
+
+  if(edge_to_collapse == NULL)
   {
-    int i;
-    for(i=new_partition_edges.size(); i--;)
+    PRINT_ERROR("No curve was found to collapse.\n");
+    finished = 1;
+    result = CUBIT_FAILURE;
+  }
+
+  if(edge_to_collapse->is_merged())
+  {
+    PRINT_ERROR("Cannot collapse a merged curve.\n");
+    finished = 1;
+    result = CUBIT_FAILURE;
+  }
+
+  if(edge_to_collapse->start_vertex()->is_merged() &&
+    edge_to_collapse->end_vertex()->is_merged())
+  {
+    PRINT_ERROR("Cannot collapse a curve where both vertices are merged.\n");
+    finished = 1;
+    result = CUBIT_FAILURE;
+  }
+  else if(edge_to_collapse->start_vertex()->is_merged())
+  {
+    if(ref_vertex_list.size() > 0)
     {
-      CompositeTool::instance()->remove_edge(new_partition_edges.get_and_step(), true);
+      if(ref_vertex_list.get() == edge_to_collapse->end_vertex())
+      {
+        PRINT_ERROR("Specified vertex to collapse to is merged--try using other vertex.\n");
+        finished = 1;
+        result = CUBIT_FAILURE;
+      }
     }
-    for(i=new_partition_vertices.size(); i--;)
+    else
+      ref_vertex_list.append(edge_to_collapse->start_vertex());
+  }
+  else if(edge_to_collapse->end_vertex()->is_merged())
+  {
+    if(ref_vertex_list.size() > 0)
     {
-      CompositeTool::instance()->remove_vertex(new_partition_vertices.get_and_step(), true);
+      if(ref_vertex_list.get() == edge_to_collapse->start_vertex())
+      {
+        PRINT_ERROR("Specified vertex to collapse to is merged--try using other vertex.\n");
+        finished = 1;
+        result = CUBIT_FAILURE;
+      }
     }
+    else
+      ref_vertex_list.append(edge_to_collapse->end_vertex());
   }
 
+  if(!finished)
+  {
+    the_body = edge_to_collapse->body();
+
+    // Make sure we have a vertex to keep.
+    if(ref_vertex_list.size() > 0)
+    {
+      keep_vertex_specified = 1;
+      keep_vertex = ref_vertex_list.get();
+    }
+    // We need to choose a vertex to keep.
+    else
+    {
+      // Arbitrarily choose start vertex.
+      keep_vertex = edge_to_collapse->start_vertex();
+    }
+
+    // Get the vertex that will go away.
+    if(keep_vertex == edge_to_collapse->start_vertex())
+    {
+      discard_vertex = edge_to_collapse->end_vertex();
+    }
+    else if(keep_vertex == edge_to_collapse->end_vertex())
+    {
+      discard_vertex = edge_to_collapse->start_vertex();
+    }
+    else
+    {
+      PRINT_ERROR("Vertex to keep was not found on the curve being collapsed.\n");
+      result = CUBIT_FAILURE;
+      finished = 1;
+    }
+  }
+
+  if(!finished)
+  {
+    // Get the valency of the keep and discard vertices.
+    discard_vertex->ref_edges(ref_edges_on_discard_vertex);
+    keep_vertex->ref_edges(ref_edges_on_keep_vertex);
+    discard_valency = ref_edges_on_discard_vertex.size();
+    keep_valency = ref_edges_on_keep_vertex.size();
+
+    // Now do some error checking and also some logic to try to 
+    // pick the best vertex to keep/discard.
+
+    // If one of the valencies is 2 just composite the vertex out.
+    if(discard_valency == 2)
+    {
+      CompositeTool::instance()->composite(ref_edges_on_discard_vertex);
+      finished = 1;
+    }
+    else if (keep_valency == 2)
+    {
+      CompositeTool::instance()->composite(ref_edges_on_keep_vertex);
+      finished = 1;
+    }
+    else
+    {
+      // Make sure that at least one of the vertices is qualified to
+      // be the discard vertex (valency of 3 or 4).  The keep vertex
+      // really doesn't have any restrictions.
+      if((discard_valency > 4 || discard_valency < 3) &&
+        (keep_valency > 4 || keep_valency < 3))
+      {
+        PRINT_ERROR("Cannot currently collapse curves where one of the vertices does not have a valency equal to 3 or 4.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+      else
+      {
+        if(keep_vertex_specified)
+        {
+          if(discard_valency < 3 || discard_valency > 4)
+          {
+            PRINT_ERROR("Cannot currently collapse curves where the discard vertex valency is not 3 or 4.\n"
+                  "Try specifying the keep vertex so that the discard vertex is 3 or 4.\n");
+            result = CUBIT_FAILURE;
+            finished = 1;
+          }
+        }
+        else
+        {
+          // The user didn't specify a keep vertex so we can try to choose the best one.
+          
+          int swap_vertices = 0;
+          if(discard_valency < 5 && discard_valency > 2 &&
+            keep_valency < 5 && keep_valency > 2)
+          {
+            // Either vertex can be the discard/keep vertex so choose the one with the
+            // lower valency as the discard vertex because it will require fewer operations.
+            if(discard_valency > keep_valency)
+            {
+              swap_vertices = 1;
+            }
+          }
+          else
+          {
+            // Only one of the vertices can be the discard vertex so pick it.
+            if(discard_valency > 4 || discard_valency < 3)
+            {
+              swap_vertices = 1;
+            }
+          }
+
+          if(swap_vertices)
+          {
+            // Swap the vertices.
+            RefVertex *tmp = discard_vertex;
+            discard_vertex = keep_vertex;
+            keep_vertex = tmp;
+
+            // Make sure to refresh the discard vertex edge list because
+            // it is used below.
+            ref_edges_on_discard_vertex.clean_out();
+            discard_vertex->ref_edges(ref_edges_on_discard_vertex);
+          }
+        }
+      }
+    }
+  }
+
+  if(!finished && small_curve_size)
+  {
+    // Check if the edges attached to the discard vertex are longer 
+    // than the small curve size.
+    DLIList<RefEdge*> tmp_edges;
+    discard_vertex->ref_edges(tmp_edges);
+    if(tmp_edges.move_to(edge_to_collapse))
+      tmp_edges.extract();
+    int y;
+    bool all_edges_long_enough = true;
+    for(y=tmp_edges.size(); y && all_edges_long_enough; y--)
+    {
+      RefEdge *cur_edge = tmp_edges.get_and_step();
+      if(cur_edge->get_arc_length() <= *small_curve_size)
+        all_edges_long_enough = false;
+    }
+    if(!all_edges_long_enough)
+    {
+      PRINT_ERROR("Cannot collapse curve %d to vertex %d--not all of the curves attached to\n"
+            "vertex %d are longer than the small_curve_size.  Try collapsing to vertex %d instead.\n",
+            edge_to_collapse->id(), keep_vertex->id(), discard_vertex->id(), discard_vertex->id());
+      result = CUBIT_FAILURE;
+      finished = 1;
+    }
+  }
+
+  // Look at all of the coedges on the curve being collapsed and
+  // throw out any that are on nonmanifold surfaces.  The collapse
+  // curve may be on a boundary of a merged surface.  This is ok
+  // but we want to make sure we don't involve this surface
+  // in the partitions and composites so we will remove from the
+  // list any coedges that are hooked to merged surfaces.
+  if(!finished)
+  {
+    DLIList<CoEdge*> collapse_curve_coedges;
+    edge_to_collapse->get_co_edges(collapse_curve_coedges);
+
+    int initial_size = collapse_curve_coedges.size();
+    while(collapse_curve_coedges.size() > 2 && initial_size > 0)
+    {
+      for(int g=collapse_curve_coedges.size(); g--;)
+      {
+        CoEdge *cur_coedge = collapse_curve_coedges.get_and_step();
+        Loop *loop_ptr = cur_coedge->get_loop_ptr();
+        if(loop_ptr)
+        {
+          RefFace *ref_face_ptr = loop_ptr->get_ref_face_ptr();
+          if(ref_face_ptr)
+          {
+            DLIList<CoFace*> coface_list;
+            ref_face_ptr->co_faces(coface_list);
+            if(coface_list.size() > 1)
+            {
+              collapse_curve_coedges.remove(cur_coedge);
+              g = 0;
+            }
+          }
+        }
+      }
+
+      // Keep from looping infinitely.
+      initial_size--;
+    }
+
+    // If we get to this point and have more than 2 coedges left
+    // in the list we are not sure what to do.
+    if(collapse_curve_coedges.size() != 2)
+    {
+      PRINT_ERROR("Currently can only collapse curves with manifold topology.\n");
+      result = CUBIT_FAILURE;
+      finished = 1;
+    }
+    else
+    {
+      // Get the collapse curve coedges entering and leaving the discard vertex.
+      exit_coedge = collapse_curve_coedges.get_and_step();
+      enter_coedge = collapse_curve_coedges.get();
+      if(enter_coedge->end_vertex() != discard_vertex)
+      {
+        CoEdge *tmp = exit_coedge;
+        exit_coedge = enter_coedge;
+        enter_coedge = tmp;
+      }
+    }
+  }
+
+  // Next we need to explore the topology around the discard vertex
+  // so that we can get the edges and surfaces that will be involved
+  // with the partitioning and compositing.  We will identify a "left"
+  // and "right" edge coming out of the discard vertex and adjacent
+  // surfacs to these edges.
+  if(!finished)
+  {
+    // Get these values for use later on.
+    discard_pos = discard_vertex->get_point_ptr()->coordinates();
+    keep_pos = keep_vertex->get_point_ptr()->coordinates();
+    CubitVector discard_to_keep = keep_pos - discard_pos;
+    arc_length = edge_to_collapse->get_arc_length();
+
+    // Depending on whether the discard vertex has valency of 3 or 4 we will
+    // either partition 1 or 2 of the curves coming into the discard vertex
+    // respectively.  Set up lists so that below we can just loop through the
+    // partitioning and compositing for either the 3 or 4 valency case.
+
+    // "Left" and "right" will be defined as if you were standing on the
+    // keep vertex looking at the discard vertex.
+    Loop *left_loop = enter_coedge->get_loop_ptr();
+    Loop *right_loop = exit_coedge->get_loop_ptr();
+    DLIList<SenseEntity*> left_sense_entities, right_sense_entities;
+    left_loop->get_sense_entity_list(left_sense_entities);
+    right_loop->get_sense_entity_list(right_sense_entities);
+
+    // We need to get these two coedges because the chains defined by the "next" and 
+    // "previous" pointers in the CoEdge objects are not circular (you can have a NULL
+    // "previous" or "next" pointer).  We will manage the circularity manually.
+    CoEdge *left_start = dynamic_cast<CoEdge*>(left_loop->get_first_sense_entity_ptr()); 
+    CoEdge *right_end = dynamic_cast<CoEdge*>(right_loop->get_last_sense_entity_ptr()); 
+    
+    CoEdge *left_coedge = dynamic_cast<CoEdge*>(enter_coedge->next());
+    if(left_coedge == NULL)
+    {
+      left_coedge = left_start;
+    }
+    CoEdge *right_coedge = dynamic_cast<CoEdge*>(exit_coedge->previous());
+    if(right_coedge == NULL)
+    {
+      right_coedge = right_end;
+    }
+
+    RefEdge *left_edge = left_coedge->get_ref_edge_ptr();
+    RefEdge *right_edge = right_coedge->get_ref_edge_ptr();
+    RefFace *left_common_face = left_edge->common_ref_face(edge_to_collapse);
+    RefFace *right_common_face = right_edge->common_ref_face(edge_to_collapse);
+
+    double left_arc_length = left_edge->get_arc_length();
+    double right_arc_length = right_edge->get_arc_length();
+    int left_ok = 1;
+    int right_ok = 1;
+
+    DLIList<RefEdge*> left_face_edges;
+    DLIList<RefEdge*> right_face_edges;
+    left_common_face->ref_edges(left_face_edges);
+    right_common_face->ref_edges(right_face_edges);
+    if(left_face_edges.size() < 3 || right_face_edges.size() < 3 ||
+      left_sense_entities.size() < 3 || right_sense_entities.size() < 3)
+    {
+      PRINT_ERROR("Cannot collapse a curve that bounds a face or loop with only two edges.\n");
+      result = CUBIT_FAILURE;
+      finished = 1;
+    }
+    else
+    {
+      // We use the length of the curve being collapsed as the distance
+      // to partition the adjacent curves connected to it.  If the
+      // adjacent curves are shorter than the curve being collapsed we
+      // will bail because the user should probably be getting rid
+      // of the adjacent edges instead or at least first.
+
+      // Get the length of the adjacent curves.
+      
+      // If the adjacent curve is within resabs of the length of 
+      // the curve being collapsed we will just snap to the end
+      // of the adjacent curve for our partition position.
+      if(arc_length > left_arc_length + GEOMETRY_RESABS)
+      {
+        left_ok = 0;
+      }
+      if(arc_length > right_arc_length + GEOMETRY_RESABS)
+      {
+        right_ok = 0;
+      }
+
+      // If neither curve is ok we need to bail.
+      if(!left_ok && !right_ok)
+      {
+        PRINT_ERROR("Curve being collapsed is too long compared to adjacent curves.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+    }
+
+    // If it looks like the lengths of the adjacent curves are
+    // ok we will go ahead and try to find a partition position
+    // on them.
+    if(!finished)
+    {
+      if(left_ok)
+      {
+         // First see if we can just use the end point of the
+         // adjacent curve as the partition position.
+         if(fabs(left_arc_length-arc_length) < GEOMETRY_RESABS)
+         {
+           if(left_edge->start_vertex() == discard_vertex)
+             position_on_left_curve = left_edge->end_vertex()->coordinates();
+           else
+             position_on_left_curve = left_edge->start_vertex()->coordinates();
+         }
+         else
+         {
+           result = this->position_from_length(left_edge, discard_vertex,
+                arc_length, position_on_left_curve);
+         }
+      }
+      if(result == CUBIT_SUCCESS && right_ok)
+      {
+         // First see if we can just use the end point of the
+         // adjacent curve as the partition position.
+         if(fabs(right_arc_length-arc_length) < GEOMETRY_RESABS)
+         {
+           if(right_edge->start_vertex() == discard_vertex)
+             position_on_right_curve = right_edge->end_vertex()->coordinates();
+           else
+             position_on_right_curve = right_edge->start_vertex()->coordinates();
+         }
+         else
+         {
+            result = this->position_from_length(right_edge, discard_vertex,
+                  arc_length, position_on_right_curve);
+         }
+      }
+      if(result == CUBIT_FAILURE)
+      {
+        PRINT_ERROR("Was unable to locate appropriate partition points on curves adjacent to curve being collapased.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+    }
+      
+    if(!finished)
+    {
+      // Get the vectors from the discard vertex to the potential partition locations.
+      CubitVector left_vec = position_on_left_curve - discard_pos;
+      CubitVector right_vec = position_on_right_curve - discard_pos;
+
+      // Calculate the angles between the left/right edge and the
+      // edge being collapsed.  I am doing it this way rather than just
+      // calling RefEdge::angle_between() because I want the angle
+      // calculation done out at the potential partition location.
+      // This will step over any small kinks in the curve near the
+      // discard vertex that might otherwise give misleading angles
+      // that don't represent what is happening out by the potential
+      // partition position.
+      left_common_face->u_v_from_position(discard_pos, u, v);
+      CubitVector left_normal = left_common_face->normal_at(discard_pos, NULL, &u, &v);
+      double left_angle = left_normal.vector_angle(left_vec, discard_to_keep);
+
+      right_common_face->u_v_from_position(discard_pos, u, v);
+      CubitVector right_normal = right_common_face->normal_at(discard_pos, NULL, &u, &v);
+      double right_angle = right_normal.vector_angle(discard_to_keep, right_vec);
+
+      // 3 valency case: 
+      // We only need to partition one of the curves (left or right) and
+      // the corresponding surface.
+      if(ref_edges_on_discard_vertex.size() == 3)
+      {
+        int use_left = 0;
+        // We can use either adjacent curve.
+        if(left_ok && right_ok)
+        {
+          // Choose the side with the smaller angle as this will in general
+          // give better angles for doing the partitioning on the surface.
+          CompositeSurface *cs_left = dynamic_cast<CompositeSurface*>(left_common_face->get_surface_ptr());
+          CompositeSurface *cs_right = dynamic_cast<CompositeSurface*>(right_common_face->get_surface_ptr());
+          if(!cs_left && cs_right)
+            use_left = 1;
+          else if(cs_left && !cs_right)
+            use_left = 0;
+          else
+          {
+            if(cs_left && cs_right)
+            {
+              int edge_on_ignored_left=0, edge_on_ignored_right=0;
+              DLIList<Surface*> srfs;
+              cs_left->get_ignored_surfs(srfs);
+              int g;
+              for(g=srfs.size(); g>0 && !edge_on_ignored_left; g--)
+              {
+                Surface *srf = srfs.get_and_step();
+                DLIList<Curve*> crvs;
+                srf->curves(crvs);
+                if(crvs.is_in_list(edge_to_collapse->get_curve_ptr()))
+                  edge_on_ignored_left = 1;
+              }
+              srfs.clean_out();
+              cs_right->get_ignored_surfs(srfs);
+              for(g=srfs.size(); g>0 && !edge_on_ignored_right; g--)
+              {
+                Surface *srf = srfs.get_and_step();
+                DLIList<Curve*> crvs;
+                srf->curves(crvs);
+                if(crvs.is_in_list(edge_to_collapse->get_curve_ptr()))
+                  edge_on_ignored_right = 1;
+              }
+              if(edge_on_ignored_left && !edge_on_ignored_right)
+                use_left = 0;
+              else if(!edge_on_ignored_left && edge_on_ignored_right)
+                use_left = 1;
+              else
+              {
+                if(left_angle < right_angle)
+                  use_left = 1;
+              }
+            }
+            else
+            {
+              if(left_angle < right_angle)
+                use_left = 1;
+            }
+          }
+        }
+        else if(left_ok)
+          use_left = 1;
+
+        if(use_left)
+        {
+          curves_to_partition.append(left_edge);
+          surfaces_to_partition.append(left_common_face);
+          angles.append(left_angle);
+          partition_positions.append(position_on_left_curve);
+          arc_lengths.append(arc_length);
+ 
+          // These vectors will be used in calculating a bisector direction
+          // below if necessary.
+          keep_vecs.append(-discard_to_keep);
+          partition_curve_vecs.append(left_vec);
+        }
+        else
+        {
+          curves_to_partition.append(right_edge);
+          surfaces_to_partition.append(right_common_face);
+          angles.append(right_angle);
+          partition_positions.append(position_on_right_curve);
+          arc_lengths.append(arc_length);
+ 
+          // These vectors will be used in calculating a bisector direction
+          // below if necessary.
+          keep_vecs.append(discard_to_keep);
+          partition_curve_vecs.append(-right_vec);
+        }
+      }
+      else if(ref_edges_on_discard_vertex.size() == 4)
+      {
+        // We have to partition both left and right curves so make
+        // sure we can.
+        if(!left_ok || !right_ok)
+        {
+          PRINT_ERROR("One of the curves adjacent to the collapse curve is not long enough for the collapse operation.\n");
+          result = CUBIT_FAILURE;
+          finished = 1;
+        }
+        else
+        {
+          // Both curves (and surfaces) adjacent to the collapse curve (left and right)
+          // will need to be partitioned so add them to the lists.
+
+          curves_to_partition.append(left_edge);
+          curves_to_partition.append(right_edge);
+          surfaces_to_partition.append(left_common_face);
+          surfaces_to_partition.append(right_common_face);
+          angles.append(left_angle);
+          angles.append(right_angle);
+          keep_vecs.append(-discard_to_keep);
+          keep_vecs.append(discard_to_keep);
+          partition_curve_vecs.append(left_vec);
+          partition_curve_vecs.append(-right_vec);
+          partition_positions.append(position_on_left_curve);
+          partition_positions.append(position_on_right_curve);
+          arc_lengths.append(arc_length);
+          arc_lengths.append(arc_length);
+        }
+      }
+      else
+      {
+        PRINT_ERROR("Currently can only collapse curves with 3 or 4 valency vertices.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+    }
+  }
+
+  if(!finished)
+  {
+    int num_reps = curves_to_partition.size();
+    curves_to_partition.reset();
+    surfaces_to_partition.reset();
+    for(int n=0; n<num_reps && !finished; ++n)
+    {
+      RefEdge *side_edge = curves_to_partition.get_and_step();
+      RefFace *side_face = surfaces_to_partition.get_and_step();
+
+      // Now we need to find the face on the other side of the edge.
+      // Because there may be edges on the boundaries of merged surfaces
+      // we want to find the
+      // face on the left/right edge that isn't the face shared by
+      // the collapse edge and isn't nonmanifold.
+      DLIList<CoEdge*> side_edge_coedges;
+      side_edge->co_edges(side_edge_coedges);
+      DLIList<RefFace*> possible_adj_faces;
+
+      // First loop through and get all of the potential faces.
+      for(int r=side_edge_coedges.size(); r--;)
+      {
+        CoEdge *cur_coedge = side_edge_coedges.get_and_step();
+        if(cur_coedge &&
+          cur_coedge->get_loop_ptr() &&
+          cur_coedge->get_loop_ptr()->get_ref_face_ptr())
+        {
+          RefFace *cur_ref_face = cur_coedge->get_loop_ptr()->get_ref_face_ptr();
+          if(cur_ref_face != side_face)
+          {
+            DLIList<CoFace*> coface_list;
+            cur_ref_face->co_faces(coface_list);
+
+            // Along with checking for whether the face is manifold we need
+            // to check if it belongs to the same volume as the side face.
+            // We have to check this because we can't composite faces
+            // from different volumes and these faces will be involved in
+            // a composite below.
+            if(coface_list.size() == 1 &&
+              side_face->ref_volume() == cur_ref_face->ref_volume())
+            {
+              possible_adj_faces.append(cur_ref_face);
+            }
+          }
+        }
+      }
+
+      // If we ended up with more than one face in the list it isn't clear
+      // what we should do so bail out.
+      if(possible_adj_faces.size() != 1)
+      {
+        PRINT_ERROR("Couldn't figure out how to perform the collapse curve with the current topology.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+      else
+      {
+        adjacent_surfaces.append(possible_adj_faces.get());
+      }
+    }
+  }
+
+  if(!finished)
+  {
+    // At this point we should know which curves and surfaces we need
+    // to partition.
+
+    int num_reps = curves_to_partition.size();
+    curves_to_partition.reset();
+    surfaces_to_partition.reset();
+    adjacent_surfaces.reset();
+    angles.reset();
+    keep_vecs.reset();
+    partition_curve_vecs.reset();
+    partition_positions.reset();
+    arc_lengths.reset();
+
+    for(int i=0; i<num_reps && !finished; ++i)
+    {
+      RefEdge *curve_to_partition = curves_to_partition.get_and_step();
+      RefFace *surface_to_partition = surfaces_to_partition.get_and_step();
+
+      // Sanity check to make sure a previous operation has not 
+      // destroyed the current face.
+      DLIList<RefFace*> body_faces;
+      the_body->ref_faces(body_faces);
+      if(body_faces.is_in_list(surface_to_partition))
+      {
+        // As we process each curve remove it from the list so that
+        // at the end we can take the last one in the list and composite
+        // it with the curve being collapsed.
+        ref_edges_on_discard_vertex.remove(curve_to_partition);
+
+        CubitVector position_on_curve = partition_positions.get_and_step();
+        DLIList<CubitVector*> positions;
+
+        // Add the point on the curve we just partitioned.  The other
+        // point we normally need to add is the keep_vertex.  However,
+        // if the angle between the collapse curve and the curve we 
+        // just partitioned dictates that we need to introduce more points 
+        // (this would be cases where the angle is large and just partitioning the
+        // surface with one curve--two points--would result in a very skinny
+        // surface) we need to add them before adding the keep_vertex.  Therefore, check
+        // that now and add the extra points if needed.
+        positions.append(new CubitVector(position_on_curve));
+
+        double cur_angle = angles.get_and_step();
+        arc_length = arc_lengths.get_and_step();
+
+        // These vectors are only used in the block below if we need to
+        // add extra points but we need to always retrieve them from the lists
+        // so that the pointer in the list stays in sync with the "for" loop.
+        CubitVector keep_vec = keep_vecs.get_and_step();
+        CubitVector partition_vec = partition_curve_vecs.get_and_step();
+
+        // Greater than 3*PI/2--add 3 interior points.  Two of these
+        // points will be generated by projecting from the discard vertex
+        // into the surface normal to the vector from the discard vertex
+        // to the keep point and new partition point respectively.  The third
+        // point will be obtained by projecting from the discard point in the
+        // direction of the bisector angle of the two previous projections.
+        if(cur_angle > 4.71)
+        {
+          // Get the u,v position of the discard vertex on this surface.
+          surface_to_partition->u_v_from_position(discard_pos, u, v);
+          
+          // Get the normal at the discard vertex.
+          CubitVector normal = surface_to_partition->normal_at(discard_pos, NULL, &u, &v);
+          normal.normalize();
+          
+          // We need to calculate a bisector direction between the
+          // collape edge and the edge we just partitioned.  We will do 
+          // this using the face normal at the discard vertex and the vectors 
+          // we calculated previously with the partition points.  Cross
+          // the face normal into the the direction vectors at the 
+          // discard and partition points to get two vectors pointing
+          // into the face and then average those two to get the
+          // bisector direction.  This is all approximate but should 
+          // be sufficient for locating another point for partitioning 
+          // the surface.
+
+          // I am not normalizing the result here because they should
+          // be roughly the same length and it shouldn't affect 
+          // the average too much.
+          CubitVector vec1 = normal * partition_vec;
+          CubitVector vec2 = normal * keep_vec;
+
+          // Get the bisector direction.
+          CubitVector bisector_dir = vec1 + vec2;
+          bisector_dir.normalize();
+
+          // Now normalise these because they will be used to
+          // project two of the new interior points.
+          vec1.normalize();
+          vec2.normalize();
+
+          CubitVector new_pos1 = discard_pos + (arc_length*vec1);
+          CubitVector mid_pos = discard_pos + (arc_length * bisector_dir);
+          CubitVector new_pos2 = discard_pos + (arc_length*vec2);
+
+          // Use the u,v from the discard vertex because it is fairly
+          // close to the new position and will at least provide a
+          // meaningful starting point.
+          double save_u = u, save_v = v;
+          surface_to_partition->move_to_surface(new_pos1, &u, &v);
+          u = save_u; v = save_v;
+          surface_to_partition->move_to_surface(mid_pos, &u, &v);
+          u = save_u; v = save_v;
+          surface_to_partition->move_to_surface(new_pos2, &u, &v);
+
+          // Add the new position to the list of partition points.
+          positions.append(new CubitVector(new_pos1));
+          positions.append(new CubitVector(mid_pos));
+          positions.append(new CubitVector(new_pos2));
+        }
+        // Greater than 3*PI/4 and less than 3*PI/2--add one interior point
+        else if(cur_angle > 2.4)
+        {
+          CubitVector third_pt;
+          
+          // Get the u,v position of the discard vertex on this surface.
+          surface_to_partition->u_v_from_position(discard_pos, u, v);
+          
+          // Get the normal at the discard vertex.
+          CubitVector normal = surface_to_partition->normal_at(discard_pos, NULL, &u, &v);
+          normal.normalize();
+          
+          // We need to calculate a bisector direction between the
+          // collape edge and the edge we just partitioned.  We will do 
+          // this using the face normal at the discard vertex and the vectors 
+          // we calculated previously with the partition points.  Cross
+          // the face normal into the the direction vectors at the 
+          // discard and partition points to get two vectors pointing
+          // into the face and then average those two to get the
+          // bisector direction.  This is all approximate but should 
+          // be sufficient for locating another point for partitioning 
+          // the surface.
+
+          // I am not normalizing the result here because they should
+          // be roughly the same length and it shouldn't affect 
+          // the average too much.
+          CubitVector vec1 = normal * keep_vec;
+          CubitVector vec2 = normal * partition_vec;
+
+          // Get the bisector direction.
+          CubitVector bisector_dir = vec1 + vec2;
+          bisector_dir.normalize();
+
+          // Project from the discard vertex in the direction of the
+          // bisector direction to get a new point for partitioning
+          // the surface.
+          CubitVector new_pos = discard_pos + (arc_length * bisector_dir);
+
+          // Use the u,v from the discard vertex because it is fairly
+          // close to the new position and will at least provide a
+          // meaningful starting point.
+          surface_to_partition->move_to_surface(new_pos, &u, &v);
+
+          // Add the new position to the list of partition points.
+          positions.append(new CubitVector(new_pos));
+        }
+
+        // Finally, add the keep_vertex to the list.
+        positions.append(new CubitVector(keep_vertex->get_point_ptr()->coordinates()));
+                
+        DLIList<RefEdge*> new_edges;
+        DLIList<DLIList<CubitVector*>*> vec_lists;
+        DLIList<CubitVector*> *vec_list = new DLIList<CubitVector*>;
+        positions.reset();
+        for(int m=positions.size(); m--;)
+          vec_list->append( new CubitVector( *positions.get_and_step() ) );
+        vec_lists.append( vec_list );
+
+        if(!SplitCompositeSurfaceTool::instance()->split_surface(surface_to_partition,
+          positions, vec_lists ))
+        {
+          finished = 1;
+          result = CUBIT_FAILURE;
+        }
+
+        while( vec_lists.size() )
+        {
+          DLIList<CubitVector*> *vec_list = vec_lists.pop();
+          while( vec_list->size() ) delete vec_list->pop();
+          delete vec_list;
+        }
+
+        delete positions.get_and_step();
+        delete positions.get_and_step();
+
+        if(cur_angle > 4.71)
+        {
+          delete positions.get_and_step();
+          delete positions.get_and_step();
+          delete positions.get_and_step();
+        }
+        else if(cur_angle > 2.4)
+        {
+          delete positions.get();
+        }
+
+        if(!finished)
+        {
+          RefFace *new_small_face = NULL;
+          DLIList<RefEdge*> keep_edges, discard_edges;
+          DLIList<RefFace*> faces_on_collapse_edge;
+          keep_vertex->ref_edges(keep_edges);
+          discard_vertex->ref_edges(discard_edges);
+          keep_edges.intersect_unordered(discard_edges);
+          if(keep_edges.size() != 1)
+          {
+            finished = 1;
+            result = CUBIT_FAILURE;
+          }
+          else
+          {
+            edge_to_collapse = keep_edges.get();
+            edge_to_collapse->ref_faces(faces_on_collapse_edge);
+            for(int y=faces_on_collapse_edge.size(); y && !new_small_face; y--)
+            {
+              RefFace *cur_face = faces_on_collapse_edge.get_and_step();
+              DLIList<RefVertex*> verts_in_face;
+              cur_face->ref_vertices(verts_in_face);
+              for(int p=verts_in_face.size(); p && !new_small_face; p--)
+              {
+                RefVertex *cur_vert = verts_in_face.get_and_step();
+                if(position_on_curve.about_equal(cur_vert->coordinates()))
+                  new_small_face = cur_face;
+              }
+            }
+          }
+
+          if(!new_small_face || new_small_face == surface_to_partition)
+          {
+            PRINT_ERROR("Failed to do the split surface operation of the collapse curve.\n");
+            result = CUBIT_FAILURE;
+            finished = 1;
+          }
+          else
+          {
+            RefVertex *vert_at_split_pos;
+            DLIList<RefEdge*> new_face_edges;
+            new_small_face->ref_edges(new_face_edges);
+            if(new_face_edges.is_in_list(curve_to_partition))
+            {
+              // The split went right through one of the vertices of the
+              // curve_to_partition so just set the close edge to be
+              // this edge and the far edge to be NULL.
+              close_edge = curve_to_partition;
+              far_edge = NULL;
+              vert_at_split_pos = close_edge->other_vertex(discard_vertex);
+            }
+            else
+            {
+              close_edge = edge_to_collapse->get_other_curve(discard_vertex, new_small_face);
+              RefVertex *tmp_vert = close_edge->other_vertex(discard_vertex);
+              if(tmp_vert)
+              {
+                RefEdge *tmp_edge = close_edge->get_other_curve(tmp_vert, new_small_face);
+                if(tmp_edge)
+                {
+                  RefFace *other_face = tmp_edge->other_face(new_small_face);
+                  if(other_face)
+                  {
+                    far_edge = tmp_edge->get_other_curve(tmp_vert, other_face);
+                    vert_at_split_pos = tmp_vert;
+                    // If close_edge and far_edge are the same it may mean
+                    // that the split really didn't do much other than maybe 
+                    // imprint one point on an edge so bail out.
+                    if(far_edge == close_edge)
+                    {
+                      PRINT_ERROR("Failed to do the split surface operation of the collapse curve.\n");
+                      result = CUBIT_FAILURE;
+                      finished = 1;
+                    }
+                  }
+                  else
+                  {
+                    result = CUBIT_FAILURE;
+                    finished = 1;
+                  }
+                }
+                else
+                {
+                  result = CUBIT_FAILURE;
+                  finished = 1;
+                }
+              }
+              else
+              {
+                finished = 1;
+                result = CUBIT_FAILURE;
+              }
+            }
+
+            if(!finished)
+            {
+              RefEdge *cur_edge = close_edge;
+              RefVertex *cur_vert = vert_at_split_pos;
+              while(cur_vert != keep_vertex)
+              {
+                cur_edge = cur_edge->get_other_curve(cur_vert, new_small_face);
+                cur_vert = cur_edge->other_vertex(cur_vert);
+                new_edges.append(cur_edge);
+              }
+
+              DLIList<RefFace*> result_faces;
+              DLIList<RefFace*> faces_to_composite;
+
+              // Used below if "ignore" keyword was specified.
+              int new_small_face_id = new_small_face->id();
+
+              faces_to_composite.append(new_small_face);
+              faces_to_composite.append(close_edge->other_face(new_small_face));
+
+              RefFace *new_comp_face = CompositeTool::instance()->composite(faces_to_composite);
+
+              CompositeSurface* csurf = NULL;
+              
+              if(new_comp_face)
+              {
+                csurf = dynamic_cast<CompositeSurface*>(new_comp_face->get_surface_ptr());
+              }
+
+              if(!new_comp_face || !csurf)
+              {
+                PRINT_ERROR("Failed to do the composite surface operation of the collapse curve.\n");
+                result = CUBIT_FAILURE;
+                finished = 1;
+              }
+              else
+              {
+                if(ignore_surfaces)
+                {
+                  csurf->ignore_surface(new_small_face_id);
+                }
+
+                if(far_edge)
+                {
+                  for(int k=new_edges.size(); k--;)
+                  {
+                    edges_to_composite.append(new_edges.get_and_step());
+                  }
+                  edges_to_composite.append(far_edge);
+
+                  if(edges_to_composite.size() > 1)
+                  {
+                    CompositeTool::instance()->composite(edges_to_composite);
+                  }
+                }
+
+                edges_to_composite.clean_out();
+              }
+            }
+          }
+        }
+      }
+    }
+
+    if(!finished)
+    {
+      ref_edges_on_discard_vertex.clean_out();
+      discard_vertex->ref_edges(ref_edges_on_discard_vertex);
+      ref_edges_on_discard_vertex.remove(edge_to_collapse);
+
+      // Now there should only be one edge in the ref_edges_on_discard_vertex
+      // list.  It should be the edge that hasn't had any modifications
+      // done to it.  We finally want to composite it with the edge
+      // being collapsed.
+      if(ref_edges_on_discard_vertex.size() != 1)
+      {
+        PRINT_ERROR("Wasn't able to complete collapse operation.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+      else
+      {
+        edges_to_composite.append(ref_edges_on_discard_vertex.get());
+        edges_to_composite.append(edge_to_collapse);
+        CompositeTool::instance()->composite(edges_to_composite);
+      }
+    }
+  }
+
+  CubitUndo::set_undo_enabled(undo_state);
+
   return result;
 }
 

Modified: cgm/branches/cubit/geom/virtual/CollapseCurveTool.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CollapseCurveTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CollapseCurveTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -20,8 +20,13 @@
 
     CubitStatus collapse_curve(DLIList <RefEdge*> ref_edge_list, 
                 DLIList<RefVertex*> ref_vertex_list,
-                int ignore_surfaces); 
+                int ignore_surfaces,
+                double *small_curve_size = NULL); 
 
+    CubitStatus collapse_curve_only_virtual(DLIList <RefEdge*> ref_edge_list, 
+                                        DLIList<RefVertex*> ref_vertex_list,
+                                        int ignore_surfaces,
+                                        double *small_curve_size = NULL);
   private:
     CollapseCurveTool();
     // Constructor

Modified: cgm/branches/cubit/geom/virtual/CompSurfFacets.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompSurfFacets.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompSurfFacets.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -20,7 +20,6 @@
 CubitStatus CompSurfFacets::setup( const SurfPtrList& surface_data )
 {
   GMem gmem;
-  int num_points, num_facets, num_triangles;
   
   // Set the size of this array of flags.
   ignoreFlags.resize(surface_data.size());
@@ -31,37 +30,37 @@
     Surface* surface = surface_data[index];
     
     CubitStatus result = surface->get_geometry_query_engine()
-      ->get_graphics( surface, num_triangles, num_points, num_facets, &gmem );
+      ->get_graphics( surface, &gmem );
     if ( !result )
       return CUBIT_FAILURE;
       
     int* f_itor = gmem.facet_list();
-    int* f_end = f_itor + num_facets;
+    int* f_end = f_itor + gmem.fListCount;
     int tri_count = 0;
+    bool non_tri = false;
     while ( f_itor < f_end )
     {
         // If facet is not a triangle, it will be split into
         // triangles later.  Update tri_count accordingly.
       int pt_count = *f_itor;
+      if(pt_count != 3)
+        non_tri = true;
       tri_count += pt_count - 2;
       f_itor += (pt_count + 1);
     }
-    
-    if (tri_count != num_triangles)
+
+    if(non_tri)
       PRINT_WARNING("Non-triangular facets encountered in surface graphics.\n");
     
-    assert(gmem.fListCount == num_facets);
-    assert(gmem.pointListCount == num_points);
-    
     int offset = pointList.size();
-    pointList.resize( offset + num_points );
+    pointList.resize( offset + gmem.pointListCount );
     
     int tri_offset = triangleData.size();
     triangleData.resize( tri_offset + tri_count * 4 );
     
     PointList::iterator p_itor = pointList.begin() + offset;
     GPoint* g_itor = gmem.point_list();
-    GPoint* g_end = g_itor + num_points;
+    GPoint* g_end = g_itor + gmem.pointListCount;
     for ( ; g_itor != g_end; ++g_itor )
     {
       //CubitVector vect(g_itor->x, g_itor->y, g_itor->z);
@@ -74,7 +73,7 @@
     
     IntegerList::iterator t_itor = triangleData.begin() + tri_offset;
     f_itor = gmem.facet_list();
-    f_end = f_itor + num_facets;
+    f_end = f_itor + gmem.fListCount;
     while ( f_itor != f_end )
     {
         // Copy facet into triangleData.
@@ -465,10 +464,12 @@
     // Update the facet list using values from index_map.
   IntegerList::iterator itor = triangleData.begin();
   IntegerList::iterator end = triangleData.end();
-  while( itor++ != end )
+  while( itor != end )
+  {
+	++itor;
     for( int count = 3; count--; itor++ )
       *itor = index_map[*itor];
-
+  }
   delete [] index_map;
   pointsConsolidated = true;
 }
@@ -530,10 +531,13 @@
     // Use index_map to update facet list
   IntegerList::iterator itor = triangleData.begin();
   IntegerList::iterator end  = triangleData.end();
-  while (itor++ != end)
-    for (int count = 3; count--; itor++)
+  while( itor != end )
+  {
+	  ++itor;
+	  for (int count = 3; count--; itor++)
       *itor = index_map[*itor];
-  
+  }
+
   delete [] index_map;
   pointsConsolidated = true;
 }

Modified: cgm/branches/cubit/geom/virtual/CompositeEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -6,6 +6,7 @@
 #include "DLIList.hpp"
 #include "TDUniqueId.hpp"
 #include "CubitTransformMatrix.hpp"
+#include "RTree.hpp"
 
 #include "CompositePoint.hpp"
 #include "CompositeCurve.hpp"
@@ -15,6 +16,7 @@
 #include "CompositeShell.hpp"
 #include "CompositeLump.hpp"
 #include "CompositeBody.hpp"
+#include "GfxPreview.hpp"
 
 #include "PartitionPoint.hpp"
 #include "SegmentedCurve.hpp"
@@ -23,6 +25,7 @@
 
 #include "VGLoopTool.hpp"
 #include "Body.hpp"
+#include "LumpSM.hpp"
 
 #include "GeometryQueryTool.hpp"
 
@@ -32,11 +35,31 @@
                    CompositeCurve,
                    CompositePoint> CompLoopTool;
 
-CompositeEngine::~CompositeEngine() {}
+CompositeEngine* CompositeEngine::instance_ = NULL; 
 
+
+CompositeEngine::~CompositeEngine()
+{
+  GeometryQueryTool::instance()->unregister_intermediate_engine(this);
+}
+
+void CompositeEngine::delete_instance()
+{
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}
+
 CompositeEngine& CompositeEngine::instance()
 {
-  static CompositeEngine* instance_ = new CompositeEngine();
+  if( instance_ == NULL )
+  {
+    instance_ = new CompositeEngine();
+    assert( instance != NULL );
+  }
+  
   return *instance_;
 }
 
@@ -111,17 +134,76 @@
   }
 }
 
-// This function pushes specified named attributes onto all curves
-// and vertices.
 void CompositeEngine::push_imprint_attributes_before_modify
-                     ( DLIList<BodySM*> &bodies )
+                     ( DLIList<BodySM*> &bodies)
 {
-  int k, m, q, w, g, b, s, t;
-  CubitString name("IMPRINT_PREEXISTING");
+}
+
+void CompositeEngine::push_named_attributes_to_curves_and_points
+//                     ( DLIList<BodySM*> &bodies, char *name_in)
+                     ( DLIList<TopologyBridge*> &in_list, const char *name_in)
+{
+  int i/*, k, m, q, w, g, b, s, t*/;
+  CubitString name(name_in);
   DLIList<CubitString*> string_list;
   string_list.append( &name );
-  CubitSimpleAttrib geom_attrib( &string_list, 0, 0 );
+  CubitSimpleAttrib attrib( &string_list, 0, 0 );
 
+  for(i=in_list.size(); i>0; i--)
+  {
+    TopologyBridge *tb = in_list.get_and_step();
+    if(dynamic_cast<BodySM*>(tb))
+    {
+      DLIList<TopologyBridge*> lumps;
+      tb->get_children_virt(lumps);
+      push_named_attributes_to_curves_and_points(lumps, name_in);
+    }
+    else if(dynamic_cast<Lump*>(tb))
+    {
+      DLIList<TopologyBridge*> shells;
+      tb->get_children_virt(shells);
+      push_named_attributes_to_curves_and_points(shells, name_in);
+    }
+    else if(dynamic_cast<ShellSM*>(tb))
+    {
+      DLIList<TopologyBridge*> surfs;
+      tb->get_children_virt(surfs);
+      push_named_attributes_to_curves_and_points(surfs, name_in);
+    }
+    else if(dynamic_cast<Surface*>(tb))
+    {
+      DLIList<TopologyBridge*> loops;
+      tb->get_children_virt(loops);
+      push_named_attributes_to_curves_and_points(loops, name_in);
+    }
+    else if(dynamic_cast<LoopSM*>(tb))
+    {
+      DLIList<TopologyBridge*> coedges;
+      tb->get_children_virt(coedges);
+      push_named_attributes_to_curves_and_points(coedges, name_in);
+    }
+    else if(dynamic_cast<CoEdgeSM*>(tb))
+    {
+      DLIList<TopologyBridge*> curves;
+      tb->get_children_virt(curves);
+      push_named_attributes_to_curves_and_points(curves, name_in);
+    }
+    else if(dynamic_cast<Curve*>(tb))
+    {
+      append_attrib( tb, &attrib );
+      DLIList<TopologyBridge*> points;
+      tb->get_children_virt(points);
+      push_named_attributes_to_curves_and_points(points, name_in);
+    }
+    else if(dynamic_cast<Point*>(tb))
+    {
+      append_attrib( tb, &attrib );
+    }
+  }
+
+/*
+
+
   DLIList<TopologyBridge*> top_bridges;
   CAST_LIST_TO_PARENT(bodies, top_bridges);
   for(k=top_bridges.size(); k--;)
@@ -157,19 +239,13 @@
               for(s=curves.size(); s--;)
               {
                 TopologyBridge *cur_curve = curves.get_and_step();
-                DLIList<CubitSimpleAttrib*> list;
-                cur_curve->get_simple_attribute("COMPOSITE_GEOM",list);
-                if(list.size() == 0)
-                  append_attrib( cur_curve, &geom_attrib );
+                append_attrib( cur_curve, &attrib );
                 DLIList<TopologyBridge*> pts;
                 cur_curve->get_children_virt(pts);
                 for(t=pts.size(); t--;)
                 {
                   TopologyBridge *cur_pt = pts.get_and_step();
-                  list.clean_out();
-                  cur_pt->get_simple_attribute("COMPOSITE_GEOM",list);
-                  if(list.size() == 0)
-                    append_attrib( cur_pt, &geom_attrib );
+                  append_attrib( cur_pt, &attrib );
                 }
               }
             }
@@ -178,243 +254,464 @@
       }
     }
   }
+  */
 }
 
+void CompositeEngine::get_all_curves_and_points(DLIList<TopologyBridge*> &tb_list,
+                                                DLIList<Curve*> &curves,
+                                                DLIList<Point*> &points)
+{
+  int i;
+  Curve *crv;
+  Point *pt;
+  for(i=tb_list.size(); i>0; i--)
+  {
+    TopologyBridge *tb = tb_list.get_and_step();
+    if(dynamic_cast<BodySM*>(tb))
+    {
+      DLIList<TopologyBridge*> lumps;
+      tb->get_children_virt(lumps);
+      get_all_curves_and_points(lumps, curves, points);
+    }
+    else if(dynamic_cast<Lump*>(tb))
+    {
+      DLIList<TopologyBridge*> shells;
+      tb->get_children_virt(shells);
+      get_all_curves_and_points(shells, curves, points);
+    }
+    else if(dynamic_cast<ShellSM*>(tb))
+    {
+      DLIList<TopologyBridge*> surfs;
+      tb->get_children_virt(surfs);
+      get_all_curves_and_points(surfs, curves, points);
+    }
+    else if(dynamic_cast<Surface*>(tb))
+    {
+      DLIList<TopologyBridge*> loops;
+      tb->get_children_virt(loops);
+      get_all_curves_and_points(loops, curves, points);
+    }
+    else if(dynamic_cast<LoopSM*>(tb))
+    {
+      DLIList<TopologyBridge*> coedges;
+      tb->get_children_virt(coedges);
+      get_all_curves_and_points(coedges, curves, points);
+    }
+    else if(dynamic_cast<CoEdgeSM*>(tb))
+    {
+      DLIList<TopologyBridge*> tmp_curves;
+      tb->get_children_virt(tmp_curves);
+      get_all_curves_and_points(tmp_curves, curves, points);
+    }
+    else if((crv = dynamic_cast<Curve*>(tb)))
+    {
+      curves.append(crv);
+      DLIList<TopologyBridge*> tmp_points;
+      tb->get_children_virt(tmp_points);
+      get_all_curves_and_points(tmp_points, curves, points);
+    }
+    else if((pt = dynamic_cast<Point*>(tb)))
+    {
+      points.append(pt);
+    }
+  }
+}
+
 // Function to apply/remove COMPOSITE_GEOM attributes as necessary based
 // on imprinting.
 void CompositeEngine::attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
                                                     DLIList<TopologyBridge*> &att_tbs,
-                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<TopologyBridge*> &tb_list,
                                                         DLIList<Body*> &old_bodies)
 {
-  DLIList<TopologyBridge*> old_bridges(old_bodies.size());
-  DLIList<TopologyBridge*> new_bridges(new_sms.size());
-  DLIList<TopologyBridge*> all_bodies;
-  CAST_LIST(new_sms, new_bridges, TopologyBridge);
-
-  all_bodies = new_bridges;
-  int k, m, q, w, g, b, s, t;
+  DLIList<TopologyBridge*> all_bridges = tb_list;
+  int i, j, k;
   for(k = old_bodies.size(); k>0; k--)
   {
     Body *body = old_bodies.get_and_step();
     TopologyBridge *tb = body->bridge_manager()->topology_bridge();
     if(tb)
-    {
-      old_bridges.append(tb);
-      all_bodies.append_unique(tb);
-    }
+      all_bridges.append_unique(tb);
   }
 
-  DLIList<DLIList<TopologyBridge*>*> lists_of_curves;
-  DLIList<DLIList<TopologyBridge*>*> lists_of_points;
+  DLIList<Curve*> all_curves;
+  DLIList<Point*> all_points;
+  get_all_curves_and_points(all_bridges, all_curves, all_points);
+  all_curves.uniquify_ordered();
+  all_points.uniquify_ordered();
 
-  // Get lists of curves and points for each body in the
-  // list all_bodies.
-  all_bodies.reset();
-  for(k=all_bodies.size(); k--;)
+  double geom_factor = GeometryQueryTool::get_geometry_factor();
+  double merge_tol = geom_factor*GEOMETRY_RESABS;
+
+  AbstractTree<Point*> *pt_tree = new RTree<Point*>(merge_tol);
+  AbstractTree<Curve*> *crv_tree = new RTree<Curve*>(merge_tol);
+
+  DLIList<Curve*> all_curves_with_composite_att;
+  DLIList<Point*> all_points_with_composite_att;
+  for(k=all_curves.size(); k>0; k--)
   {
-    DLIList<TopologyBridge*> *new_curve_list = new DLIList<TopologyBridge*>;
-    DLIList<TopologyBridge*> *new_point_list = new DLIList<TopologyBridge*>;
-    lists_of_curves.append(new_curve_list);
-    lists_of_points.append(new_point_list);
-    TopologyBridge *cur_body = all_bodies.get_and_step();
-    DLIList<TopologyBridge*> lumps;
-    cur_body->get_children_virt(lumps);
-    for(m=lumps.size(); m--;)
+    Curve *cur_curve = all_curves.get_and_step();
+    crv_tree->add(cur_curve);
+    DLIList<CubitSimpleAttrib*> list;
+    cur_curve->get_simple_attribute("COMPOSITE_GEOM",list);
+    if(list.size() > 0)
+      all_curves_with_composite_att.append(cur_curve);
+  }
+  for(k=all_points.size(); k>0; k--)
+  {
+    Point *cur_point = all_points.get_and_step();
+    pt_tree->add(cur_point);
+    DLIList<CubitSimpleAttrib*> list;
+    cur_point->get_simple_attribute("COMPOSITE_GEOM",list);
+    if(list.size() > 0)
+      all_points_with_composite_att.append(cur_point);
+  }
+
+  DLIList<CubitSimpleAttrib*> list;
+  while(all_points_with_composite_att.size())
+  {
+    DLIList<Point*> other_pts;
+    DLIList<BodySM*> other_bodies;
+    DLIList<double> other_distances;
+
+    // For the given pt we will look for "coincident" pts (those within merge tol)
+    // and categorize them as either having or not having a composite att.
+    Point *cur_pt = all_points_with_composite_att.extract();
+    pt_tree->remove(cur_pt);
+
+    BodySM *cur_body = cur_pt->bodysm();
+    DLIList<Point*> coincident_pts_with_composite_att, coincident_pts_without_composite_att;
+    DLIList<Point*> close_pts;
+    CubitBox bbox = cur_pt->bounding_box();
+    pt_tree->find(bbox, close_pts);
+
+    // Only keep the closest pt from each body.
+    for(j=close_pts.size(); j>0; j--)
     {
-      TopologyBridge *cur_lump = lumps.get_and_step();
-      DLIList<TopologyBridge*> shells;
-      cur_lump->get_children_virt(shells);
-      for(q=shells.size(); q--;)
+      Point *other_pt = close_pts.get_and_step();
+      BodySM *other_body = other_pt->bodysm();
+      // Don't keep anything that is in the same body as the current pt.
+      if(other_body != cur_body)
       {
-        TopologyBridge *cur_shell = shells.get_and_step();
-        DLIList<TopologyBridge*> surfaces;
-        cur_shell->get_children_virt(surfaces);
-        for(w=surfaces.size(); w--;)
+        double cur_dist_sq = cur_pt->coordinates().distance_between_squared(other_pt->coordinates());
+        if(other_bodies.move_to(other_body))
         {
-          TopologyBridge *cur_surface = surfaces.get_and_step();
-          DLIList<TopologyBridge*> loops;
-          cur_surface->get_children_virt(loops);
-          for(g=loops.size(); g--;)
+          int list_index = other_bodies.get_index();
+          other_distances.reset();
+          other_distances.step(list_index);
+          double prev_dist_sq = other_distances.get();
+          if(cur_dist_sq < prev_dist_sq)
           {
-            TopologyBridge *cur_loop = loops.get_and_step();
-            DLIList<TopologyBridge*> coedges;
-            cur_loop->get_children_virt(coedges);
-            for(b=coedges.size(); b--;)
+            other_distances.change_to(cur_dist_sq);
+            other_pts.reset();
+            other_pts.step(list_index);
+            other_pts.change_to(other_pt);
+          }
+        }
+        else
+        {
+          other_bodies.append(other_body);
+          other_pts.append(other_pt);
+          other_distances.append(cur_dist_sq);
+        }
+      }
+    }
+    // Make sure our current pt is added to a list.
+    coincident_pts_with_composite_att.append(cur_pt);
+    // Classify the coincident pts as either having or not
+    // having a composite att.
+    for(j=other_pts.size(); j>0; j--)
+    {
+      Point *pt = other_pts.get_and_step();
+      list.clean_out();
+      pt->get_simple_attribute("COMPOSITE_GEOM",list);
+      if(list.size() > 0)
+      {
+        coincident_pts_with_composite_att.append(pt);
+        if(all_points_with_composite_att.move_to(pt))
+          all_points_with_composite_att.extract();
+      }
+      else
+        coincident_pts_without_composite_att.append(pt);
+    }
+
+    // If we have found at least one other pt coincident with the current point...
+    if(coincident_pts_with_composite_att.size() > 1 ||
+      coincident_pts_without_composite_att.size() > 0)
+    {
+      // If there is at least one pt without a composite att that is an imprinter we
+      // will remove all composite atts from coincident pts
+      bool found = false;
+      for(j=coincident_pts_without_composite_att.size(); j>0 && !found; j--)
+      {
+        Point *tmp_pt = coincident_pts_without_composite_att.get_and_step();
+        list.clean_out();
+        tmp_pt->get_simple_attribute("IMPRINTER",list);
+        if(list.size() > 0)
+          found = true;
+      }
+      if(found)
+      {
+        // Remove all composite atts.
+        for(j=coincident_pts_with_composite_att.size(); j>0; j--)
+        {
+          Point *tmp_pt = coincident_pts_with_composite_att.get_and_step();
+          list.clean_out();
+          tmp_pt->get_simple_attribute("COMPOSITE_GEOM",list);
+          if(list.size() > 0)
+            tmp_pt->remove_simple_attribute_virt(list.get());
+        }
+      }
+      else
+      {
+        // There were no imprinter points that didn't have composite atts.  
+        // Next we will look for imprinter points with composite atts.  These
+        // may have resulted in a new point.  If there is a non composite att
+        // point that doesn't have an ORIGINAL att we will know it is new
+        // from the imprinter composite att point and we know to put a composite
+        // att on it.
+        found = false;
+        for(j=coincident_pts_with_composite_att.size(); j>0 && !found; j--)
+        {
+          Point *tmp_pt = coincident_pts_with_composite_att.get_and_step();
+          list.clean_out();
+          tmp_pt->get_simple_attribute("IMPRINTER",list);
+          if(list.size() > 0)
+            found = true;
+        }
+        if(found)
+        {
+          // Now put a composite att on any point that doesn't have one.
+          for(j=coincident_pts_without_composite_att.size(); j>0; j--)
+          {
+            Point *tmp_pt = coincident_pts_without_composite_att.get_and_step();
+            list.clean_out();
+            tmp_pt->get_simple_attribute("ORIGINAL", list);
+            if(list.size() == 0)
             {
-              TopologyBridge *cur_coedge = coedges.get_and_step();
-              DLIList<TopologyBridge*> curves;
-              cur_coedge->get_children_virt(curves);
-              for(s=curves.size(); s--;)
-              {
-                TopologyBridge *cur_curve = curves.get_and_step();
-                new_curve_list->append_unique(cur_curve);
-                DLIList<TopologyBridge*> pts;
-                cur_curve->get_children_virt(pts);
-                for(t=pts.size(); t--;)
-                {
-                  TopologyBridge *cur_pt = pts.get_and_step();
-                  new_point_list->append_unique(cur_pt);
-                }
-              }
+              // The point was not in the original model and therefore was created by 
+              // the imprint of a pt with a composite att.  We need to put a composite
+              // att on it.
+              list.clean_out();
+              coincident_pts_with_composite_att.get()->get_simple_attribute("COMPOSITE_GEOM",list);
+              tmp_pt->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
             }
           }
         }
       }
     }
+
+    for(i=coincident_pts_with_composite_att.size(); i>0; i--)
+    {
+      Point *pt = coincident_pts_with_composite_att.get_and_step();
+      list.clean_out();
+      pt->get_simple_attribute("IMPRINTER",list);
+      if(list.size() > 0)
+        pt->remove_simple_attribute_virt(list.get());
+      list.clean_out();
+      pt->get_simple_attribute("ORIGINAL",list);
+      if(list.size() > 0)
+        pt->remove_simple_attribute_virt(list.get());
+    }
+    for(i=coincident_pts_without_composite_att.size(); i>0; i--)
+    {
+      Point *pt = coincident_pts_without_composite_att.get_and_step();
+      list.clean_out();
+      pt->get_simple_attribute("IMPRINTER",list);
+      if(list.size() > 0)
+        pt->remove_simple_attribute_virt(list.get());
+      list.clean_out();
+      pt->get_simple_attribute("ORIGINAL",list);
+      if(list.size() > 0)
+        pt->remove_simple_attribute_virt(list.get());
+    }
   }
+  delete pt_tree;
 
-
-  int i, j, h;
   CubitSense rel_sense;
-  double geom_factor = GeometryQueryTool::get_geometry_factor();
+  while(all_curves_with_composite_att.size())
+  {
+    DLIList<Curve*> other_crvs;
+    DLIList<BodySM*> other_bodies;
+    DLIList<double> other_distances;
 
-  // This code will look at all of the topology bridges that have
-  // COMPOSITE_GEOM attributes on them and determine whether to 
-  // keep these attributes, remove them, or pass them on to bridges
-  // on other volumes based on the expected results from the imprinting operation.
+    Curve *cur_crv = all_curves_with_composite_att.extract();
+    crv_tree->remove(cur_crv);
 
-  // Loop twice, once for the curves and then once for the points.
-  for(h=0; h<2; h++)
-  {
-    for(i=att_tbs.size(); i--;)
+    BodySM *cur_body = cur_crv->bodysm();
+    DLIList<Curve*> coincident_crvs_with_composite_att, coincident_crvs_without_composite_att;
+    DLIList<Curve*> close_crvs;
+    CubitBox bbox = cur_crv->bounding_box();
+    crv_tree->find(bbox, close_crvs);
+
+    for(j=close_crvs.size(); j>0; j--)
     {
-      TopologyBridge *att_tb = att_tbs.get_and_step();
-      Curve *att_cur = dynamic_cast<Curve*>(att_tb);
-      Point *att_pt = dynamic_cast<Point*>(att_tb);
-      Curve *match_cur;
-      Point *match_pt;
-
-      // Force curves to be done first.
-      if(h==0 && att_cur)
+      Curve *other_crv = close_crvs.get_and_step();
+      BodySM *other_body = other_crv->bodysm();
+      // Only consider curves from other bodies.
+      if(cur_body != other_body)
       {
-        match_cur = NULL;
-        CubitBox att_box = att_cur->bounding_box();
-
-        // First check the list of new bridges as the corresponding
-        // curve will often be there.
-        for(j=new_tbs.size(); !match_cur && j; j--)
+        if(this->about_spatially_equal(cur_crv, other_crv, rel_sense, geom_factor, 0))
         {
-          TopologyBridge *new_tb = new_tbs.get_and_step();
-          Curve *new_cur = dynamic_cast<Curve*>(new_tb);
-          if(new_cur && new_cur != att_cur)
+          CubitVector pos1, pos2;
+          double cur_dist;
+          cur_crv->get_geometry_query_engine()->entity_entity_distance(
+            cur_crv, other_crv, pos1, pos2, cur_dist );
+          if(other_bodies.move_to(other_body))
           {
-            CubitBox new_box = new_cur->bounding_box();
-            if(att_box.overlap(GEOMETRY_RESABS, new_box))
+            int list_index = other_bodies.get_index();
+            other_distances.reset();
+            other_distances.step(list_index);
+            double prev_dist = other_distances.get();
+            if(cur_dist < prev_dist)
             {
-              if(this->about_spatially_equal(new_cur, att_cur, rel_sense, geom_factor, 0))
-              {
-                match_cur = new_cur;
-                process_curves_after_imprint(att_cur, new_cur, new_sms);
-              }
+              other_distances.change_to(cur_dist);
+              other_crvs.reset();
+              other_crvs.step(list_index);
+              other_crvs.change_to(other_crv);
             }
           }
-        }
-
-        // If we didn't find a matching curve in the new bridge list
-        // look at all of the rest of the curves.
-        if(!match_cur)
-        {
-          BodySM *att_body = att_cur->bodysm();
-          all_bodies.reset();
-          lists_of_curves.reset();
-          for(j=all_bodies.size(); !match_cur && j; j--)
+          else
           {
-            TopologyBridge *cur_body = all_bodies.get_and_step();
-            DLIList<TopologyBridge*> *curves = lists_of_curves.get_and_step();
-            BodySM *cur_bodysm = cur_body->bodysm();
-
-            // Don't look at curves from the same body.
-            if(att_body != cur_bodysm)
-            {
-              for(m=curves->size(); !match_cur && m; m--)
-              {
-                TopologyBridge *curtb = curves->get_and_step();
-                Curve *cur = dynamic_cast<Curve*>(curtb);
-                if(cur && cur != att_cur)
-                {
-                  CubitBox new_box = cur->bounding_box();
-                  if(att_box.overlap(GEOMETRY_RESABS, new_box))
-                  {
-                    if(this->about_spatially_equal(cur, att_cur, rel_sense, geom_factor, 0))
-                    {
-                      match_cur = cur;
-                      process_curves_after_imprint(att_cur, cur, new_sms);
-                    }
-                  }
-                }
-              }
-            }
+            other_bodies.append(other_body);
+            other_crvs.append(other_crv);
+            other_distances.append(cur_dist);
           }
         }
       }
+      coincident_crvs_with_composite_att.append(cur_crv);
+      for(j=other_crvs.size(); j>0; j--)
+      {
+        Curve *crv = other_crvs.get_and_step();
+        list.clean_out();
+        crv->get_simple_attribute("COMPOSITE_GEOM", list);
+        if(list.size() > 0)
+        {
+          coincident_crvs_with_composite_att.append(other_crv);
+          if(all_curves_with_composite_att.move_to(other_crv))
+            all_curves_with_composite_att.extract();
+        }
+        else
+          coincident_crvs_without_composite_att.append(other_crv);
+      }
+    }
 
-      // Force points to be done second.
-      else if(h==1 && att_pt)
+    // If we have found at least one other crv coincident with the current crv...
+    if(coincident_crvs_with_composite_att.size() > 1 ||
+      coincident_crvs_without_composite_att.size() > 0)
+    {
+      // If there is at least one curve without a composite att that is an imprinter we
+      // will remove all composite atts from coincident curves
+      bool found = false;
+      for(j=coincident_crvs_without_composite_att.size(); j>0 && !found; j--)
       {
-        match_pt = NULL;
-        CubitBox att_box = att_pt->bounding_box();
-
-        // First check the list of new bridges as the corresponding
-        // point will often be there.
-        for(j=new_tbs.size(); !match_pt && j; j--)
+        Curve *tmp_crv = coincident_crvs_without_composite_att.get_and_step();
+        list.clean_out();
+        tmp_crv->get_simple_attribute("IMPRINTER",list);
+        if(list.size() > 0)
+          found = true;
+      }
+      if(found)
+      {
+        // Remove all composite atts.
+        for(j=coincident_crvs_with_composite_att.size(); j>0; j--)
         {
-          TopologyBridge *new_tb = new_tbs.get_and_step();
-          Point *new_pt = dynamic_cast<Point*>(new_tb);
-          if(new_pt && new_pt != att_pt)
-          {
-            CubitBox new_box = new_pt->bounding_box();
-            if(att_box.overlap(GEOMETRY_RESABS, new_box))
-            {
-              if(GeometryQueryTool::instance()->about_spatially_equal(new_pt->coordinates(), 
-                                    att_pt->coordinates(), geom_factor))
-              {
-                match_pt = new_pt;
-                process_points_after_imprint(att_pt, new_pt, new_sms);
-              }
-            }
-          }
+          Curve *tmp_crv = coincident_crvs_with_composite_att.get_and_step();
+          list.clean_out();
+          tmp_crv->get_simple_attribute("COMPOSITE_GEOM",list);
+          if(list.size() > 0)
+            tmp_crv->remove_simple_attribute_virt(list.get());
         }
-        // If we didn't find a matching point in the new bridge list
-        // look at all of the rest of the points.
-        if(!match_pt)
+      }
+      else
+      {
+        // There were no imprinter crvs that didn't have composite atts.  
+        // Next we will look for imprinter crvs with composite atts.  These
+        // may have resulted in a new crv.  If there is a non composite att
+        // crv that doesn't have an ORIGINAL att we will know it is new
+        // from the imprinter composite att crv and we know to put a composite
+        // att on it.
+        found = false;
+        for(j=coincident_crvs_with_composite_att.size(); j>0 && !found; j--)
         {
-          BodySM *att_body = att_pt->bodysm();
-          all_bodies.reset();
-          lists_of_points.reset();
-          for(j=all_bodies.size(); !match_pt && j; j--)
+          Curve *tmp_crv = coincident_crvs_with_composite_att.get_and_step();
+          list.clean_out();
+          tmp_crv->get_simple_attribute("IMPRINTER",list);
+          if(list.size() > 0)
+            found = true;
+        }
+        if(found)
+        {
+          // Now put a composite att on any crv that doesn't have one.
+          for(j=coincident_crvs_without_composite_att.size(); j>0; j--)
           {
-            TopologyBridge *cur_body = all_bodies.get_and_step();
-            DLIList<TopologyBridge*> *points = lists_of_points.get_and_step();
-            BodySM *cur_bodysm = cur_body->bodysm();
-            
-            // Don't look at points from the same body.
-            if(att_body != cur_bodysm)
+            Curve *tmp_crv = coincident_crvs_without_composite_att.get_and_step();
+            list.clean_out();
+            tmp_crv->get_simple_attribute("ORIGINAL", list);
+            if(list.size() == 0)
             {
-              for(m=points->size(); !match_pt && m; m--)
-              {
-                TopologyBridge *curtb = points->get_and_step();
-                Point *pt = dynamic_cast<Point*>(curtb);
-                if(pt && pt != att_pt)
-                {
-                  CubitBox new_box = pt->bounding_box();
-                  if(att_box.overlap(GEOMETRY_RESABS, new_box))
-                  {
-                    if(GeometryQueryTool::instance()->about_spatially_equal(pt->coordinates(), 
-                                          att_pt->coordinates(), geom_factor))
-                    {
-                      match_pt = pt;
-                      process_points_after_imprint(att_pt, pt, new_sms);
-                    }
-                  }
-                }
-              }
+              // The crv was not in the original model and therefore was created by 
+              // the imprint of a crv with a composite att.  We need to put a composite
+              // att on it.
+              list.clean_out();
+              coincident_crvs_with_composite_att.get()->get_simple_attribute("COMPOSITE_GEOM",list);
+              tmp_crv->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
             }
           }
         }
       }
     }
+
+    for(i=coincident_crvs_with_composite_att.size(); i>0; i--)
+    {
+      Curve *crv = coincident_crvs_with_composite_att.get_and_step();
+      list.clean_out();
+      crv->get_simple_attribute("IMPRINTER",list);
+      if(list.size() > 0)
+        crv->remove_simple_attribute_virt(list.get());
+      list.clean_out();
+      crv->get_simple_attribute("ORIGINAL",list);
+      if(list.size() > 0)
+        crv->remove_simple_attribute_virt(list.get());
+    }
+    for(i=coincident_crvs_without_composite_att.size(); i>0; i--)
+    {
+      Curve *crv = coincident_crvs_without_composite_att.get_and_step();
+      list.clean_out();
+      crv->get_simple_attribute("IMPRINTER",list);
+      if(list.size() > 0)
+        crv->remove_simple_attribute_virt(list.get());
+      list.clean_out();
+      crv->get_simple_attribute("ORIGINAL",list);
+      if(list.size() > 0)
+        crv->remove_simple_attribute_virt(list.get());
+    }
   }
+  delete crv_tree;
+  for(i=all_curves.size(); i>0; i--)
+  {
+    Curve *cur_curve = all_curves.get_and_step();
+    list.clean_out();
+    cur_curve->get_simple_attribute("IMPRINTER",list);
+    if(list.size() > 0)
+      cur_curve->remove_simple_attribute_virt(list.get());
+    list.clean_out();
+    cur_curve->get_simple_attribute("ORIGINAL",list);
+    if(list.size() > 0)
+      cur_curve->remove_simple_attribute_virt(list.get());
+  }
+  for(i=all_points.size(); i>0; i--)
+  {
+    Point *cur_point = all_points.get_and_step();
+    list.clean_out();
+    cur_point->get_simple_attribute("IMPRINTER",list);
+    if(list.size() > 0)
+      cur_point->remove_simple_attribute_virt(list.get());
+    list.clean_out();
+    cur_point->get_simple_attribute("ORIGINAL",list);
+    if(list.size() > 0)
+      cur_point->remove_simple_attribute_virt(list.get());
+  }
 }
 
 void CompositeEngine::process_curves_after_imprint(Curve *att_cur, 
@@ -423,53 +720,67 @@
 {
   DLIList<CubitSimpleAttrib*> list;
 
-  other_cur->get_simple_attribute("IMPRINT_PREEXISTING",list);
-  if(list.size() == 0)
+  if(att_cur == other_cur)
   {
-    // This is a new bridge created by imprinting this hidden bridge.  In 
-    // this case we need to add a COMPOSITE_GEOM attribute to the new bridge
-    // so we don't see a resulting imprinted bridge from the hidden bridge.
-    list.clean_out();
+    // This case will happen when we have manually added one of the existing
+    // curves on the surface to be imprinted to the "new_ENTITIES" list.  We
+    // do this in cases where the curve to imprint on the surface exactly 
+    // falls on one of the existing curves.  In this case the ACIS face 
+    // doesn't get new curves created but we need to consider the 
+    // curve on the face as new because it may have been hidden in a 
+    // composite surface and needs to be reintroduced.  So, in this
+    // case we will remove the attribute so that the curve is no longer
+    // hidden.
     att_cur->get_simple_attribute("COMPOSITE_GEOM",list);
-    other_cur->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
+    att_cur->remove_simple_attribute_virt(list.get());
   }
   else
   {
-    // This bridge existed before the imprint operation.  Therefore it
-    // could also have a COMPOSITE_GEOM attribute on it.  Check this.
-    list.clean_out();
-    other_cur->get_simple_attribute("COMPOSITE_GEOM",list);
+    other_cur->get_simple_attribute("IMPRINT_PREEXISTING",list);
     if(list.size() == 0)
     {
-      // It doesn't have a COMPOSITE_GEOM attribute so we need to remove
-      // the COMPOSITE_GEOM from att_bridge because the hidden nature gets
-      // wiped out by the imprinting process.
+      // This is a new bridge created by imprinting this hidden bridge.  In 
+      // this case we need to add a COMPOSITE_GEOM attribute to the new bridge
+      // so we don't see a resulting imprinted bridge from the hidden bridge.
+      list.clean_out();
       att_cur->get_simple_attribute("COMPOSITE_GEOM",list);
-      att_cur->remove_simple_attribute_virt(list.get());
-      BodySM *bsm = att_cur->bodysm();
-      if(bsm)
-        new_sms.append_unique(bsm);
-      TBOwner *bridge_owner = att_cur->owner();
-      CompositeCurve *cc_bridge_owner = dynamic_cast<CompositeCurve*>(bridge_owner);
-      if(cc_bridge_owner)
+      other_cur->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
+    }
+    else
+    {
+      // This bridge existed before the imprint operation.  Therefore it
+      // could also have a COMPOSITE_GEOM attribute on it.  Check this.
+      list.clean_out();
+      other_cur->get_simple_attribute("COMPOSITE_GEOM",list);
+      if(list.size() == 0)
       {
-        TBOwner *cc_owner = cc_bridge_owner->owner();
-        HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cc_owner);
-        if(hes)
+        // It doesn't have a COMPOSITE_GEOM attribute so we need to remove
+        // the COMPOSITE_GEOM from att_bridge because the hidden nature gets
+        // wiped out by the imprinting process.
+        att_cur->get_simple_attribute("COMPOSITE_GEOM",list);
+        att_cur->remove_simple_attribute_virt(list.get());
+        TBOwner *bridge_owner = att_cur->owner();
+        CompositeCurve *cc_bridge_owner = dynamic_cast<CompositeCurve*>(bridge_owner);
+        if(cc_bridge_owner)
         {
-          CompositeSurface *cs = dynamic_cast<CompositeSurface*>(hes->owner());
-          if(cs)
-            cs->HadBridgeRemoved = 1;
-            // This is currently how we are notifying the owning CompositeSurface
-            // that it needs to be deactivated and rebuilt.  It really has 
-            // nothing to do with the bridge being removed though.  Bad.
+          TBOwner *cc_owner = cc_bridge_owner->owner();
+          HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cc_owner);
+          if(hes)
+          {
+            CompositeSurface *cs = dynamic_cast<CompositeSurface*>(hes->owner());
+            if(cs)
+              cs->HadBridgeRemoved = 1;
+              // This is currently how we are notifying the owning CompositeSurface
+              // that it needs to be deactivated and rebuilt.  It really has 
+              // nothing to do with the bridge being removed though.  Bad.
+          }
         }
       }
+      else
+      {
+        // This bridge was also hidden so do nothing.
+      }
     }
-    else
-    {
-      // This bridge was also hidden so do nothing.
-    }
   }
 }
 
@@ -480,92 +791,103 @@
   int i;
   DLIList<CubitSimpleAttrib*> list;
 
-  other_pt->get_simple_attribute("IMPRINT_PREEXISTING",list);
-  if(list.size() == 0)
+  if(att_pt == other_pt)
   {
-    // This is a new bridge created by imprinting this hidden bridge.  In 
-    // this case we need to add a COMPOSITE_GEOM attribute to the new bridge
-    // if possible so we don't see a resulting imprinted bridge from the hidden bridge.
-    int num_visible_curves = 0;
-    DLIList<TopologyBridge*> curves;
-    att_pt->get_parents_virt(curves);
-    for(i=curves.size(); i--;)
+    // This case will happen when we have manually added one of the existing
+    // pts on the surface to be imprinted to the "new_ENTITIES" list.  We
+    // do this in cases where the pt to imprint on the surface exactly 
+    // falls on one of the existing pts.  In this case the ACIS face 
+    // doesn't get new pts created but we need to consider the 
+    // pt on the face as new because it may have been hidden in a 
+    // composite curve and needs to be reintroduced.  So, in this
+    // case we will remove the attribute so that the pt is no longer
+    // hidden.
+    att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
+    att_pt->remove_simple_attribute_virt(list.get());
+  }
+  else
+  {
+    other_pt->get_simple_attribute("IMPRINT_PREEXISTING",list);
+    if(list.size() == 0)
     {
-      list.clean_out();
-      TopologyBridge *c = curves.get_and_step();
-      c->get_simple_attribute("COMPOSITE_GEOM", list);
-      if(list.size() == 0)
-        num_visible_curves++;
-    }
-    if(num_visible_curves > 2)
-    {
-      list.clean_out();
-      att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
-      att_pt->remove_simple_attribute_virt(list.get());
-      BodySM *bsm = att_pt->bodysm();
-      if(bsm)
-        new_sms.append_unique(bsm);
-      TBOwner *bridge_owner = att_pt->owner();
-      CompositePoint *cp_bridge_owner = dynamic_cast<CompositePoint*>(bridge_owner);
-      if(cp_bridge_owner)
+      // This is a new bridge created by imprinting this hidden bridge.  In 
+      // this case we need to add a COMPOSITE_GEOM attribute to the new bridge
+      // if possible so we don't see a resulting imprinted bridge from the hidden bridge.
+      int num_visible_curves = 0;
+      DLIList<TopologyBridge*> curves;
+      att_pt->get_parents_virt(curves);
+      for(i=curves.size(); i--;)
       {
-        TBOwner *cp_owner = cp_bridge_owner->owner();
-        HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cp_owner);
-        if(hes)
+        list.clean_out();
+        TopologyBridge *c = curves.get_and_step();
+        c->get_simple_attribute("COMPOSITE_GEOM", list);
+        if(list.size() == 0)
+          num_visible_curves++;
+      }
+      if(num_visible_curves > 2)
+      {
+        list.clean_out();
+        att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
+        att_pt->remove_simple_attribute_virt(list.get());
+        TBOwner *bridge_owner = att_pt->owner();
+        CompositePoint *cp_bridge_owner = dynamic_cast<CompositePoint*>(bridge_owner);
+        if(cp_bridge_owner)
         {
-          CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
-          if(cc)
-            cc->HadBridgeRemoved = 1;
-            // This is currently how we are notifying the owning CompositeCurve
-            // that it needs to be deactivated and rebuilt.  It really has 
-            // nothing to do with the bridge being removed though.  Bad.
+          TBOwner *cp_owner = cp_bridge_owner->owner();
+          HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cp_owner);
+          if(hes)
+          {
+            CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
+            if(cc)
+              cc->HadBridgeRemoved = 1;
+              // This is currently how we are notifying the owning CompositeCurve
+              // that it needs to be deactivated and rebuilt.  It really has 
+              // nothing to do with the bridge being removed though.  Bad.
+          }
         }
       }
+      else
+      {
+        list.clean_out();
+        att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
+        other_pt->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
+      }
     }
     else
     {
+      // This bridge existed before the imprint operation.  Therefore it
+      // could also have a COMPOSITE_GEOM attribute on it.  Check this.
       list.clean_out();
-      att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
-      other_pt->append_simple_attribute_virt(new CubitSimpleAttrib(list.get()));
-    }
-  }
-  else
-  {
-    // This bridge existed before the imprint operation.  Therefore it
-    // could also have a COMPOSITE_GEOM attribute on it.  Check this.
-    list.clean_out();
-    other_pt->get_simple_attribute("COMPOSITE_GEOM",list);
-    if(list.size() == 0)
-    {
-      // It doesn't have a COMPOSITE_GEOM attribute so we need to remove
-      // the COMPOSITE_GEOM from att_bridge because the hidden nature gets
-      // wiped out by the imprinting process.
-      att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
-      att_pt->remove_simple_attribute_virt(list.get());
-      BodySM *bsm = att_pt->bodysm();
-      if(bsm)
-        new_sms.append_unique(bsm);
-      TBOwner *bridge_owner = att_pt->owner();
-      CompositePoint *cp_bridge_owner = dynamic_cast<CompositePoint*>(bridge_owner);
-      if(cp_bridge_owner)
+      other_pt->get_simple_attribute("COMPOSITE_GEOM",list);
+      if(list.size() == 0)
       {
-        TBOwner *cp_owner = cp_bridge_owner->owner();
-        HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cp_owner);
-        if(hes)
+        // It doesn't have a COMPOSITE_GEOM attribute so we need to remove
+        // the COMPOSITE_GEOM from att_bridge because the hidden nature gets
+        // wiped out by the imprinting process.
+        att_pt->get_simple_attribute("COMPOSITE_GEOM",list);
+        att_pt->remove_simple_attribute_virt(list.get());
+        TBOwner *bridge_owner = att_pt->owner();
+        CompositePoint *cp_bridge_owner = dynamic_cast<CompositePoint*>(bridge_owner);
+        if(cp_bridge_owner)
         {
-          CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
-          if(cc)
-            cc->HadBridgeRemoved = 1;
-            // This is currently how we are notifying the owning CompositeCurve
-            // that it needs to be deactivated and rebuilt.  It really has 
-            // nothing to do with the bridge being removed though.  Bad.
+          TBOwner *cp_owner = cp_bridge_owner->owner();
+          HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(cp_owner);
+          if(hes)
+          {
+            CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
+            if(cc)
+              cc->HadBridgeRemoved = 1;
+              // This is currently how we are notifying the owning CompositeCurve
+              // that it needs to be deactivated and rebuilt.  It really has 
+              // nothing to do with the bridge being removed though.  Bad.
+          }
         }
       }
+      else
+      {
+        // This bridge was also hidden so do nothing.
+      }
     }
-    else
-    {
-      // This bridge was also hidden so do nothing.
-    }
   }
 }
 
@@ -678,12 +1000,13 @@
 // been modified and if so will deactivate them so that they can be 
 // rebuilt later using the COMPOSITE_GEOM attributes on the underlying
 // solid model topology.
-void CompositeEngine::remove_modified(DLIList<TopologyBridge*>& geometry_list)
+void CompositeEngine::remove_modified(DLIList<Surface*> &surfaces,  
+                                      DLIList<Curve*> &curves, 
+                                      DLIList<Point*> &points)
 {
   clean_out_deactivated_geometry();
 
   int i, j, k, m, n, w;
-  int deactivate;
   int something_changed = 1;
   DLIList<Point*> already_deactivated_points;
   DLIList<Curve*> already_deactivated_curves;
@@ -693,574 +1016,207 @@
   {
     something_changed = 0;
 
-    for (i=geometry_list.size(); i--; )
+    DLIList<Point*> deactivated_points;
+    DLIList<Curve*> deactivated_curves;
+    DLIList<Surface*> deactivated_surfs;
+
+    // Look for composite points that are out of date.
+    for(w=points.size(); w--;)
     {
-      // This code will first look for portions of the left over virtual
-      // topology layer that need to be blown away (deactivated).  It
-      // will put its findings in lists.  Then it will loop through
-      // and actualy deactivate everything.
-      TopologyBridge* geom_bridge = geometry_list.get_and_step();
+      CompositePoint *p = dynamic_cast<CompositePoint*>(points.get_and_step());
+      if(p && !already_deactivated_points.is_in_list(p))
+        deactivated_points.append(p);
+    }
+    deactivated_points.uniquify_ordered();
 
-      DLIList<Surface*> surfaces;
-      DLIList<Curve*> curves;
-      DLIList<Point*> points;
-      DLIList<Point*> deactivated_points;
-      DLIList<Curve*> deactivated_curves;
-      DLIList<Surface*> deactivated_surfs;
+    // Look for composite curves that are out of date.
+    for(w=curves.size(); w--;)
+    {
+      Curve *current_curve = curves.get_and_step();
+      CompositeCurve *cur = dynamic_cast<CompositeCurve*>(current_curve);
+      if(cur && !already_deactivated_curves.is_in_list(cur))
+        deactivated_curves.append(cur);
+    }
+    deactivated_curves.uniquify_ordered();
 
-      geom_bridge->surfaces(surfaces);
-      geom_bridge->curves(curves);
-      geom_bridge->points(points);
+    // Look for composite surfaces that are out of date.
+    for(w=surfaces.size(); w--;)
+    {
+      CompositeSurface* csurf = dynamic_cast<CompositeSurface*> (surfaces.get_and_step());
+      if (csurf && !already_deactivated_surfs.is_in_list(csurf))
+        deactivated_surfs.append(csurf);
+    }
+    deactivated_surfs.uniquify_ordered();
 
-      // Look for composite points that are out of date.
-      while(points.size())
-      {
-        CompositePoint *p = dynamic_cast<CompositePoint*>(points.pop());
-        if(p && !already_deactivated_points.is_in_list(p))
-        {
-          Point *real_point = p->get_point();
+    already_deactivated_points += deactivated_points;
+    already_deactivated_curves += deactivated_curves;
+    already_deactivated_surfs += deactivated_surfs;
 
-          deactivate = 0;
+    something_changed += deactivated_surfs.size() + deactivated_curves.size() +
+      deactivated_points.size();
 
-          if(p->HadBridgeRemoved)
-            deactivate = 1;
+    // Now actually deactivate the out of date composite surfs.
+    for(j=deactivated_surfs.size(); j--;)
+    {
+      CompositeSurface *csurf = dynamic_cast<CompositeSurface*>(deactivated_surfs.get_and_step());
 
-          // Check the curve attached to this point and make sure the
-          // virtual layer still matches the solid model layer.
-          if(!deactivate)
-          {
-            // Get the curves at this point using the virtual layer.
-            DLIList<Curve*> curves_referenced_by_virtual;
-            DLIList<Curve*> crvs;
-            p->curves(crvs);
-            for(j=crvs.size(); j--;)
-            {
-              Curve *c = crvs.get_and_step();
-              CompositeCurve *cc = dynamic_cast<CompositeCurve*>(c);
-              if(cc)
-              {
-                int num_curves = cc->num_curves();
-                for(k=0; k<num_curves; ++k)
-                {
-                  Curve *cur_c = cc->get_curve(k);
-                  DLIList<TopologyBridge*> pts;
-                  cur_c->get_children(pts, false, 0);
-                  if(pts.is_in_list(real_point))
-                    curves_referenced_by_virtual.append_unique(cur_c);
-                }
-              }
-              else
-                curves_referenced_by_virtual.append_unique(c);
-            }
+      // We have to also deactivate the boundary curves.  When we deactivate
+      // the CompositeSurface it removes all of the CompositeCoEdges associated
+      // with it.  However, it doesn't deactivate the composite curves associated
+      // with the composite coedges.  Therefore you can end up with a regular
+      // CoEdge pointing to a CompositeCurve and if the CompositeCurve has more
+      // than 1 curve in it later calls to replace_surface (which will in turn
+      // call replace_curve) will fail.
+      DLIList<Curve*> boundary_curves;
+      csurf->curves(boundary_curves);
+      for (k=boundary_curves.size(); k--; )
+      {
+        CompositeCurve* c = dynamic_cast<CompositeCurve*>(boundary_curves.get_and_step());
+        assert(NULL != c);
+        deactivated_curves.append_unique(c);
+        already_deactivated_curves.append_unique(c);
 
-            // Get the curves refernced by the solid model layer.
-            DLIList<Curve*> curves_referenced_by_solid_model_layer;
-            DLIList<TopologyBridge*> sm_crvs;
-            real_point->get_parents_virt(sm_crvs);
-            CAST_LIST(sm_crvs, curves_referenced_by_solid_model_layer, Curve);
+        DLIList<Point*> boundary_pts;
+        c->points(boundary_pts);
+        for (int e=boundary_pts.size(); e--; )
+        {
+          CompositePoint* p = dynamic_cast<CompositePoint*>(boundary_pts.get_and_step());
+          deactivated_points.append_unique(p);
+          already_deactivated_points.append_unique(p);
+          notify_deactivated(p);
+        }
 
-            // Now check to make sure all of the curves referenced from the virtual
-            // layer show up in the ones referenced by the solid model layer.  If
-            // they don't we know something has been modified and this CompositePoint
-            // is no longer valid.
-            for(j=curves_referenced_by_virtual.size(); j && !deactivate; j--)
-            {
-              Curve *c = curves_referenced_by_virtual.get_and_step();
-              if(!curves_referenced_by_solid_model_layer.is_in_list(c))
-                deactivate = 1;
-            }
-          }
-
-          if(deactivate)
-            deactivated_points.append_unique(p);
-        }
+        notify_deactivated(c);
       }
 
-      // Look for composite curves that are out of date.
-      for(w=curves.size(); w--;)
+      notify_deactivated(csurf);
+
+      DLIList<Curve*> hidden;
+      csurf->get_hidden_curves(hidden);
+      for (k=hidden.size(); k--; )
       {
-        Curve *current_curve = curves.get_and_step();
-        CompositeCurve *cur = dynamic_cast<CompositeCurve*>(current_curve);
-        if(cur && !already_deactivated_curves.is_in_list(cur))
-        {
-          deactivate = 0;
+        CompositeCurve* hcurve = dynamic_cast<CompositeCurve*>(hidden.pop());
+        assert(NULL != hcurve);
 
-          if(cur->HadBridgeRemoved)
-            deactivate = 1;
+        deactivated_curves.append_unique(hcurve);
+        already_deactivated_curves.append_unique(hcurve);
+        notify_deactivated(hcurve);
 
-          // Deactivate this curve if any of its points have been 
-          // deactivated.
-          if(!deactivate)
+        if(hcurve->num_curves() == 1)
+        {
+          Curve *c = hcurve->get_curve(0);
+          DLIList<TopologyBridge*> end_pts;
+          c->get_children(end_pts, false, 0);
+          for(m=end_pts.size(); m--;)
           {
-            DLIList<Point*> hidden_pts;
-            DLIList<Point*> boundary_pts;
-
-            cur->get_hidden_points(hidden_pts);
-            for(j=hidden_pts.size(); j && !deactivate; j--)
+            Point *cur_p = dynamic_cast<Point*>(end_pts.get_and_step());
+            if(cur_p)
             {
-              Point *pt = hidden_pts.get_and_step();
-              if(deactivated_points.is_in_list(pt))
-                deactivate = 1;
-            }
-
-            cur->points(boundary_pts);
-            for(j=boundary_pts.size(); j && !deactivate; j--)
-            {
-              Point *pt = boundary_pts.get_and_step();
-              if(deactivated_points.is_in_list(pt))
-                deactivate = 1;
-            }
-          }
-
-          // Deactivate this curve if the coedges stored at the
-          // virtual layer are out of sync with the solid model layer.
-          if(!deactivate)
-          {
-            // Get all of the coedges seen from the virtual layer.
-            DLIList<CoEdgeSM*> virt_coedges;
-            DLIList<TopologyBridge*> coedge_list;
-            cur->get_parents(coedge_list);
-            for(j=coedge_list.size(); j--;)
-            {
-              CoEdgeSM *csm = dynamic_cast<CoEdgeSM*>(coedge_list.get_and_step());
-              if(csm)
+              CompositePoint* cp = dynamic_cast<CompositePoint*>(cur_p->owner());
+              if(cp)
+                cur_p = (Point*)cp;
+              TBOwner *own = cur_p->owner();
+              HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(own);
+              if(hes)
               {
-                CompositeCoEdge *cce = dynamic_cast<CompositeCoEdge*>(csm);
-                if(cce)
+                CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
+                if(cc)
                 {
-                  int num_coedges = cce->num_coedges();
-                  for(k=0; k<num_coedges; k++)
+                  deactivated_curves.append_unique(cc);
+                  already_deactivated_curves.append_unique(cc);
+                  notify_deactivated(cc);
+
+                  DLIList<Point*> hidden_pts;
+                  cc->get_hidden_points(hidden_pts);
+                  for (n=hidden_pts.size(); n--; )
                   {
-                    CoEdgeSM *cur_coedge = cce->get_coedge(k);
-                    virt_coedges.append_unique(cur_coedge);
+                    CompositePoint *hpoint = dynamic_cast<CompositePoint*>(hidden_pts.pop());
+                    assert(NULL != hpoint);
+                    deactivated_points.append_unique(hpoint);
+                    already_deactivated_points.append_unique(hpoint);
+                    notify_deactivated(hpoint);
                   }
                 }
-                else
-                  virt_coedges.append_unique(csm);
               }
             }
-
-            // Get all of the coedges seen from the solid model layer.
-            DLIList<CoEdgeSM*> real_coedges;
-            int num_curves = cur->num_curves();
-            for(j=0; j<num_curves; j++)
-            {
-              Curve *cur_c = cur->get_curve(j);
-              DLIList<TopologyBridge*> tb_list;
-              cur_c->get_parents_virt(tb_list);
-              for(k=tb_list.size(); k--;)
-              {
-                CoEdgeSM *cur_ce = dynamic_cast<CoEdgeSM*>(tb_list.get_and_step());
-                if(cur_ce)
-                  real_coedges.append_unique(cur_ce);
-              }
-            }
-
-            // Now make sure all of the coedges seen from the virtual layer actually
-            // still exist in the solid model layer.
-            for(j=virt_coedges.size(); j && !deactivate; j--)
-            {
-              if(!real_coedges.is_in_list(virt_coedges.get_and_step()))
-                deactivate = 1;
-            }
           }
-
-          // Deactivate this curve if any of the points seen from the virtual
-          // layer are out of date.
-          if(!deactivate)
-          {
-            DLIList<Point*> points_referenced_by_virtual;
-            DLIList<Point*> points_referenced_by_solid_model_layer;
-
-            // Get all of the hidden points in virtual layer.
-            DLIList<Point*> hidden_pts;
-            cur->get_hidden_points(hidden_pts);
-            for(j=hidden_pts.size(); j--;)
-            {
-              Point *cur_point = hidden_pts.get_and_step();
-              CompositePoint *cur_cpoint = dynamic_cast<CompositePoint*>(cur_point);
-              if(cur_cpoint)
-                cur_point = cur_cpoint->get_point();
-              points_referenced_by_virtual.append_unique(cur_point);
-            }
-
-            // Get the end points in virtual layer.
-            DLIList<Point*> end_pts;
-            cur->points(end_pts);
-            for(j=end_pts.size(); j--;)
-            {
-              Point *cur_point = end_pts.get_and_step();
-              CompositePoint *cur_cpoint = dynamic_cast<CompositePoint*>(cur_point);
-              if(cur_cpoint)
-                cur_point = cur_cpoint->get_point();
-              points_referenced_by_virtual.append_unique(cur_point);
-            }
-            
-            // Get the points of all of the curves from the solid model layer.
-            int num_curves = cur->num_curves();
-            for(j=0; j<num_curves; ++j)
-            {
-              DLIList<TopologyBridge*> pts;
-              Curve *c = cur->get_curve(j);
-              c->get_children(pts, false, 0);
-              for(k=pts.size(); k--;)
-                points_referenced_by_solid_model_layer.
-                        append_unique(dynamic_cast<Point*>(pts.get_and_step()));
-            }
-
-            // Now that we have gathered all of the info we can check to make sure
-            // that all of the points in the virtual layer actually exist in the
-            // solid model layer.
-            for(j=points_referenced_by_virtual.size(); j && !deactivate; j--)
-            {
-              Point *cur_point = points_referenced_by_virtual.get_and_step();
-              if(!points_referenced_by_solid_model_layer.is_in_list(cur_point))
-                deactivate = 1;
-            }
-          }
-
-          // Check to see if there is a hidden entity that doesn't have a 
-          // COMPOSITE_GEOM attribute.  This can happen if the geometry 
-          // modification operation cut the body right through a hidden 
-          // entity without splitting it.  In this case a merge_owner event
-          // gets triggered and the COMPOSITE_GEOM attribute gets removed
-          // from the hidden entity.  In this case we want to remove the
-          // composite.
-          if(!deactivate)
-          {
-            DLIList<Point*> hidden_points;
-            cur->get_hidden_points(hidden_points);
-            for(j=hidden_points.size(); j>0 && !deactivate; j--)
-            {
-              DLIList<CubitSimpleAttrib*> att_list;
-              hidden_points.get_and_step()->get_simple_attribute("COMPOSITE_GEOM", att_list);
-              if(att_list.size() == 0)
-                deactivate = 1;
-            }
-          }
-
-          // This block checks to see if any of the hidden points in 
-          // a composite curve are the endpoints of an actual curve of
-          // the passed in geometry list.  This can happen if the hidden
-          // curve of a composite surface was cut by a real operation and
-          // an end point of the original hidden curve was a hidden point
-          // in a composite curve.  In this case we want to deactivate the
-          // composite curve.  If the composite curve is still valid it will 
-          // get reconstructed by the composite attributes later. 
-          if(!deactivate)
-          {
-            DLIList<Point*> hidden;
-            cur->get_hidden_points(hidden);
-            for (j=hidden.size(); j && !deactivate; j--)
-            {
-              Point *pt = hidden.pop();
-              DLIList<TopologyBridge*> point_curves;
-              pt->get_parents_virt(point_curves);
-              for(k=point_curves.size(); k && !deactivate; k--)
-              {
-                Curve *c = dynamic_cast<Curve*>(point_curves.get_and_step());
-                if(c && c != current_curve && curves.is_in_list(c))
-                  deactivate = 1;
-              }
-            }
-          }
-
-          // Check to see if the existing CompositeCurve end points match the
-          // underlying geometry end points.  In some geometry modification
-          // operations I found that a curve can be modified in place so that 
-          // the underlying entity was changed but owner attribute wasn't blown
-          // away.  As a result you end up with the same toplogy bridge which can
-          // be out of date.  The case I saw was where the Point in the CompositePoint
-          // at one of the ends of the CompositeCurve was out of date and didn't
-          // match the new Point that was created during the geometry modification.
-          if(!deactivate)
-          {
-            // Not quite sure how to handle multiple curve cases yet so we
-            // will do our best for now.
-            if(cur->num_curves() == 1)
-            {
-              DLIList<TopologyBridge*> underlying_points;
-              cur->get_curve(0)->get_children_virt(underlying_points);
-              if(underlying_points.size() == 2)
-              {
-                Point *p1 = dynamic_cast<Point*>(underlying_points.get_and_step());
-                Point *p2 = dynamic_cast<Point*>(underlying_points.get());
-
-                CompositePoint *cp1 = cur->start_point();
-                CompositePoint *cp2 = cur->end_point();
-
-                if(!cp1 || !cp2)
-                  deactivate = 1;
-                else
-                {
-                  Point *cpp1 = cp1->get_point();
-                  Point *cpp2 = cp2->get_point();
-                  if((p1 != cpp1 && p2 != cpp1) || (p1 != cpp2 && p2 != cpp2))
-                    deactivate = 1;
-                }
-              }
-            }
-          }
-
-          if(deactivate)
-            deactivated_curves.append_unique(cur);
-
         }
       }
+    }
 
-      // Look for composite surfaces that are out of date.
-      while (surfaces.size())
+    // Now actually deactivate the out of date composite curves.
+    for(j=deactivated_curves.size(); j--;)
+    {
+      CompositeCurve *ccurve = dynamic_cast<CompositeCurve*>(deactivated_curves.get_and_step());
+
+      DLIList<Point*> boundary_pts;
+      ccurve->points(boundary_pts);
+      for (k=boundary_pts.size(); k--; )
       {
-        CompositeSurface* csurf = dynamic_cast<CompositeSurface*> (surfaces.pop());
-        if (csurf && !already_deactivated_surfs.is_in_list(csurf))
-        {
-          deactivate = 0;
+        CompositePoint* p = dynamic_cast<CompositePoint*>(boundary_pts.get_and_step());
+        deactivated_points.append_unique(p);
+        already_deactivated_points.append_unique(p);
+        notify_deactivated(p);
+      }
 
-          // If one of the surfaces was removed from the compGeom list we
-          // suspect this composite surface was modified so we need to remove it.
-          if(csurf->HadBridgeRemoved)
-            deactivate = 1;
+      notify_deactivated(ccurve);
 
-          // Deactivate this surface if any of its curves were deactivated.
-          if(!deactivate)
-          {
-            DLIList<Curve*> hidden_curves;
-            DLIList<Curve*> boundary_curves;
-
-            csurf->get_hidden_curves(hidden_curves);
-            for(j=hidden_curves.size(); j && !deactivate; j--)
-            {
-              Curve *curve = hidden_curves.get_and_step();
-              if(deactivated_curves.is_in_list(curve))
-                deactivate = 1;
-            }
-
-            csurf->curves(boundary_curves);
-            for(j=boundary_curves.size(); j && !deactivate; j--)
-            {
-              Curve *curve = boundary_curves.get_and_step();
-              if(deactivated_curves.is_in_list(curve))
-                deactivate = 1;
-            }
-          }
-
-          // Deactivate this surface if any of its curves seen from the
-          // virtual layer are out of date.
-          if(!deactivate)
-          {
-            DLIList<Curve*> curves_referenced_by_virtual;
-            DLIList<Curve*> curves_referenced_by_solid_model_layer;
-
-            // Get all of the hidden curves in virtual layer.
-            DLIList<Curve*> hidden_curves;
-            csurf->get_hidden_curves(hidden_curves);
-            for(j=hidden_curves.size(); j--;)
-            {
-              Curve *cur_curve = hidden_curves.get_and_step();
-              CompositeCurve *cur_ccurve = dynamic_cast<CompositeCurve*>(cur_curve);
-              if(cur_ccurve)
-              {
-                for(k=cur_ccurve->num_curves()-1; k>-1; k--)
-                {
-                  Curve *cur = cur_ccurve->get_curve(k);
-                  curves_referenced_by_virtual.append_unique(cur);
-                }
-              }
-              else
-                curves_referenced_by_virtual.append_unique(cur_curve);
-            }
-
-            // Get the boundary curves in virtual layer.
-            DLIList<Curve*> end_curves;
-            csurf->curves(end_curves);
-            for(j=end_curves.size(); j--;)
-            {
-              Curve *cur_curve = end_curves.get_and_step();
-              CompositeCurve *cur_ccurve = dynamic_cast<CompositeCurve*>(cur_curve);
-              if(cur_ccurve)
-              {
-                for(k=cur_ccurve->num_curves()-1; k>-1; k--)
-                {
-                  Curve *cur = cur_ccurve->get_curve(k);
-                  curves_referenced_by_virtual.append_unique(cur);
-                }
-              }
-              else
-                curves_referenced_by_virtual.append_unique(cur_curve);
-            }
-            
-            // Get the curves of all of the surfaces from the solid model layer.
-            int num_surfs = csurf->num_surfs();
-            for(j=0; j<num_surfs; ++j)
-            {
-              Surface *s = csurf->get_surface(j);
-              DLIList<TopologyBridge*> loops;
-              s->get_children(loops, false, 0);
-              for(k=loops.size(); k--;)
-              {
-                LoopSM *cur_loop = dynamic_cast<LoopSM*>(loops.get_and_step());
-                DLIList<TopologyBridge*> coedges;
-                cur_loop->get_children(coedges, false, 0);
-                for(m=coedges.size(); m--;)
-                {
-                  CoEdgeSM *cur_coedge = dynamic_cast<CoEdgeSM*>(coedges.get_and_step());
-                  DLIList<TopologyBridge*> crvs;
-                  cur_coedge->get_children(crvs, false, 0);
-                  for(n=crvs.size(); n--;)
-                  {
-                    Curve *cur_curve = dynamic_cast<Curve*>(crvs.get_and_step());
-                    curves_referenced_by_solid_model_layer.append_unique(cur_curve);
-                  }
-                }
-              }
-            }
-
-            // Now that we have gathered all of the info we can check to make sure
-            // that all of the curves in the virtual layer actually exist in the
-            // solid model layer.
-            if(curves_referenced_by_virtual.size() != 
-              curves_referenced_by_solid_model_layer.size())
-            {
-              deactivate = 1;
-            }
-            else
-            {
-              for(j=curves_referenced_by_virtual.size(); j && !deactivate; j--)
-              {
-                Curve *cur_curve = curves_referenced_by_virtual.get_and_step();
-                if(!curves_referenced_by_solid_model_layer.is_in_list(cur_curve))
-                  deactivate = 1;
-              }
-            }
-          }
-
-          // Check to see if there is a hidden entity that doesn't have a 
-          // COMPOSITE_GEOM attribute.  This can happen if the geometry 
-          // modification operation cut the body right through a hidden 
-          // entity without splitting it.  In this case a merge_owner event
-          // gets triggered and the COMPOSITE_GEOM attribute gets removed
-          // from the hidden entity.  In this case we want to remove the
-          // composite.
-          if(!deactivate)
-          {
-            DLIList<Curve*> hidden_curves;
-            csurf->get_hidden_curves(hidden_curves);
-            for(j=hidden_curves.size(); j>0 && !deactivate; j--)
-            {
-              DLIList<CubitSimpleAttrib*> att_list;
-              hidden_curves.get_and_step()->get_simple_attribute("COMPOSITE_GEOM", att_list);
-              if(att_list.size() == 0)
-                deactivate = 1;
-            }
-          }
-
-          if(deactivate)
-            deactivated_surfs.append_unique(csurf);
-        }
+      int j;
+      DLIList<Point*> hidden;
+      ccurve->get_hidden_points(hidden);
+      for (j=hidden.size(); j--; )
+      {
+        CompositePoint *hpoint = dynamic_cast<CompositePoint*>(hidden.pop());
+        assert(NULL != hpoint);
+        deactivated_points.append_unique(hpoint);
+        already_deactivated_points.append_unique(hpoint);
+        notify_deactivated(hpoint);
       }
+    }
 
-      already_deactivated_points += deactivated_points;
-      already_deactivated_curves += deactivated_curves;
-      already_deactivated_surfs += deactivated_surfs;
+    // Now actually deactivate the out of date composite points.
+    for(j=deactivated_points.size(); j--;)
+    {
+      CompositePoint* cpoint = dynamic_cast<CompositePoint*> (deactivated_points.pop());
+      notify_deactivated(cpoint);
+    }
+  }
 
-      something_changed += deactivated_surfs.size() + deactivated_curves.size() +
-        deactivated_points.size();
-
-      // Now actually deactivate the out of date composite surfs.
-      for(j=deactivated_surfs.size(); j--;)
+  int remove_point_atts = 1;
+  if(remove_point_atts)
+  {
+    // Remove any COMPOSITE_GEOM attributes on points that
+    // have a valence of more than two (real curves - hidden curves).
+    for(i=points.size(); i>0; i--)
+    {
+      Point *pt = points.get_and_step();
+      CompositePoint *cp = dynamic_cast<CompositePoint*>(pt);
+      if(cp)
+        pt = cp->get_point();
+      DLIList<CubitSimpleAttrib*> attribs;
+      pt->get_simple_attribute("COMPOSITE_GEOM", attribs);
+      if(attribs.size() > 0)
       {
-        CompositeSurface *csurf = dynamic_cast<CompositeSurface*>(deactivated_surfs.get_and_step());
-
-        // We have to also deactivate the boundary curves.  When we deactivate
-        // the CompositeSurface it removes all of the CompositeCoEdges associated
-        // with it.  However, it doesn't deactivate the composite curves associated
-        // with the composite coedges.  Therefore you can end up with a regular
-        // CoEdge pointing to a CompositeCurve and if the CompositeCurve has more
-        // than 1 curve in it later calls to replace_surface (which will in turn
-        // call replace_curve) will fail.
-        DLIList<Curve*> boundary_curves;
-        csurf->curves(boundary_curves);
-        for (k=boundary_curves.size(); k--; )
+        DLIList<TopologyBridge*> tmp_curves;
+        pt->get_parents_virt(tmp_curves);
+        int num_curves = 0;
+        for(j=tmp_curves.size(); j>0; j--)
         {
-          CompositeCurve* c = dynamic_cast<CompositeCurve*>(boundary_curves.get_and_step());
-          assert(NULL != c);
-
-          notify_deactivated(c);
+          TopologyBridge *crv = tmp_curves.get_and_step();
+          DLIList<CubitSimpleAttrib*> attribs;
+          crv->get_simple_attribute("COMPOSITE_GEOM", attribs);
+          if(attribs.size() == 0)
+            num_curves++;
         }
-
-        notify_deactivated(csurf);
-
-        DLIList<Curve*> hidden;
-        csurf->get_hidden_curves(hidden);
-        for (k=hidden.size(); k--; )
+        if(num_curves != 2)
         {
-          CompositeCurve* hcurve = dynamic_cast<CompositeCurve*>(hidden.pop());
-          assert(NULL != hcurve);
-
-          notify_deactivated(hcurve);
-
-          if(hcurve->num_curves() == 1)
+          for(j=attribs.size(); j>0; j--)
           {
-            Curve *c = hcurve->get_curve(0);
-            DLIList<TopologyBridge*> end_pts;
-            c->get_children(end_pts, false, 0);
-            for(m=end_pts.size(); m--;)
-            {
-              Point *cur_p = dynamic_cast<Point*>(end_pts.get_and_step());
-              if(cur_p)
-              {
-                CompositePoint* cp = dynamic_cast<CompositePoint*>(cur_p->owner());
-                if(cp)
-                  cur_p = (Point*)cp;
-                TBOwner *own = cur_p->owner();
-                HiddenEntitySet *hes = dynamic_cast<HiddenEntitySet*>(own);
-                if(hes)
-                {
-                  CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hes->owner());
-                  if(cc)
-                  {
-                    notify_deactivated(cc);
-
-                    DLIList<Point*> hidden_pts;
-                    cc->get_hidden_points(hidden_pts);
-                    for (n=hidden_pts.size(); n--; )
-                    {
-                      CompositePoint *hpoint = dynamic_cast<CompositePoint*>(hidden_pts.pop());
-                      assert(NULL != hpoint);
-                      notify_deactivated(hpoint);
-                    }
-                  }
-                }
-              }
-            }
+            CubitSimpleAttrib *csa = attribs.get_and_step();
+            pt->remove_simple_attribute_virt(csa);
           }
         }
       }
-
-      // Now actually deactivate the out of date composite curves.
-      for(j=deactivated_curves.size(); j--;)
-      {
-        CompositeCurve *ccurve = dynamic_cast<CompositeCurve*>(deactivated_curves.get_and_step());
-
-        notify_deactivated(ccurve);
-
-        int j;
-        DLIList<Point*> hidden;
-        ccurve->get_hidden_points(hidden);
-        for (j=hidden.size(); j--; )
-        {
-          CompositePoint *hpoint = dynamic_cast<CompositePoint*>(hidden.pop());
-          assert(NULL != hpoint);
-          notify_deactivated(hpoint);
-        }
-      }
-
-      // Now actually deactivate the out of date composite points.
-      for(j=deactivated_points.size(); j--;)
-      {
-        CompositePoint* cpoint = dynamic_cast<CompositePoint*> (deactivated_points.pop());
-        notify_deactivated(cpoint);
-      }
     }
   }
 }
@@ -4789,8 +4745,9 @@
     surfaces += temp_surfaces;
     lumps += temp_lumps;
   }
-  
-    // assert that lists do not contain duplicates
+
+ 
+  // assert that lists do not contain duplicates
   //assert( (i = points.size(),   points.uniquify_ordered(),   i == points.size()  ) );
   //assert( (i = curves.size(),   curves.uniquify_ordered(),   i == curves.size()  ) );  
   points.uniquify_ordered(); // can have duplicates in some non-manifold cases
@@ -4835,17 +4792,15 @@
     if( !create_composites( curves   ) ) result = CUBIT_FAILURE;
     if( !create_composites( points   ) ) result = CUBIT_FAILURE;
   }
-  else
-  {
-    for ( i = bodies.size(); i--; )
-      strip_attributes( bodies.get_and_step() );
-    for ( i = surfaces.size(); i--; )
-      strip_attributes( surfaces.get_and_step() );
-    for ( i = curves.size(); i--; )
-      strip_attributes( curves.get_and_step() );
-    for ( i = points.size(); i--; )
-      strip_attributes( points.get_and_step() );
-  }
+
+  for ( i = bodies.size(); i--; )
+    strip_attributes( bodies.get_and_step() );
+  for ( i = surfaces.size(); i--; )
+    strip_attributes( surfaces.get_and_step() );
+  for ( i = curves.size(); i--; )
+    strip_attributes( curves.get_and_step() );
+  for ( i = points.size(); i--; )
+    strip_attributes( points.get_and_step() );
   
     // update imported_geom list to contain composites rather than
     // entities used to create the composites
@@ -4864,7 +4819,6 @@
     // entity.  need to remove the duplicates.
   imported_geom.uniquify_unordered();
 */
-  
     // that's all folks
   return result;
 } 
@@ -4887,6 +4841,24 @@
   return ret;
 }
 
+bool CompositeEngine::is_composite(TopologyBridge *bridge)
+{
+  bool ret = false;
+  if(bridge)
+  {
+    if(dynamic_cast<CompositeBody*>(bridge) ||
+       dynamic_cast<CompositeLump*>(bridge) ||
+       dynamic_cast<CompositeSurface*>(bridge) ||
+       dynamic_cast<CompositeCurve*>(bridge) ||
+       dynamic_cast<CompositeCoEdge*>(bridge) ||
+       dynamic_cast<CompositePoint*>(bridge))
+    {
+      ret = true;
+    }
+  }
+  return ret;
+}
+
 bool CompositeEngine::is_partition(TBOwner *bridge_owner)
 {
   return false;
@@ -4941,35 +4913,47 @@
     surface_list += temp_surfaces;
   }
 
-  DLIList<CompositeCurve*> ccurve_list;
-  DLIList<CompositeSurface*> csurf_list;
+//  DLIList<CompositeCurve*> ccurve_list;
+//  DLIList<CompositeSurface*> csurf_list;
 
-  CAST_LIST( curve_list, ccurve_list, CompositeCurve );
-  CAST_LIST( surface_list, csurf_list, CompositeSurface );
+//  CAST_LIST( curve_list, ccurve_list, CompositeCurve );
+//  CAST_LIST( surface_list, csurf_list, CompositeSurface );
 
-  ccurve_list.uniquify_unordered();
-  csurf_list.uniquify_unordered();
+//  ccurve_list.uniquify_unordered();
+//  csurf_list.uniquify_unordered();
+  curve_list.uniquify_unordered();
+  surface_list.uniquify_unordered();
 
   int j,k;
-  for( i = ccurve_list.size(); i--; )
+  for( i = curve_list.size(); i--; )
   {
-    CompositeCurve* tmp_comp_curve = ccurve_list.get_and_step();
-    for( j = 0; j < tmp_comp_curve->num_curves(); j++ )
+    Curve *tmp_curve = curve_list.get_and_step();
+    strip_attributes(tmp_curve);
+    CompositeCurve* tmp_comp_curve = dynamic_cast<CompositeCurve*>(tmp_curve);
+    if(tmp_comp_curve)
     {
-      strip_attributes( tmp_comp_curve->get_curve(j) );
+      for( j = 0; j < tmp_comp_curve->num_curves(); j++ )
+      {
+        strip_attributes( tmp_comp_curve->get_curve(j) );
 
-      //remove attributes off underlying points too
-      DLIList<Point*> hidden_points;
-      tmp_comp_curve->get_hidden_points( hidden_points );
-      for( k=hidden_points.size(); k--; )
-        strip_attributes( hidden_points.get_and_step() );
+        //remove attributes off underlying points too
+        DLIList<Point*> hidden_points;
+        tmp_comp_curve->get_hidden_points( hidden_points );
+        for( k=hidden_points.size(); k--; )
+          strip_attributes( hidden_points.get_and_step() );
+      }
     }
   }
-  for( i = csurf_list.size(); i--; )
+  for( i = surface_list.size(); i--; )
   {
-    CompositeSurface *tmp_comp_surf = csurf_list.get_and_step();
-    for( int j = 0; j < tmp_comp_surf->num_surfs(); j++ )
-      strip_attributes( tmp_comp_surf->get_surface(j) );
+    Surface *tmp_surf = surface_list.get_and_step();
+    strip_attributes(tmp_surf);
+    CompositeSurface *tmp_comp_surf = dynamic_cast<CompositeSurface*>(tmp_surf);
+    if(tmp_comp_surf)
+    {
+      for( int j = 0; j < tmp_comp_surf->num_surfs(); j++ )
+        strip_attributes( tmp_comp_surf->get_surface(j) );
+    }
   }
 
   //remove attrigutes off of bridges passed in
@@ -5145,15 +5129,6 @@
     CubitSimpleAttrib* attrib = find_attribute_by_name( curve, "COMPOSITE_GEOM" );
     if( attrib )
     {
-      // The attribute contains the ids of surfaces in the composite
-      // that should be ignored during evaluation.  Get these ids
-      // and put them in a list to be used below.
-      DLIList<int> surfs_to_ignore;
-      for(int k=attrib->int_data_list()->size(); k--;)
-      {
-        surfs_to_ignore.append(*(attrib->int_data_list()->get_and_step()));
-      }
-       
       curve->remove_simple_attribute_virt( attrib );
       
 /*
@@ -5202,9 +5177,15 @@
       {
         // Tell the composite surface which surfaces to ignore during
         // evaluation.
-        for(int k=surfs_to_ignore.size(); k--;)
+        for(int j=0; j<surf->num_surfs(); j++)
         {
-          surf->ignore_surface(surfs_to_ignore.get_and_step());
+          Surface *srf = surf->get_surface(j);
+          CubitSimpleAttrib* ignore_attrib = find_attribute_by_name( srf, "COMPOSITE_IGNORE" );
+          if( ignore_attrib )
+          {
+            surf->ignore_surface(srf);
+            srf->remove_simple_attribute_virt( ignore_attrib );
+          }
         }
         surf->read_attributes();
       }
@@ -5331,7 +5312,9 @@
 // Creation Date : 06/18/02
 //-------------------------------------------------------------------------
 CubitStatus CompositeEngine::create_composites( DLIList<BodySM*>&  )
-  { return CUBIT_SUCCESS; }
+{ 
+  return CUBIT_SUCCESS; 
+}
 
 //-------------------------------------------------------------------------
 // Purpose       : Save composite geometry
@@ -5438,20 +5421,11 @@
             geom_attrib.int_data_list()->append(&tb_id);
             append_attrib(tb, &geom_attrib);
             geom_attrib.int_data_list()->clean_out();
+
          }
       }
    }
-   /* Do the same for curves here.
-   ccurve_list.reset();
-   for(i=ccurve_list.size(); i--;)
-   {
-      CompositeCurve *cur_curve = ccurve_list.get_and_step();
-      cur_curve->add_topology_id_attributes();
-      cur_curve->add_ignore_attributes();
-   }
-   */
 
-
     for( i = ccurve_list.size(); i--; )
       save( ccurve_list.get_and_step() );
     for( i = csurf_list.size(); i--; )
@@ -5630,16 +5604,8 @@
     
     for( j = 0; j < ccurve->num_curves(); j++ )
     {      
-      // Add to the attribute information about surfaces
-      // to ignore during evaluation.
-      for(int k=surf->surfacesToIgnore.size(); k--;)
-      {
-         int *id = new int(surf->surfacesToIgnore.get_and_step());
-         geom_attrib.int_data_list()->append(id);
-      }
       Curve* tb = ccurve->get_curve(j);
       append_attrib( tb, &geom_attrib );
-      geom_attrib.int_data_list()->clean_out();
     }  
   }
   
@@ -5682,6 +5648,19 @@
     }
   }
 
+  name = "COMPOSITE_IGNORE";
+  CubitSimpleAttrib ignore_attrib( &string_list, 0, 0 );
+
+  DLIList<Surface*> srfs;
+  surf->get_ignored_surfs(srfs);
+  for( i = 0; i < surf->num_surfs(); i++ )
+  {
+    Surface *srf = surf->get_surface(i);
+    if(srfs.is_in_list(srf))
+      srf->append_simple_attribute_virt(&ignore_attrib);
+  }
+
+
   return CUBIT_SUCCESS;
 }
 
@@ -5911,7 +5890,7 @@
   Point *result = 0;
   CubitVector position;
   DLIList<Point*> pts;
-  const double tolsqr = GEOMETRY_RESABS*GEOMETRY_RESABS;
+  double tolsqr = GEOMETRY_RESABS*GEOMETRY_RESABS;
   Point *start, *end;
   DLIList<TopologyBridge*> pt_list;
   Curve *rcurve = 0;
@@ -5933,8 +5912,28 @@
   for(i=pts.size(); i--;)
   {
     Point *cur_pt = pts.get_and_step();
-    if( (cur_pt->coordinates() - position).length_squared() < tolsqr )
+
+    // Don't use GEOMETRY_RESABS if we can get a
+    // value from the solid modeling engine.
+    double tmp_tol = tolsqr;
+    CompositePoint *cp = dynamic_cast<CompositePoint*>(cur_pt);
+    GeometryQueryEngine *gqe = NULL;
+    if(cp)
     {
+      Point *real_pt = cp->get_point();
+      gqe = real_pt->get_geometry_query_engine();
+    }
+    else
+      gqe = cur_pt->get_geometry_query_engine();
+    if(gqe)
+    {
+      double tmp_tol = gqe->get_sme_resabs_tolerance();
+      tmp_tol *= tmp_tol;
+      if(tmp_tol > tolsqr)
+        tolsqr = tmp_tol;
+    }
+    if( (cur_pt->coordinates() - position).length_squared() < tmp_tol )
+    {
       result = cur_pt;
       i = 0;
     }
@@ -6552,3 +6551,10 @@
   delete comp2;
   return comp1;
 }
+
+void CompositeEngine::get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                                            DLIList<TopologyBridge*> &tbs )
+{
+  //do nothing.
+}
+

Modified: cgm/branches/cubit/geom/virtual/CompositeEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -39,17 +39,23 @@
 class CompositeEngine : public IntermediateGeomEngine
 {
 	public:
+    void get_all_curves_and_points(DLIList<TopologyBridge*> &tb_list,
+                                   DLIList<Curve*> &curves,
+                                   DLIList<Point*> &points);
     bool is_composite(TBOwner *bridge_owner);
+    bool is_composite(TopologyBridge *bridge);
     bool is_partition(TBOwner *bridge_owner);
 
     virtual void remove_imprint_attributes_after_modify
                                 ( DLIList<BodySM*> &old_sms,
                                 DLIList<BodySM*> &new_sms );
+    virtual void push_named_attributes_to_curves_and_points
+                     ( DLIList<TopologyBridge*> &tb_list, const char *name_in);
     virtual void push_imprint_attributes_before_modify
                      ( DLIList<BodySM*> &body_sms );
     virtual void attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
                                                     DLIList<TopologyBridge*> &att_tbs,
-                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<TopologyBridge*> &tb_list,
                                                         DLIList<Body*> &old_bodies);
 
     // This is a copy of the function in MergeTool with the difference that it
@@ -64,7 +70,8 @@
     virtual ~CompositeEngine();
 	
     static CompositeEngine& instance();
-    
+    static void delete_instance();
+
     int level() const { return COMPOSITE_LAYER; }
 		
     CubitStatus import_geometry( DLIList<TopologyBridge*>& imported_geometry );
@@ -202,8 +209,13 @@
 
     void remove_attributes( DLIList<TopologyBridge*> &bridge_list );
       //remove Composite attributes off of topology bridges
-    void remove_modified(DLIList<TopologyBridge*>& geometry_list);
+    virtual void remove_modified(DLIList<Surface*> &all_surfs,
+      DLIList<Curve*> &all_curves, DLIList<Point*> &all_pts);
+
+    void get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                               DLIList<TopologyBridge*> &tbs );
     
+    
   protected:
 	
     Point* remove_composite( CompositePoint* point );

Modified: cgm/branches/cubit/geom/virtual/CompositeGeom.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeGeom.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeGeom.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -60,7 +60,12 @@
 //-------------------------------------------------------------------------
 CompositeGeom::~CompositeGeom()
 {
-  rem_all_attributes();
+  while(listHead)
+  {
+    CompositeAttrib* dead = listHead;
+    listHead = listHead->next;
+    delete dead;
+  }
 }
 
 //-------------------------------------------------------------------------
@@ -609,8 +614,8 @@
     delete dead;
   }
   
- // if (entityList.size() == 1)
- //   entityList[0].entity->remove_all_simple_attribute_virt();
+  if (entityList.size() == 1)
+    entityList[0].entity->remove_all_simple_attribute_virt();
 }
 
 
@@ -820,6 +825,20 @@
       assert(attrib->int_data_list()->size());
       if (*attrib->int_data_list()->get() == entityList.size())
       {
+        // Take the attributes off of the current entity and put them on the first entity
+        // in this list.  I believe this is ok to do because the attributes should apply to
+        // the whole composite surface and not just the underlying entity they are on 
+        // (the one exception to this might be UNIQUE_ID but I haven't seen any problems
+        // with this yet).  The reason for doing this is that there is some code (I believe
+        // in uncomposite() that assumes any attributes will be on the first entity
+        // in the list.  Previous code actually moved the entity to the beginning
+        // of the list but this reordering of the list does not fly with composite
+        // curves because there is code depending on the curves in the list being
+        // ordered so that they connect end to end in a contiguous manner (the 
+        // faceting code, for one, relies on this).  BWC 1/7/07.
+        entityList[i].entity->remove_simple_attribute_virt(attrib);
+        entityList[0].entity->append_simple_attribute_virt(attrib);
+
         delete attrib->int_data_list()->remove();
         attrib->string_data_list()->reset();
         delete attrib->string_data_list()->remove();
@@ -828,14 +847,6 @@
       }
     }
   }
-
-  if( index_of_entity_with_attribs != 0 && index_of_entity_with_attribs != -1 )
-  {
-    //Swap entities around so that one with attribs is first
-    CompositeEntry should_be_first =  entityList[ index_of_entity_with_attribs ];
-    entityList.remove( index_of_entity_with_attribs );
-    entityList.insert( should_be_first, 0 ); 
-  }
 }
 
 //-------------------------------------------------------------------------

Modified: cgm/branches/cubit/geom/virtual/CompositeGeom.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeGeom.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeGeom.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -21,6 +21,7 @@
 class GeometryEntity;
 class CubitSimpleAttrib;
 class CompositeAttrib;
+class TopologyBridge;
 
 struct CompositeEntry
 {

Modified: cgm/branches/cubit/geom/virtual/CompositeLoop.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeLoop.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeLoop.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -171,6 +171,27 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : The purpose of this function is to see if a loop is an external
+//                  or internal loop of a surface.
+//
+// Special Notes : 
+//
+// Creator       : Jonathan Bugman
+//
+// Creation Date : 9/9/2008
+//-------------------------------------------------------------------------
+CubitBoolean CompositeLoop::is_external()
+{
+		  PRINT_ERROR( "This command is not supported with this engine.\n");
+          return CUBIT_FAILURE;
+}
+
+LoopType CompositeLoop::loop_type()
+{
+  return LOOP_TYPE_UNKNOWN;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : get parent bridges
 //
 // Special Notes : pure virtual in TopologyBridge

Modified: cgm/branches/cubit/geom/virtual/CompositeLoop.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeLoop.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeLoop.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -44,6 +44,13 @@
   GeometryQueryEngine* get_geometry_query_engine() const;
   int layer() const { return COMPOSITE_LAYER; }
   
+  virtual LoopType loop_type() ;
+  virtual CubitBoolean is_external() ;
+    //R CubitBoolean
+    //R- CUBIT_TRUE/CUBIT_FALSE
+    //- Returns CUBIT_TRUE if the Loop is an external Loop and CUBIT_FALSE
+    //- otherwise.
+
   void append_simple_attribute_virt( CubitSimpleAttrib* );
   void remove_simple_attribute_virt( CubitSimpleAttrib* );
   void remove_all_simple_attribute_virt();

Modified: cgm/branches/cubit/geom/virtual/CompositeSurface.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeSurface.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeSurface.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -320,6 +320,21 @@
   return CUBIT_SUCCESS;
 }
 
+void CompositeSurface::get_ignored_surfs(DLIList<Surface*> &surfs)
+{
+  int i;
+
+  if(surfacesToIgnore.size() > 0)
+  {
+    for(i=0; i<num_surfs(); i++)
+    {
+      Surface *srf = get_surface(i);
+      if(surfacesToIgnore.is_in_list(srf))
+        surfs.append(srf);
+    }
+  }
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Return the bounding box
 //
@@ -629,11 +644,10 @@
          facetTool->set_ignore_flag(i, 0);
 
          Surface *cur_surf = get_surface(i);
-         int id = cur_surf->get_saved_id();
          surfacesToIgnore.reset();
          for(int j=surfacesToIgnore.size(); j--;)
          {
-            if(id == surfacesToIgnore.get_and_step())
+            if(cur_surf == surfacesToIgnore.get_and_step())
             {
                facetTool->set_ignore_flag(i, 1);
                j=0;
@@ -658,13 +672,30 @@
          Surface *cur_surf = get_surface(i);
          if(cur_surf->get_saved_id() == surface_id)
          {
-            break;
+            surfacesToIgnore.append_unique(cur_surf);
+            i = num_surfs_in_composite;
+            update_facets_to_ignore();
          }
       }
-      if(i < num_surfs_in_composite)
+   }
+}
+
+void CompositeSurface::ignore_surface(Surface *surf)
+{
+   update_facet_tool();
+   if(facetTool)
+   {
+      int i;
+      int num_surfs_in_composite = num_surfs();
+      for (i=0; i<num_surfs_in_composite; i++)
       {
-         surfacesToIgnore.append_unique(surface_id);
-         update_facets_to_ignore();
+         Surface *cur_surf = get_surface(i);
+         if(cur_surf == surf)
+         {
+            surfacesToIgnore.append_unique(cur_surf);
+            i = num_surfs_in_composite;
+            update_facets_to_ignore();
+         }
       }
    }
 }
@@ -683,14 +714,11 @@
          Surface *cur_surf = get_surface(i);
          if(cur_surf->get_saved_id() == surface_id)
          {
-            break;
+            surfacesToIgnore.remove(cur_surf);
+            update_facets_to_ignore();
+            i = num_surfs_in_composite;
          }
       }
-      if(i < num_surfs_in_composite)
-      {
-         surfacesToIgnore.remove(surface_id);
-         update_facets_to_ignore();
-      }
    }
 }
 
@@ -847,6 +875,7 @@
                                           curvature1, curvature2 );
   
   update_facet_tool();
+  
   if ( facetTool )
   {
     CubitStatus result;
@@ -861,30 +890,39 @@
 
       CubitVector normal(0.0, 0.0, 0.0);
       int i;
-      for (i = 0; i < num_found; i++) {
+      for (i = 0; i < num_found; i++) 
+      {
         int index = index_list[i];
-        Surface* surf = get_surface(index);
-        
-        result = surf->closest_point( facet_closest, closest_location,
-                                      &normal, curvature1, curvature2 );
-        
-        if (get_sense(index) == CUBIT_REVERSED)
-          *unit_normal += (-normal);
-        else
-          *unit_normal += normal;
+        if(index > -1)
+        {
+          Surface* surf = get_surface(index);
+          
+          result = surf->closest_point( facet_closest, closest_location,
+                                        &normal, curvature1, curvature2 );
+          
+          if (get_sense(index) == CUBIT_REVERSED)
+            *unit_normal += (-normal);
+          else
+            *unit_normal += normal;
+        }
       }
       unit_normal->normalize();
     }
     else
     {  
       int index = facetTool->closest_index( location, &facet_closest );
-      Surface* surf = get_surface(index);
+      if(index > -1)
+      {
+        Surface* surf = get_surface(index);
+      
+        result = surf->closest_point( facet_closest, closest_location,
+                                      unit_normal, curvature1, curvature2 );
     
-      result = surf->closest_point( facet_closest, closest_location,
-                                    unit_normal, curvature1, curvature2 );
-    
-//       if (unit_normal && get_sense(index) == CUBIT_REVERSED)
-//         *unit_normal = -*unit_normal;
+  //       if (unit_normal && get_sense(index) == CUBIT_REVERSED)
+  //         *unit_normal = -*unit_normal;
+      }
+      else
+        result = CUBIT_FAILURE;
     }
     
     return result;
@@ -1550,7 +1588,7 @@
       for(int k=surfacesToIgnore.size(); k--;)
       {
          PRINT_INFO("%sSurface: %d\n", 
-                    new_prefix, surfacesToIgnore.get_and_step());
+                    new_prefix, surfacesToIgnore.get_and_step()->get_saved_id());
       }
   }
   if( hiddenSet ) hiddenSet->print_debug_info( new_prefix );
@@ -1886,7 +1924,7 @@
   if (!facetTool)
     return CUBIT_FAILURE;
   
-  facetTool->graphics( GEOMETRY_RESABS*10, gmem);
+  facetTool->graphics( GEOMETRY_RESABS, gmem);
   return CUBIT_SUCCESS;
 }
 

Modified: cgm/branches/cubit/geom/virtual/CompositeSurface.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeSurface.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeSurface.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -46,6 +46,7 @@
 	
   //CubitStatus add( Surface* surface, CubitSense relative_sense );
   //CubitStatus remove( Surface* surface );	
+  void get_ignored_surfs(DLIList<Surface*> &surfs);
   int num_surfs() const;
   int index_of( Surface* surface ) const;
   void update();
@@ -53,6 +54,7 @@
   CubitSense get_sense( int index ) const;
   Surface* remove_surface( int index );
   void ignore_surface(int surface_id);
+  void ignore_surface(Surface *surf);
   void unignore_surface(int surface_id);
   CompositeLoop* first_loop() const;
   CompositeLoop* next_loop( CompositeLoop* after_this = 0 ) const;
@@ -216,7 +218,7 @@
 private:
   int HadBridgeRemoved;
 
-  DLIList<int> surfacesToIgnore;	
+  DLIList<Surface*> surfacesToIgnore;	
 
     // these have no implementation, just private delcarations
     // to prevent the compiler from generating default implementations

Modified: cgm/branches/cubit/geom/virtual/CompositeTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/CompositeTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/CompositeTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -128,7 +128,7 @@
     PRINT_ERROR("Cannot create any composites from passed curves.\n");
     return 0;
   }
-  
+ 
   vertex_list.reset();
   RefEdge* result = 0;
   DLIList<RefEdge*> vtx_edges;
@@ -163,6 +163,7 @@
   modified_edges.remove_all_with_value(0);
   
   result = modified_edges.size() ? modified_edges.get() : 0;
+
   DLIList<Surface*> update_surfaces, curve_surfaces;
   DLIList<TopologyBridge*> curve_bridges;
   for ( i = modified_edges.size(); i--; )
@@ -205,9 +206,6 @@
                                        bool update_dag ,       /* = true  */
                                        RefEdge* keep_edge      /* = NULL */ )
 {
-#ifdef BOYD17
-  DLIList<RefEdge*> free_edges, vertex_edges;
-#endif
   DLIList<RefEdge*> vertex_edges;
   int i;
   
@@ -277,7 +275,11 @@
     } // end if (curves.size() == 1)
     
 
-    assert(curves.size() == 2);
+   // assert(curves.size() == 2);
+    if(curves.size() != 2)
+    {
+      break;
+    }
     
     TopologyEntity* topo = curves.get()->topology_entity();
     refedge1 = CAST_TO(topo, RefEdge);
@@ -339,13 +341,18 @@
       end_result = result_curve;
   }
   
-  RefEdge* result = dynamic_cast<RefEdge*>(end_result->topology_entity());
-  
-  
+  RefEdge* result = NULL;
+  if(end_result)
+    result = dynamic_cast<RefEdge*>(end_result->topology_entity());
+    
+  RefEdge* dead = NULL;
+  if(result)
+  {
     // notify observers that one edge is being composited into another
     // TODO - make a simple function for this notification since it is  times????
-  RefEdge* dead = result != refedge1 ? refedge1 : result != refedge2 ? refedge2 : 0;
-  update_combined_edges( result, dead );
+    dead = result != refedge1 ? refedge1 : result != refedge2 ? refedge2 : 0;
+    update_combined_edges( result, dead );
+  }
 
   if ( result && update_dag )
   {
@@ -451,7 +458,11 @@
     {
       RefFace* face1 = coedges.get()->get_ref_face();
       RefFace* face2 = coedges.next()->get_ref_face();
-      if (face_list.is_in_list(face1) && face_list.is_in_list(face2))
+      // Check to make sure both faces are in the faces we are compositing
+      // and also make sure the faces are not the same otherwise we
+      // will composite out hardlines in one of the faces.
+      if (face1 != face2 &&
+        face_list.is_in_list(face1) && face_list.is_in_list(face2))
         continue;
     }
     
@@ -464,7 +475,7 @@
     PRINT_ERROR("Cannot create composites from the specified surfaces.\n");
     return 0;
   }
-  
+
   edge_list.reset();
   for( i = edge_list.size(); i--; )
   {
@@ -1525,9 +1536,8 @@
     if(DEBUG_FLAG(87))
     {
       GMem gmem;
-      int count;
-      curve->get_geometry_query_engine()->get_graphics(curve,count,&gmem);
-      GfxDebug::draw_polyline(gmem.point_list(),count,CUBIT_RED);
+      curve->get_geometry_query_engine()->get_graphics(curve,&gmem);
+      GfxDebug::draw_polyline(gmem.point_list(),gmem.pointListCount,CUBIT_RED);
       GfxDebug::flush();
     }
 
@@ -2163,7 +2173,7 @@
     for ( i = s_itor->size(); i--; )
       s_itor->get_and_step()->marked(0);
   }
-  
+
     // composite faces
   for ( s_itor = face_sets.begin(); s_itor != face_sets.end(); ++s_itor )
   {
@@ -2176,7 +2186,7 @@
     else
       result = CUBIT_FAILURE;
   }
-  
+
   return result;
 }
 

Modified: cgm/branches/cubit/geom/virtual/FacetProjectTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/FacetProjectTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/FacetProjectTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -70,29 +70,36 @@
     // make the PST edges and faces from the coordinates and connections.
   PST_Edge::make_facets( coordinates, connections, GEOMETRY_RESABS, facet_edges );
   DLIList<PST_Face*> faces;
-  PST_Edge::faces( facet_edges, faces );
-  populate_data(faces);
 
-    // Order the orignal points by sequence number.  New points
-    // will be appended in order.
-  pointList.sort(&sequence_compare_pts);
-      
-    // Do the work
-  CubitBoolean point_changed;
-  do_projection(segments, point_changed, tolerance_length);
-  
-    // fill in segmentPoints
-  assert (segPoints.size() == segments.size());
-  segmentPoints.resize( segPoints.size() );
-  segPoints.reset();
   CubitStatus success = CUBIT_SUCCESS;
-  for ( i = 0; i < segPoints.size(); i++ )
+  if(facet_edges.size() > 0)
   {
-    PST_Point* pt = segPoints.get_and_step();
-    segmentPoints[i] = pt ? pt->sequence : -1;
-    if (point_changed)
-      success = CUBIT_FAILURE;
+
+    PST_Edge::faces( facet_edges, faces );
+    populate_data(faces);
+
+      // Order the orignal points by sequence number.  New points
+      // will be appended in order.
+    pointList.sort(&sequence_compare_pts);
+        
+      // Do the work
+    CubitBoolean point_changed;
+    success = do_projection(segments, point_changed, tolerance_length);
+    
+      // fill in segmentPoints
+//    assert (segPoints.size() == segments.size());
+    segmentPoints.resize( segPoints.size() );
+    segPoints.reset();
+    for ( i = 0; i < segPoints.size(); i++ )
+    {
+      PST_Point* pt = segPoints.get_and_step();
+      segmentPoints[i] = pt ? pt->sequence : -1;
+      if (point_changed)
+        success = CUBIT_FAILURE;
+    }
   }
+  else
+    success = CUBIT_FAILURE;
   
   if (!success)
   {
@@ -808,20 +815,24 @@
     
     PST_Point* start_point = last_point;
     PST_Point* end_point = end_pt;
-    project( last_point, end_pt );
-    if ((*start_point - *last_point).length_squared() > TOL_SQR)
+    if(project( last_point, end_pt ) == CUBIT_SUCCESS)
     {
-       segPoints.move_to(start_point);
-       segPoints.change_to(last_point);
-       point_changed = CUBIT_TRUE;
+      if ((*start_point - *last_point).length_squared() > TOL_SQR)
+      {
+        segPoints.move_to(start_point);
+        segPoints.change_to(last_point);
+        point_changed = CUBIT_TRUE;
+      }
+      if ((*end_pt - *end_point).length_squared() > TOL_SQR)
+      {
+        segPoints.move_to(end_point);
+        segPoints.change_to(end_pt);
+        point_changed = CUBIT_TRUE;
+      }
+      last_point = end_pt;
     }
-    if ((*end_pt - *end_point).length_squared() > TOL_SQR)
-    {
-       segPoints.move_to(end_point);
-       segPoints.change_to(end_pt);
-       point_changed = CUBIT_TRUE;
-    }
-    last_point = end_pt;
+    else
+      return CUBIT_FAILURE;
   
   } // end for( i = segments )
   
@@ -846,7 +857,7 @@
 //-------------------------------------------------------------------------
 CubitStatus FacetProjectTool::project( PST_Point* &start, PST_Point* &end )
 {
-  PST_Edge* edge,* closest_edge;
+  PST_Edge* edge,* closest_edge, *last_closest_edge=NULL;
   PST_Face* closest_face;
   PST_Point* point;
   PST_Point* start_point = start;
@@ -891,10 +902,14 @@
     
       // Get face or edge adjacent to start and closest to the polyline segment
     stat = next_around_point( start_point, *end, closest_face, closest_edge, 
-                              is_boundary_edge );
+                              is_boundary_edge, last_closest_edge);
+
+    if(closest_edge)
+      last_closest_edge = closest_edge;
+
     if (!stat || (closest_face && closest_edge))
     {
-      assert(false);
+ //     assert(false);
       return stat;
     }
     
@@ -1003,7 +1018,12 @@
           // Otherwise closest point to segment end is in the interior
           // of the edge -- split the edge.
         else
-          point = split_edge( closest_edge, t_edge );
+        {
+          if(start_point != closest_edge->start_point())
+            point = split_edge( closest_edge, 1.0 - t_edge );
+          else
+            point = split_edge( closest_edge, t_edge );
+        }
       }
     } // if(closest_edge)
 
@@ -1070,7 +1090,8 @@
                                         const CubitVector& seg_end,
                                         PST_Face*& closest_face,
                                         PST_Edge*& closest_edge,
-                                        CubitBoolean & is_boundary_edge )
+                                        CubitBoolean & is_boundary_edge,
+                                        PST_Edge *last_closest_edge)
 {
   DLIList<PST_Face*> face_list;
   DLIList<PST_Edge*> boundary_edges;
@@ -1176,7 +1197,7 @@
         const double dist_sqr = 
           tangent.length_squared() - dot_prod * dot_prod / prev.length_squared();
 
-        if (dist_sqr <= shortest_dist_sqr)
+        if (dist_sqr <= shortest_dist_sqr && coedge->edge() != last_closest_edge)
         {
           closest_face = 0;
           closest_edge = coedge->edge();
@@ -1219,7 +1240,7 @@
     
     const double dist_sqr =
       tangent.length_squared() - dot_prod * dot_prod / edge_tan.length_squared();
-    if (dist_sqr < shortest_dist_sqr)
+    if (dist_sqr < shortest_dist_sqr && edge != last_closest_edge)
     {
       closest_edge = edge;
       is_boundary_edge = CUBIT_TRUE;

Modified: cgm/branches/cubit/geom/virtual/FacetProjectTool.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/FacetProjectTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/FacetProjectTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -216,7 +216,8 @@
                                  const CubitVector& segment_end,
                                  PST_Face*& closest_face,
                                  PST_Edge*& closest_edge,
-                                 CubitBoolean & is_boundary_edge );
+                                 CubitBoolean & is_boundary_edge,
+                                 PST_Edge *last_closest_edge);
   
   private:
   

Modified: cgm/branches/cubit/geom/virtual/Faceter.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/Faceter.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/Faceter.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -583,10 +583,8 @@
   GMem curve_graphics;
   const double dist_tol = GEOMETRY_RESABS;
   const double dist_tol_sqr = dist_tol*dist_tol;
-  int n;
   Curve* curve_ptr = curve->get_curve_ptr();
-  curve_ptr->get_geometry_query_engine()->get_graphics( 
-    curve_ptr, n, &curve_graphics );
+  curve_ptr->get_geometry_query_engine()->get_graphics( curve_ptr, &curve_graphics );
   
   GPoint* gp = curve_graphics.point_list();
   CubitPoint* last = (CubitPoint*) new FaceterPointData( gp->x, gp->y, gp->z );

Modified: cgm/branches/cubit/geom/virtual/ImprintBoundaryTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/ImprintBoundaryTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/ImprintBoundaryTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -394,9 +394,8 @@
     //make sure the segments are larger than the tolerance.
   const double dist_tol = 2*myTolerance + .5*myTolerance;// + .05*myTolerance;
   //const double dist_tol_sqr = dist_tol*dist_tol;
-  int n;
   Curve* curve_ptr = curve->get_curve_ptr();
-  curve_ptr->get_geometry_query_engine()->get_graphics( curve_ptr, n, &curve_graphics );
+  curve_ptr->get_geometry_query_engine()->get_graphics( curve_ptr, &curve_graphics );
   
   GPoint* gp = curve_graphics.point_list();
   ImprintPointData* last = new ImprintPointData( gp[0].x, gp[0].y, gp[0].z );
@@ -6006,6 +6005,14 @@
       return NULL;
   }
 
+  bool start_vertex_is_free = true;
+  if( start->num_parent_ref_entities() )
+    start_vertex_is_free = false;
+
+  bool end_vertex_is_free = true;
+  if( end->num_parent_ref_entities() )
+    end_vertex_is_free = false;
+
   DLIList<CoEdgeSM*> coedgesms;
   GeometryEntity *ge = start->get_geometry_entity_ptr();
   Point *start_psm = CAST_TO(ge, Point);
@@ -6022,6 +6029,12 @@
     return (RefEdge*)NULL;
   }
   
+  //if vertices are consumed....notify that they are gone.
+  if( start_vertex_is_free )
+    start->notify_all_observers( TOP_LEVEL_ENTITY_DESTRUCTED );
+  if( end_vertex_is_free )
+    end->notify_all_observers( TOP_LEVEL_ENTITY_DESTRUCTED );
+  
   Curve *new_curve_ptr = (Curve*) new_facet_curve;
   return GeometryQueryTool::instance()->make_RefEdge(new_curve_ptr);
 }

Modified: cgm/branches/cubit/geom/virtual/Makefile.am
===================================================================
--- cgm/branches/cubit/geom/virtual/Makefile.am	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/Makefile.am	2010-01-06 19:22:14 UTC (rev 3423)
@@ -60,6 +60,7 @@
     PartSurfFacetTool.cpp \
     PST_Data.cpp \
     SegmentedCurve.cpp \
+    SplitCompositeSurfaceTool.cpp \
     SubCurve.cpp \
     SubEntitySet.cpp \
     SubSurface.cpp \
@@ -115,6 +116,7 @@
     PartitionSurface.hpp \
     PartitionTool.hpp \
     SegmentedCurve.hpp \
+    SplitCompositeSurfaceTool.hpp \
     SplitSurfaceVirtual.hpp \
     SubCurve.hpp \
     SubEntitySet.hpp \

Modified: cgm/branches/cubit/geom/virtual/PST_Data.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PST_Data.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PST_Data.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -960,11 +960,13 @@
     {
       PST_Face* new_face 
         = PST_Edge::create_face( ptlist[i1], ptlist[i2], ptlist[i3] );
-      if( new_face )
+      if( new_face ){
         face_list.append(new_face);
-      else
+        new_face->sequence = i;
+      }
+      else{
         fail_count++;
-      new_face->sequence = i;
+      }
     }
   }
    
@@ -975,11 +977,14 @@
   delete [] ptindex_list;
   delete [] ptlist;
   
-  PST_Edge::edges( face_list, edge_list );
-  validate( edge_list, true );
-  bool debug1 = false;
-  if (debug1)
-    debug_draw_edges( edge_list, CUBIT_BLUE, CUBIT_RED, true );
+  if(fail_count == 0)
+  {
+    PST_Edge::edges( face_list, edge_list );
+    validate( edge_list, true );
+    bool debug1 = false;
+    if (debug1)
+      debug_draw_edges( edge_list, CUBIT_BLUE, CUBIT_RED, true );
+  }
 }
 
 int PST_Point::validate(CubitBoolean print)

Modified: cgm/branches/cubit/geom/virtual/PartSurfFacetTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartSurfFacetTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartSurfFacetTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -569,10 +569,21 @@
 
     // Get real points on surface boundary
   mySurface->get_points(geom_points);
-  geom_points.last();
-  for (i = geom_points.size(); i--; )
-    if (!geom_points.step_and_get()->real_point())
-      geom_points.change_to(0);
+  for (i = 0; i < geom_points.size(); i++ )
+  {
+    if (!geom_points[i]->real_point())
+      geom_points[i] = 0;
+    // also process for hardpoints
+    if (geom_points[i]) 
+    {
+      PartitionCurve* curve = geom_points[i]->next_curve();
+      if ( curve->measure() < GEOMETRY_RESABS &&
+           curve->start_point() == curve->end_point() )
+      {
+        geom_points[i] = 0;
+      }
+    }
+  }
   geom_points.remove_all_with_value(0);
   
     // Group geometric points into boundary and interior sets
@@ -648,6 +659,13 @@
       PartitionPoint* start_point = coedge->start_point();
       PartitionPoint* end_point = coedge->end_point();
 
+      // Hardpoints (meeting all cases below) are a special
+      // case loop that should not be handled in the partitioning.
+      if (loop->num_coedges() == 1 && 
+          first_curve->measure() < GEOMETRY_RESABS &&
+          start_point == end_point)
+        break;
+
         // Get list of curves until next real vertex
       curve_set.clean_out();
       curve_set.append(first_curve);
@@ -665,9 +683,8 @@
         for (i = curve_set.size(); i--; )
         {
           GMem gmem;
-          int junk;
           PartitionCurve* c = curve_set.get_and_step();
-          c->get_geometry_query_engine()->get_graphics( c, junk, &gmem );
+          c->get_geometry_query_engine()->get_graphics( c, &gmem );
           GfxDebug::draw_polyline(gmem.point_list(), gmem.pointListCount, CUBIT_RED );
         }
         GfxDebug::flush();
@@ -1482,7 +1499,6 @@
         {
           if (!collapse_edge(new_point, prev_point, &old_facets))
           {
-            assert(0);
             return CUBIT_FAILURE;
           }
           std::swap(prev_point, new_point);
@@ -1576,7 +1592,6 @@
         {
           if (!collapse_edge(curve_point, prev_point, &old_facets))
           {
-            assert(0);
             return CUBIT_FAILURE;
           }
           std::swap(curve_point, prev_point);

Modified: cgm/branches/cubit/geom/virtual/PartitionEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartitionEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartitionEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -49,6 +49,7 @@
 #include "CompositeCurve.hpp"
 #include "PartitionLumpImprint.hpp"
 #include "GfxDebug.hpp"
+#include "BridgeManager.hpp"
 
 #include "CADefines.hpp"
 
@@ -64,8 +65,25 @@
                          std::vector<CubitFacetData*> &facet_list,
                          std::vector<CubitFacetEdgeData*> replacement_edges[3]);
 
-PartitionEngine::~PartitionEngine() {}
 
+PartitionEngine* PartitionEngine::instance_ = NULL; 
+
+
+PartitionEngine::~PartitionEngine()
+{
+  GeometryQueryTool::instance()->unregister_intermediate_engine(this);
+}
+
+void PartitionEngine::delete_instance()
+{
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}    
+
+
 //-------------------------------------------------------------------------
 // Purpose       : Constructor
 //
@@ -92,7 +110,12 @@
 //-------------------------------------------------------------------------
 PartitionEngine& PartitionEngine::instance()
 {
-  static PartitionEngine* instance_ = new PartitionEngine();
+  if( instance_ == NULL )
+  {
+    instance_ = new PartitionEngine();
+    assert( instance != NULL );
+  }
+  
   return *instance_;
 }
 
@@ -717,6 +740,11 @@
   return false;
 }
 
+bool PartitionEngine::is_composite(TopologyBridge *bridge)
+{
+  return false;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : Destroy a shell
 //
@@ -1629,6 +1657,12 @@
     loop2->remove( coedge2 );
     assert( loop2->first_coedge() == 0 );
     surf2->remove( loop2 );
+    if( loop1->num_coedges() == 0 )
+    {
+      surf1->remove( loop1 );
+      delete loop1;
+    }
+
     delete loop2;
   }
   
@@ -1943,14 +1977,32 @@
     {
       edges.clean_out();
       curve->get_facet_data( edges );
-      edges.reset();
-      edge = edges.get();
-      CubitPoint* start_pt = curve->start_point()->facet_point();
-      bool forward = edge->point(0) == start_pt;
-      assert( forward || edge->point(1) == start_pt );
-      if ( coe->sense() == CUBIT_REVERSED )
-        forward = !forward;
-      face = find_facet( edge, forward, new_surf );
+      if (edges.size() > 0) // normal facet
+      {
+        edges.reset();
+        edge = edges.get();
+        CubitPoint* start_pt = curve->start_point()->facet_point();
+        bool forward = edge->point(0) == start_pt;
+        assert( forward || edge->point(1) == start_pt );
+        if ( coe->sense() == CUBIT_REVERSED )
+          forward = !forward;
+        face = find_facet( edge, forward, new_surf );
+      }
+      else // this is a hardpoint there is a curve with no facets (length)
+           // and the start and end points are the same
+      {
+        Point* hardpoint = curve->start_point()->real_point();
+        if (hardpoint && curve->start_point() == curve->end_point() )
+        {
+          CubitVector hardpoint_coord = hardpoint->coordinates(); 
+          CubitVector new_closest, old_closest;
+          new_surf->closest_point_trimmed( hardpoint_coord, new_closest );
+          surface->closest_point_trimmed( hardpoint_coord,  old_closest );
+          // It appears that the new_surf is really the original surface
+          if ( new_closest.length_squared() > old_closest.length_squared() )
+            face = reinterpret_cast<CubitFacetData*>(1); // just set the point to non-zero (true)
+        }
+      }
     }
     
     if( face )
@@ -2285,8 +2337,17 @@
       
     if (count < polyline_pts.size())
     {
-      for (i = 0; i < polyline_pts.size(); i++)
-        *(segment_points[i]) = polyline_pts[i]->coordinates();
+      for( i = 0; i < polyline_pts.size(); i++ )
+      {
+        if( polyline_pts[i] )
+        {
+          *(segment_points[i]) = polyline_pts[i]->coordinates();
+        }
+        else
+        {
+          return CUBIT_FAILURE;
+        }
+      }
     }
   }
 
@@ -2951,10 +3012,12 @@
       }
       else
       {
-        assert(pt_index >= 0 && pt_index < cubit_points.size());
-        CubitPoint* pt = cubit_points.next( pt_index );
-        CubitPointData* ptd = dynamic_cast<CubitPointData*>(pt);
-        assert(!!ptd);
+        CubitPointData* ptd = NULL;
+        if(pt_index >= 0 && pt_index < cubit_points.size())
+        {
+          CubitPoint* pt = cubit_points.next( pt_index );
+          ptd = dynamic_cast<CubitPointData*>(pt);
+        }
         polyline_points.append(ptd);
       }
     }
@@ -3350,9 +3413,9 @@
 Lump* PartitionEngine::insert_surface( Surface* surface, Lump* lump)
 {
   GMem gmem;
-  int i, num_tri, num_pts, num_facets;
+  int i;
   CubitStatus status = surface->get_geometry_query_engine()->
-    get_graphics( surface, num_tri, num_pts, num_facets, &gmem );
+    get_graphics( surface, &gmem );
   
   if( !status )
   {
@@ -3360,8 +3423,9 @@
                 "get_graphics failed for surface.\n");
     return 0;
   }
+
+  int num_pts = gmem.pointListCount;
   
-  assert(gmem.pointListCount == num_pts && gmem.fListCount == num_facets );
   CubitPointData** ptarray = new CubitPointData*[num_pts];
   GPoint *p_itor = gmem.point_list();
   GPoint *p_end = p_itor + num_pts;
@@ -3371,7 +3435,7 @@
   
   DLIList<CubitFacetData*> facets;
   int* f_itor = gmem.facet_list();
-  int* f_end = f_itor + num_facets;
+  int* f_end = f_itor + gmem.fListCount;
   i = 0;
   for( ; f_itor < f_end ; f_itor += (1 + *f_itor) )
   {
@@ -4820,11 +4884,14 @@
                               polyline_edges, polyline_pts );
       while( positions.size() ) 
       {
-        assert(polyline_pts.size());
         CubitVector* position = positions.pop();
-        CubitPointData* point = polyline_pts.pop();
-        if (point->check_inverted_facets(*position))
-          point->set(*position);
+        if(s)
+        {
+   //       assert(polyline_pts.size());
+          CubitPointData* point = polyline_pts.pop();
+          if (point && point->check_inverted_facets(*position))
+            point->set(*position);
+        }
         delete position;
       }
       delete attrib;
@@ -6215,8 +6282,31 @@
 void PartitionEngine::clean_out_deactivated_geometry()
 {
 }
-void PartitionEngine::remove_modified(DLIList<TopologyBridge*>& geometry_list)
+void PartitionEngine::remove_modified(DLIList<Surface*> &all_surfs,
+    DLIList<Curve*> &all_curves, DLIList<Point*> &all_pts)
 {
 }
 
+void PartitionEngine::get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                                            DLIList<TopologyBridge*> &tbs )
+{
+  SubEntitySet* set = dynamic_cast<SubEntitySet*>(source_bridge->owner());
+  if( !set ) 
+    return;
+
+  DLIList<PartitionEntity*> entity_list;
+  set->get_sub_entities( entity_list );
+  DLIList<TopologyBridge*> temp_list;
+  CAST_LIST( entity_list, temp_list, TopologyBridge );
+
+  int i;
+  for( i=temp_list.size(); i--; )
+  {
+    if( temp_list.get()->bridge_manager() )
+      tbs.append( temp_list.get() );
+    temp_list.step();
+  }
   
+  return;
+}
+  

Modified: cgm/branches/cubit/geom/virtual/PartitionEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartitionEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartitionEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -65,14 +65,17 @@
 public:
   bool is_partition(TBOwner *bridge_owner);
   bool is_composite(TBOwner *bridge_owner);
+  bool is_composite(TopologyBridge *bridge);
   virtual void remove_imprint_attributes_after_modify
                                 ( DLIList<BodySM*> &old_sms,
                                 DLIList<BodySM*> &new_sms ){};
   virtual void push_imprint_attributes_before_modify
                      ( DLIList<BodySM*> &body_sms ){};
-    virtual void attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
+  virtual void push_named_attributes_to_curves_and_points
+                     ( DLIList<TopologyBridge*> &tb_list, const char *name_in ){};
+  virtual void attribute_after_imprinting( DLIList<TopologyBridge*> &new_tbs,
                                                     DLIList<TopologyBridge*> &att_tbs,
-                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<TopologyBridge*> &tb_list,
                                                     DLIList<Body*> &old_bodies){};
   virtual void remove_attributes_from_unmodifed_virtual(DLIList<TopologyBridge*> &bridges){};
 
@@ -82,6 +85,7 @@
 
   /** Get singleton instance */
   static PartitionEngine& instance();
+  static void delete_instance();
 
   int level() const { return SUBCOMP_PARTITION_LAYER; }
 
@@ -290,8 +294,11 @@
    
   void remove_attributes( DLIList<TopologyBridge*> &bridge_list );
     //remove Composite attributes off of topology bridges
-  void remove_modified(DLIList<TopologyBridge*>& geometry_list);
+  virtual void remove_modified(DLIList<Surface*> &all_surfs,
+    DLIList<Curve*> &all_curves, DLIList<Point*> &all_pts);
     
+  void get_tbs_with_bridge_manager_as_owner( TopologyBridge *source_bridge, 
+                                               DLIList<TopologyBridge*> &tbs );
 private:
 
   CubitStatus notify_transform_internal( TopologyBridge* bridge,
@@ -600,6 +607,8 @@
   /** Restore lump partitions from attributes */
   CubitStatus restore_from_attrib( Lump* partitioned_lump );
   
+  static PartitionEngine* instance_;
+
   /** Map for getting a SubEntitySet given its unique ID */  
   std::map<int,SubEntitySet*> uniqueIdMap;
 

Modified: cgm/branches/cubit/geom/virtual/PartitionLoop.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartitionLoop.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartitionLoop.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -20,6 +20,27 @@
 }
 
 //-------------------------------------------------------------------------
+// Purpose       : The purpose of this function is to see if a loop is an external
+//                  or internal loop of a surface.
+//
+// Special Notes : 
+//
+// Creator       : Jonathan Bugman
+//
+// Creation Date : 9/9/2008
+//-------------------------------------------------------------------------
+CubitBoolean PartitionLoop::is_external()
+{
+		  PRINT_ERROR( "This command is not supported with this engine.\n");
+          return CUBIT_FAILURE;
+}
+
+LoopType PartitionLoop::loop_type()
+{
+  return LOOP_TYPE_UNKNOWN;
+}
+
+//-------------------------------------------------------------------------
 // Purpose       : Destructor
 //
 // Special Notes : 

Modified: cgm/branches/cubit/geom/virtual/PartitionLoop.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartitionLoop.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartitionLoop.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -27,6 +27,14 @@
   PartitionSurface* get_surface() const;
   //void surface( PartitionSurface* );
   
+  virtual CubitBoolean is_external() ;
+    //R CubitBoolean
+    //R- CUBIT_TRUE/CUBIT_FALSE
+    //- Returns CUBIT_TRUE if the Loop is an external Loop and CUBIT_FALSE
+    //- otherwise.
+  
+  virtual LoopType loop_type() ;
+
   PartitionCoEdge* first_coedge( );
   PartitionCoEdge* next_coedge( PartitionCoEdge* after_this );
   PartitionCoEdge* prev_coedge( PartitionCoEdge* before_this );

Modified: cgm/branches/cubit/geom/virtual/PartitionSurface.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartitionSurface.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartitionSurface.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -173,7 +173,8 @@
       if( point && !point->num_adj_facets() ) {
         if ( TDVGFacetOwner::get(point) ) {
           ppoint = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(point));
-          ppoint->facet_point(0);
+          if( ppoint )
+            ppoint->facet_point(0);
         }
         delete point;
       }
@@ -320,6 +321,7 @@
     do 
     {
       PartitionCurve* curve = coedge->get_curve();
+
       list.append( curve->start_point() );
       list.append( curve->end_point() );
       
@@ -985,14 +987,11 @@
   //assert(are_marks_cleared());
 
   CubitStatus res = CUBIT_SUCCESS;
-  int num_triangles;
-  int num_points;
-  int num_facets;
   GMem gMem;
   
   // TODO - tolerance arguments are defaulted.  Do we need to specify?
   res = real_surf->get_geometry_query_engine()->
-    get_graphics(real_surf, num_triangles, num_points,  num_facets, &gMem);
+    get_graphics(real_surf, &gMem);
   if( !res )
     return CUBIT_FAILURE;
 
@@ -1003,7 +1002,6 @@
   if( old_count != gMem.pointListCount ) {
     PRINT_WARNING("Possible invalid facetting for surface.  "
                   "Coincident points found.\n");
-    num_points = gMem.pointListCount;
   }
 
   DLIList<CubitFacetData*> surf_facets;
@@ -1021,8 +1019,23 @@
   }
 
   int junk = 0;
-  for ( i = 0; i < gMem.fListCount; i += 4 ) {
-    if(gMem.facet_list()[i] != 3) {
+  bool fail_out = false;
+  CubitPoint *p1, *p2, *p3;
+  for ( i = 0; i < gMem.fListCount; i += 4 ) 
+  {
+    if(gMem.facet_list()[i] != 3)
+      fail_out = true;
+    else
+    {
+      p1 = point_array[ gMem.facet_list()[i+1] ];
+      p2 = point_array[ gMem.facet_list()[i+2] ];
+      p3 = point_array[ gMem.facet_list()[i+3] ];
+
+      if(p1 == p2 || p1 == p3 || p2 == p3)
+        fail_out = true;
+    }
+    if(fail_out == true)
+    {
       PRINT_ERROR("Non-triangular facet encountered.  Aborting.\n");
       while (surf_facets.size())
         delete surf_facets.pop();
@@ -1031,12 +1044,11 @@
       delete [] point_array;
       return CUBIT_FAILURE;
     }
-
-    CubitFacetData* facet = new CubitFacetData(
-                           point_array[ gMem.facet_list()[i+1] ],
-                           point_array[ gMem.facet_list()[i+2] ],
-                           point_array[ gMem.facet_list()[i+3] ], &junk );
-    surf_facets.append(facet);
+    else
+    {
+      CubitFacetData* facet = new CubitFacetData(p1, p2, p3, &junk );
+      surf_facets.append(facet);
+    }
   }
   
   delete [] point_array; 

Modified: cgm/branches/cubit/geom/virtual/PartitionTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/PartitionTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/PartitionTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -64,6 +64,7 @@
 #include "RefEntityFactory.hpp"
 #include "GeometryQueryTool.hpp"
 #include "MergeTool.hpp"
+#include "CubitUndo.hpp"
 
 #include "TDUPtr.hpp"
 #include <vector>
@@ -378,9 +379,8 @@
   DLIList<RefEdge*> new_edges;
   GMem edge_facets;
   
-  int numpts;
   Curve* curve = edge_ptr->get_curve_ptr();
-  if( ! curve->get_geometry_query_engine()->get_graphics( curve, numpts, &edge_facets ) )
+  if( ! curve->get_geometry_query_engine()->get_graphics( curve, &edge_facets ) )
   {
     return CUBIT_FAILURE;
   }
@@ -436,7 +436,7 @@
       for (j = 0; j < edge_list.size(); j++) 
       { 
         the_edge = edge_list.get_and_step();
-        the_edge->closest_point(pos, closest);
+        the_edge->closest_point_trimmed(pos, closest);
 
         if ( (pos - closest).length_squared() > TOL_SQR )
           continue;
@@ -522,6 +522,13 @@
     pos = *segments.step_and_get();
     }
   }
+  
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefFace*> tmp_face_list(1);
+    tmp_face_list.append( face_ptr );
+    CubitUndo::save_state_with_cubit_file( tmp_face_list );
+  }
 
   DLIList<TopologyBridge*> bridge_list;
   face_ptr->bridge_manager()->get_bridge_list( bridge_list );
@@ -548,7 +555,12 @@
     if (!new_surf && level_of_recursion == 0)
     {
       level_of_recursion++;
-      return insert_edge( face_ptr, segments, CUBIT_FALSE, new_edges, level_of_recursion);
+      RefFace *return_face = insert_edge( face_ptr, segments, CUBIT_FALSE, new_edges, level_of_recursion);
+      
+      if( CubitUndo::get_undo_enabled() && return_face == NULL ) 
+        CubitUndo::remove_last_undo();
+
+      return return_face; 
     }
 
     if(!new_surf)
@@ -556,6 +568,9 @@
       CompositeSurface* cs = dynamic_cast<CompositeSurface*>(old_surf);
       if(cs)
       {
+        Surface *tmp_srf = cs->get_surface(0);
+        GeometryQueryEngine *gqe = tmp_srf->get_geometry_query_engine();
+        double tmp_tol = gqe->get_sme_resabs_tolerance();
         DLIList<Curve*> hidden_curves;
         cs->get_hidden_curves(hidden_curves);
         int k;
@@ -568,12 +583,12 @@
           int curve_on_polyline = 1;
           cur_curve->get_param_range(min, max);
           cur_curve->position_from_u(min, start_vec);
-          if(!int_tool.point_on_polyline(start_vec, segments))
+          if(!int_tool.point_on_polyline(start_vec, segments, &tmp_tol))
             curve_on_polyline = 0;
           if(curve_on_polyline)
           {
             cur_curve->position_from_u(max, end_vec);
-            if(!int_tool.point_on_polyline(end_vec, segments))
+            if(!int_tool.point_on_polyline(end_vec, segments, &tmp_tol))
               curve_on_polyline = 0;
           }
           if(curve_on_polyline)
@@ -586,7 +601,7 @@
             for(n=0; n<num_mid_pts && curve_on_polyline; ++n)
             {
               cur_curve->position_from_u(cur_t, cur_vec);
-              if(!int_tool.point_on_polyline(cur_vec, segments))
+              if(!int_tool.point_on_polyline(cur_vec, segments, &tmp_tol))
                 curve_on_polyline = 0;
               cur_t += dt;
             }
@@ -695,12 +710,20 @@
   }
   
   if ( !removed_composite_curve && !new_edges.size() )
+  {
+    if( CubitUndo::get_undo_enabled() ) 
+      CubitUndo::remove_last_undo();
+
     return 0;
+  }
     
   DLIList<RefEntity*> ref_list;
   CAST_LIST_TO_PARENT(new_edges, ref_list);
   notify_partition( ref_list, face_ptr, result, face_ptr );
   
+  if( CubitUndo::get_undo_enabled() && status == CUBIT_FAILURE ) 
+    CubitUndo::remove_last_undo();
+
   return status ? result : 0;
 }
 
@@ -987,6 +1010,13 @@
   CAST_LIST(bridge_list, surface_list, Surface);
   assert(bridge_list.size() == surface_list.size());
   surface_list.reset();
+  
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefFace*> tmp_faces(1);
+    tmp_faces.append( face_ptr );
+    CubitUndo::save_state_with_cubit_file( tmp_faces );
+  }
 
     // For each position in the list
   positions.reset();
@@ -1082,6 +1112,10 @@
   if (new_vertices.size() > 1)
     new_vertices.uniquify_ordered();  
 
+
+  if( CubitUndo::get_undo_enabled() && new_points.size() == 0 )
+    CubitUndo::remove_last_undo();
+
   return rval; 
 }
 
@@ -1101,10 +1135,18 @@
   DLIList<CubitVector> positions(1);
   DLIList<RefVertex*> results(1);
   positions.append(position);
+  
+  if( CubitUndo::get_undo_enabled() )
+    CubitUndo::save_state_with_cubit_file( face_ptr );
+
   if (make_point_curves(face_ptr, positions, results) && results.size())
     return results.get();
   else
+  {
+    if( CubitUndo::get_undo_enabled() )
+      CubitUndo::remove_last_undo();
     return 0;
+  }
 }
 
 
@@ -1329,63 +1371,17 @@
   {
     RefEdge* edge = refedge_list.step_and_get();
     PartPTCurve* point_curve = dynamic_cast<PartPTCurve*>(edge->get_curve_ptr());
-    if ( !(point_curve || edge->marked() == 2) || !can_remove(edge) )
-      refedge_list.change_to(0);
-    else 
+    SegmentedCurve* seg_curve = dynamic_cast<SegmentedCurve*>(edge->get_curve_ptr());
+    if((point_curve || (seg_curve && edge->marked() == 2)) &&
+               can_remove(edge))
     {
-      // If we got to this point we think this is an "interior" edge that
-      // was introduced to partition a surface and we want to keep it
-      // in the list for unpartitioning.  However,
-      // we need to do one final check.  There are cases where
-      // two surfaces share an edge before either one is partitioned.
-      // Then both of them are partitioned in some way and so the
-      // original shared edge gets replaced with partition edges and
-      // partition coedges and when we get to this function it looks like
-      // an "interior" edge and that it should be unpartitioned 
-      // even though it was an original edge in the model and should not
-      // get unpartitioned.  True "interior" partition edges will have the
-      // same entitySet ptr for both of its coedges.  Check if this is the
-      // case and if it isn't mark the edge for removal from the list.
-      DLIList<CoEdge*> cur_coedges;
-      edge->get_co_edges(cur_coedges);
-      int coedge_size = cur_coedges.size();
-      Loop *loop_ptr;
-      RefFace *face_ptr;
-      Surface *surf_ptr;
-      PartitionSurface *part_surf_ptr;
-      SubEntitySet *common_sub_entity_set = NULL;
-      SubEntitySet *cur_sub_entity_set;
-      for(int g=0; g<coedge_size; g++)
-      {
-        CoEdge *cur_co_edge = cur_coedges.get_and_step();
-        if(g==0)
-        {
-          if((loop_ptr = cur_co_edge->get_loop_ptr()) &&
-            (face_ptr = loop_ptr->get_ref_face_ptr()) &&
-            (surf_ptr = face_ptr->get_surface_ptr()) &&
-            (part_surf_ptr = dynamic_cast<PartitionSurface*>(surf_ptr)))
-          {
-            common_sub_entity_set = &(part_surf_ptr->sub_entity_set());
-          }
-        }
-        else
-        {
-          cur_sub_entity_set = NULL;
-          if((loop_ptr = cur_co_edge->get_loop_ptr()) &&
-            (face_ptr = loop_ptr->get_ref_face_ptr()) &&
-            (surf_ptr = face_ptr->get_surface_ptr()) &&
-            (part_surf_ptr = dynamic_cast<PartitionSurface*>(surf_ptr)))
-          {
-            cur_sub_entity_set = &(part_surf_ptr->sub_entity_set());
-          }
-          if(cur_sub_entity_set != common_sub_entity_set)
-          {
-            refedge_list.change_to(0);
-            g = coedge_size;
-          }
-        }
-      }
+      // Try to remove this partition.
     }
+    else
+    {
+      // Don't try to remove this partition.
+      refedge_list.change_to(0);
+    }
     edge->marked(0);
   }
   refedge_list.remove_all_with_value(0);
@@ -1449,18 +1445,26 @@
   DLIList<CubitVector*> segments;
   GMem gmem;
   
+  if( CubitUndo::get_undo_enabled() )
+  {
+    DLIList<RefFace*> tmp_ref_face_list(1);
+    tmp_ref_face_list.append( face_to_split );
+    CubitUndo::save_state_with_cubit_file( tmp_ref_face_list );
+  }
+
   faces[0].append( face_to_split );
   for (i = 0; i < split_curves.size(); i++ )
   {
     Curve* curve = split_curves.next(i);
     GeometryQueryEngine* engine = curve->get_geometry_query_engine();
 
-    if (!engine->get_graphics( curve, numpts, &gmem ))
+    if (!engine->get_graphics( curve, &gmem ))
     {
       status = CUBIT_FAILURE;
       continue;
     }
-    assert( numpts == gmem.pointListCount);
+
+    numpts = gmem.pointListCount;
 /*
 This code causes a failure in virtual imprint because it compares
 against the number of graphics curve facets.  I think this is wrong but
@@ -1521,13 +1525,13 @@
       if (curve->bridge_sense() == CUBIT_REVERSED)
       {
         CubitVector* p1 = new CubitVector;
-        CubitStatus sta = curve->position_from_u( curve->end_param(), *p1 );
+        curve->position_from_u( curve->end_param(), *p1 );
         segments.append( p1 );
       }
       else
       {
         CubitVector* p1 = new CubitVector;
-        CubitStatus sta = curve->position_from_u( curve->start_param(), *p1 );
+        curve->position_from_u( curve->start_param(), *p1 );
         segments.append( p1 );
       }
     
@@ -1541,13 +1545,13 @@
       if (curve->bridge_sense() == CUBIT_REVERSED)
       {
         CubitVector* p1 = new CubitVector;
-        CubitStatus sta = curve->position_from_u( curve->start_param(), *p1 );
+        curve->position_from_u( curve->start_param(), *p1 );
         segments.append( p1 );
       }
       else
       {
         CubitVector* p1 = new CubitVector;
-        CubitStatus stat = curve->position_from_u( curve->end_param(), *p1 );
+        curve->position_from_u( curve->end_param(), *p1 );
         segments.append( p1 );
       }
     }
@@ -1567,8 +1571,13 @@
     while (segments.size())
       delete segments.pop();
   }
+
+  result_set = faces[split_curves.size()%2];
+
+  //surface might not have gotton split
+  if( CubitUndo::get_undo_enabled() && result_set.size() == 1)
+    CubitUndo::remove_last_undo();
   
-  result_set = faces[split_curves.size()%2];
   return status;
 }
 

Modified: cgm/branches/cubit/geom/virtual/RemoveBlends.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/RemoveBlends.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/RemoveBlends.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -51,7 +51,7 @@
 
    vec_lists.append( vec_list );
 
-   sst.calculate_split_curves(the_face, locations, vec_lists, curve_list);
+   sst.calculate_split_curves(the_face, vec_lists, curve_list);
 
    //int num_segs = 2; 
    //double fraction =.5;
@@ -76,6 +76,16 @@
    DLIList<RefFace*> result_faces;
    result = PartitionTool::instance()->
           partition_face_by_curves( the_face, curve_list, result_faces, CUBIT_TRUE, &new_edges );
+   // clean up curves
+   while (curve_list.size())
+   {
+     Curve* curve = curve_list.pop();
+     if (curve)
+     {
+       GeometryQueryEngine* gqe = curve->get_geometry_query_engine();
+       gqe->delete_solid_model_entities(curve);
+     }
+   }
    if( result == CUBIT_FAILURE )
    {
       PRINT_ERROR("Failed to partition surface %d into 2 distinct pieces\n", the_face->id());

Modified: cgm/branches/cubit/geom/virtual/SimplifyTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/SimplifyTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/SimplifyTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -43,6 +43,7 @@
                                            DLIList<RefEdge*> respect_edge_list,
                                            CubitBoolean respect_rounds,
                                            CubitBoolean respect_imprints,
+                                           CubitBoolean local_normals,
                                            CubitBoolean preview)
 {
     ref_volume_list.uniquify_unordered();
@@ -54,6 +55,7 @@
         respect_edge_list,
         respect_rounds,
         respect_imprints,
+        local_normals,
         preview);
 
     if(preview)
@@ -68,6 +70,7 @@
                                             DLIList<RefEdge*> respect_edge_list,
                                             CubitBoolean respect_rounds,
                                             CubitBoolean respect_imprints,
+                                            CubitBoolean local_normals,
                                             CubitBoolean preview)
 {
     CubitStatus status = CUBIT_FAILURE;
@@ -95,6 +98,7 @@
                 respect_edge_list,
                 respect_rounds,
                 respect_imprints,
+                local_normals,
                 preview);
         }
         ref_face_list -= ref_faces_in_volume;
@@ -106,12 +110,57 @@
     return CUBIT_SUCCESS;
 }
 
+CubitStatus SimplifyTool::simplify_curves(DLIList<RefEdge*> ref_edge_list, 
+                                            double angle_in,
+                                            DLIList<RefEdge*> respect_edge_list,
+                                            DLIList<RefVertex*> respect_vertex_list,
+                                            CubitBoolean respect_imprints,
+                                          CubitBoolean local_normals,
+                                            CubitBoolean preview)
+{
+    CubitStatus status = CUBIT_FAILURE;
+    ref_edge_list.uniquify_unordered();
+    while(ref_edge_list.size())
+    {
+        DLIList<RefEdge*> ref_edges_in_volume;
+        ref_edge_list.reset();
+        RefEdge* cur_edge = ref_edge_list.get_and_step();
+        RefVolume* cur_vol = cur_edge->ref_volume();
+        ref_edges_in_volume.append(cur_edge);
+        for(int i =1;i<ref_edge_list.size();i++)
+        {
+            RefEdge* edge = ref_edge_list.get_and_step();
+            if(edge->ref_volume() == cur_vol)
+                ref_edges_in_volume.append(edge);
+        }
+
+        if(ref_edges_in_volume.size()>1)
+        {
+            status = simplify_curves_in_volume(
+                ref_edges_in_volume,
+                angle_in,
+                respect_edge_list,
+                respect_vertex_list,
+                respect_imprints,
+                local_normals,
+                preview);
+        }
+        ref_edge_list -= ref_edges_in_volume;
+    }
+
+    if(preview)
+        GfxDebug::flush();
+
+    return CUBIT_SUCCESS;
+}
+
 CubitStatus SimplifyTool::simplify_volume(RefVolume* ref_volume, 
                                           double angle_in,
                                           DLIList<RefFace*> respect_face_list,
                                           DLIList<RefEdge*> respect_edge_list,
                                           CubitBoolean respect_rounds,
                                           CubitBoolean respect_imprints,
+                                          CubitBoolean local_normals,
                                           CubitBoolean preview)
 {
     DLIList<RefFace*> ref_face_list;
@@ -123,6 +172,7 @@
         respect_edge_list,
         respect_rounds,
         respect_imprints,
+        local_normals,
         preview);
 }
 
@@ -135,6 +185,7 @@
     DLIList<RefEdge*> respect_edge_list,
     CubitBoolean respect_rounds,
     CubitBoolean respect_imprints,
+    CubitBoolean local_normals,
     CubitBoolean preview)
 {
     if(ref_face_list.size()==0)
@@ -238,12 +289,22 @@
                     if( !ref_volumes.size() || ref_volumes.size()==1 )
                     {
                         // Only add the ref_face if it meets the feature angle criteria
-                        if(composite_surfaces(seed_ref_face,ref_face_ptr,angle_in))
+                      if(local_normals){
+                        if(composite_surfaces_test_at_curves(seed_ref_face,ref_face_ptr,angle_in))
                         {
                             ref_face_ptr->marked( CUBIT_TRUE );
                             seed_faces.append(ref_face_ptr);
                             composite_faces.append(ref_face_ptr);
                         }
+                      }
+                      else{
+                        if(composite_surfaces(seed_ref_face,ref_face_ptr,angle_in))
+                        {
+                          ref_face_ptr->marked( CUBIT_TRUE );
+                          seed_faces.append(ref_face_ptr);
+                          composite_faces.append(ref_face_ptr);
+                        }
+                      }
                     }
                 }
             }
@@ -256,7 +317,7 @@
         {
             DLIList<RefEdge*> result_edges;
             DLIList<RefFace*> result_faces;
-            CubitStatus new_face = CompositeTool::instance()->composite(
+            CompositeTool::instance()->composite(
                 composite_faces,
                 result_faces,
                 result_edges);
@@ -313,8 +374,210 @@
         PRINT_INFO("Simplified %d surfaces into %d surfaces\n",
             combined_face_count,
             new_face_count);
+	}
+
+	// make sure to set all of the surface markers to false
+	DLIList<RefFace*> marked_face_list;
+	ref_volume->ref_faces(marked_face_list);
+	for(int i =0;i<marked_face_list.size();i++)
+		marked_face_list[i]->marked(CUBIT_FALSE);
+
+    return CUBIT_SUCCESS;
+}
+
+CubitStatus SimplifyTool::simplify_curves_in_volume(
+    DLIList<RefEdge*> ref_edge_list, 
+    double angle_in,
+    DLIList<RefEdge*> respect_edge_list,
+    DLIList<RefVertex*> respect_vertex_list,
+    CubitBoolean respect_imprints,
+    CubitBoolean local_normals,
+    CubitBoolean preview)
+{
+  if(local_normals){
+    PRINT_WARNING("When simplifying curves, 'local_normals' is currently ignored.\n");
+  }
+  
+    if(ref_edge_list.size()==0)
+    {
+        PRINT_ERROR("No curves specified for simplification\n");
+        return CUBIT_FAILURE;
     }
+    else if(ref_edge_list.size() == 1)
+    {
+        PRINT_ERROR("Only one curve specified for simplification\n");
+        return CUBIT_FAILURE;
+    }
 
+    RefVolume* ref_volume = ref_edge_list.get()->ref_volume();
+    if (NULL == ref_volume)
+    {
+      PRINT_WARNING("Simplifying free curves is not supported.\n"); 
+      return CUBIT_FAILURE;
+    }
+
+    DLIList<RefEdge*> seed_edges;
+    DLIList<RefVertex*> preview_vertices;
+    DLIList<RefVertex*> preview_removed;
+
+    if(preview)
+        ref_volume->ref_vertices(preview_vertices);
+
+    int j,k;
+
+    int new_edge_count = 0;
+    int combined_edge_count = 0;
+    ProgressTool *prog_ptr = 0;
+    if(ref_edge_list.size() > 100 )
+    {
+        char title[200];
+        if(preview)
+            sprintf(title, "Previewing Volume %d",ref_volume->id());
+        else
+            sprintf(title, "Simplifying Curves in Volume %d",ref_volume->id());
+
+        prog_ptr = AppUtil::instance()->progress_tool();
+        assert(prog_ptr != NULL);
+        prog_ptr->start(0,100, title);
+    }
+    int start_edge_count = ref_edge_list.size();
+    while(ref_edge_list.size())
+    {
+        DLIList<RefEdge*> composite_edges;
+        seed_edges.append_unique(ref_edge_list.pop());
+
+        for ( j = ref_edge_list.size(); j--; )
+            ref_edge_list.get_and_step()->marked( CUBIT_FALSE );
+
+        while(seed_edges.size())
+        {
+            RefEdge *seed_ref_edge = seed_edges.pop();
+            seed_ref_edge->marked(CUBIT_TRUE);
+
+            composite_edges.append(seed_ref_edge);
+
+            // Get the vertices
+            DLIList<RefVertex*> ref_vertex_list;
+            seed_ref_edge->ref_vertices( ref_vertex_list );
+            RefVertex *ref_vertex_ptr;
+            RefEdge *ref_edge_ptr;
+            for( k = ref_vertex_list.size(); k--; )
+            {
+                ref_vertex_ptr = ref_vertex_list.get_and_step();
+
+                // Don't go propagate across surface splits if the user asks for it
+                GeometryFeatureTool* gft = GeometryFeatureTool::instance();
+                if( respect_imprints &&
+                    gft->feature_type(ref_vertex_ptr) == GeometryFeatureEngine::FEATURE_IMPRINT)
+                    continue;
+
+                // Don't cross a curve if we want it respected
+                if(respect_vertex_list.is_in_list(ref_vertex_ptr))
+                    continue;
+
+                DLIList<RefEdge*> attached_ref_edges;
+                ref_vertex_ptr->ref_edges( attached_ref_edges );
+
+                attached_ref_edges.remove(seed_ref_edge);
+                ref_edge_ptr = attached_ref_edges.size()!=0?attached_ref_edges.get():0;
+
+                // keep the face if we want it respected
+                if(attached_ref_edges.size() == 1 &&
+                    respect_edge_list.is_in_list(attached_ref_edges.get()))
+                    continue;
+
+                // Don't consider ref_faces that are already in the list
+                if( attached_ref_edges.size() == 1 &&
+                    !ref_edge_ptr->marked())
+                {
+                    DLIList<RefVolume*> ref_volumes;
+                    ref_edge_ptr->ref_volumes( ref_volumes );
+                    if( !ref_volumes.size() || ref_volumes.size()==1 )
+                    {
+                        // Only add the ref_face if it meets the feature angle criteria
+                        if(composite_curves(seed_ref_edge,ref_edge_ptr,angle_in))
+                        {
+                          ref_edge_ptr->marked( CUBIT_TRUE );
+                          seed_edges.append(ref_edge_ptr);
+                          composite_edges.append(ref_edge_ptr);
+                        }
+                    }
+                }
+            }
+        }
+        composite_edges.uniquify_unordered();
+        ref_edge_list -= composite_edges;
+
+        if(!preview &&
+            composite_edges.size()>1)
+        {
+            DLIList<RefVertex*> result_vertices;
+            DLIList<RefEdge*> result_edges;
+            CompositeTool::instance()->composite(
+                composite_edges,
+                result_edges,
+                &result_vertices);
+
+            combined_edge_count +=composite_edges.size();
+            for(int m = result_edges.size();m--;)
+                result_edges.get_and_step()->marked(CUBIT_TRUE);
+
+            new_edge_count+=result_edges.size();
+        }
+        else if(preview)
+        {
+            int edge_count = composite_edges.size();
+            for(int i =0;i<edge_count;i++)
+            {
+                RefEdge* cur_comp_edge = composite_edges[i];
+                DLIList<RefVertex*> refvertices; 
+                for(int j =0;j<edge_count;j++)
+                {
+                    if(i==j) continue;
+                    composite_edges[j]->ref_vertices(refvertices);
+                }
+
+                refvertices.uniquify_unordered();
+
+                DLIList<RefVertex*> temp_refvertices; 
+                cur_comp_edge->ref_vertices(temp_refvertices);
+                refvertices.intersect_unordered(temp_refvertices);
+                preview_removed+=refvertices;
+            }
+        }
+
+        if(prog_ptr)
+        {
+            double frac = 1.0-(double)ref_edge_list.size()/(double)start_edge_count;
+            prog_ptr->percent(frac);
+        }
+    }
+
+    if(prog_ptr)
+    {
+        prog_ptr->end();
+        prog_ptr = 0;
+    }
+
+    if(preview)
+    {
+        preview_vertices -=preview_removed;
+        for(int c = preview_vertices.size();c--;)
+            GfxDebug::draw_ref_vertex(preview_vertices.get_and_step(),7);
+    }
+    else if(combined_edge_count>new_edge_count)
+    {
+        PRINT_INFO("Simplified %d curves into %d curves\n",
+            combined_edge_count,
+            new_edge_count);
+	}
+
+	// make sure to set all of the surface markers to false
+	DLIList<RefEdge*> marked_edge_list;
+	ref_volume->ref_edges(marked_edge_list);
+	for(int i =0;i<marked_edge_list.size();i++)
+		marked_edge_list[i]->marked(CUBIT_FALSE);
+
     return CUBIT_SUCCESS;
 }
 
@@ -339,6 +602,37 @@
     return CUBIT_FALSE;
 }
 
+CubitBoolean SimplifyTool::composite_curves(
+    RefEdge* seed_ref_edge,
+    RefEdge* ref_edge_ptr,
+    double angle_in)
+{
+    double angle;
+    CubitVector pos, norm1, norm2;
+
+    // Only add the ref_face if it meets the feature angle criteria
+    RefVertex* shared_vert = seed_ref_edge->common_ref_vertex( ref_edge_ptr );
+
+    CubitVector seed_tangent;
+    seed_ref_edge->tangent( shared_vert->coordinates(), seed_tangent );
+    // make this vector point away from the vertex along the edge
+    if( shared_vert == seed_ref_edge->end_vertex() )
+      seed_tangent *= -1;
+
+    CubitVector edge2_tangent;
+    ref_edge_ptr->tangent( shared_vert->coordinates(), edge2_tangent );
+    // make this vector point into the vertex along the edge
+    if( shared_vert == ref_edge_ptr->start_vertex() )
+      edge2_tangent *= -1;
+
+    angle = seed_tangent.interior_angle( edge2_tangent );
+
+    if( angle < angle_in)
+        return CUBIT_TRUE;
+
+    return CUBIT_FALSE;
+}
+
 void SimplifyTool::process_rounds(RefVolume* ref_volume,
                                   double min_radius, 
                                   double max_radius)
@@ -396,26 +690,22 @@
                                       CubitVector &normal, 
                                       double &weight )
 {
-    int i;
-    int num_tris, num_pnts, num_facets;
     GMem g_mem;
     unsigned short norm_tol = 30;
     double dist_tol = -1.0;
 
     ref_face->get_geometry_query_engine()->
-        get_graphics(ref_face->get_surface_ptr(),num_tris, num_pnts, num_facets,
-        &g_mem, norm_tol, dist_tol );
+        get_graphics(ref_face->get_surface_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;
         ref_face->get_geometry_query_engine()->
-            get_graphics(ref_face->get_surface_ptr(),num_tris, num_pnts, num_facets,
-            &g_mem, norm_tol, dist_tol );
+            get_graphics(ref_face->get_surface_ptr(), &g_mem, norm_tol, dist_tol );
     }
 
-    if(num_tris < 1)
+    if(g_mem.fListCount < 1)
     {
         // Lets give up 
         PRINT_ERROR( "Unable to find average normal of a surface\n" );
@@ -432,7 +722,7 @@
     GPoint* plist = g_mem.point_list();
     int* facet_list = g_mem.facet_list();
     int c = 0;
-    for( i=0; i<num_tris; i++ )
+    for( ;c<g_mem.fListCount; )
     {
         p[0] = plist[facet_list[++c]];
         p[2] = plist[facet_list[++c]];
@@ -472,3 +762,91 @@
 
     return CUBIT_SUCCESS;
 }
+
+
+
+CubitBoolean SimplifyTool::composite_surfaces_test_at_curves(
+    RefFace* seed_ref_face,
+    RefFace* ref_face_ptr,
+    double angle_in)
+{
+  double angle;
+
+  if(!maximum_angle_deviation(seed_ref_face, ref_face_ptr, angle_in,  angle))
+    return CUBIT_FALSE;
+
+  if( angle < angle_in)
+    return CUBIT_TRUE;
+
+  return CUBIT_FALSE;
+}
+
+
+CubitBoolean SimplifyTool::maximum_angle_deviation(
+    RefFace* seed_ref_face,
+    RefFace* ref_face_ptr,
+    double angle_in,
+    double &angle_out)
+{
+  double max_angle = -360;
+  RefEdge* ref_edge = NULL;
+
+  double tol = angle_in / 2.0;
+    
+    
+  DLIList<RefEdge*> common_edges;
+  int num_edges = seed_ref_face->common_ref_edges(ref_face_ptr, common_edges);
+  if(num_edges != common_edges.size()){
+    PRINT_ERROR("Unexpected results.  List size incorrect.\n");
+    return CUBIT_FALSE;
+  }
+
+  int i, j;
+  for(i=0; i<num_edges; i++){
+      
+    GMem g_mem;
+    ref_edge = common_edges.get_and_step();
+      
+    ref_edge->get_geometry_query_engine()->
+        get_graphics(ref_edge->get_curve_ptr(), &g_mem, tol);
+
+    if(g_mem.pointListCount < 2)
+    {
+        // Decrease tolerance and try again (we can get this for small features)
+      tol /= 2.;
+        
+      ref_edge->get_geometry_query_engine()->
+          get_graphics(ref_edge->get_curve_ptr(), &g_mem, tol); 
+    }
+
+    if(g_mem.pointListCount < 2)
+    {
+        // Lets give up 
+      PRINT_ERROR( "Unable to find average normal of a curve\n" );
+      return CUBIT_FAILURE;
+    }
+
+    GPoint* plist = g_mem.point_list();
+      
+    for( j=0; j<g_mem.pointListCount; j++ )
+    {
+      CubitVector p1(plist[j].x, plist[j].y, plist[j].z);
+        
+
+      CubitVector norm1(ref_face_ptr->normal_at(p1));
+      CubitVector norm2(seed_ref_face->normal_at(p1));
+        
+      double angle = norm1.interior_angle( norm2 );
+      if(angle > max_angle)
+        max_angle=angle;
+    }
+  }
+  if(max_angle < -.000001){
+    return CUBIT_FAILURE;
+  }
+  angle_out = max_angle;
+    
+  return CUBIT_SUCCESS;
+}
+
+

Modified: cgm/branches/cubit/geom/virtual/SimplifyTool.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/SimplifyTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/SimplifyTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -22,6 +22,7 @@
 class RefVolume;
 class RefFace;
 class RefEdge;
+class RefVertex;
 template <class X> class DLIList;
 
 /// Tool to automatically simplify geometry
@@ -43,6 +44,7 @@
         DLIList<RefEdge*> respect_edge_list,
         CubitBoolean respect_rounds,
         CubitBoolean respect_imprints,
+        CubitBoolean local_normals,
         CubitBoolean preview);
 
     CubitStatus simplify_surfaces(
@@ -52,8 +54,32 @@
         DLIList<RefEdge*> respect_edge_list,
         CubitBoolean respect_rounds,
         CubitBoolean respect_imprints,
+        CubitBoolean local_normals,
         CubitBoolean preview);
 
+	CubitStatus simplify_curves(
+		DLIList<RefEdge*> ref_edge_list, 
+		double angle_in,
+		DLIList<RefEdge*> respect_edge_list,
+		DLIList<RefVertex*> respect_vertex_list,
+		CubitBoolean respect_imprints,
+                    CubitBoolean local_normals,
+		CubitBoolean preview);
+
+	CubitStatus simplify_curves_in_volume(
+		DLIList<RefEdge*> ref_edge_list, 
+		double angle_in,
+		DLIList<RefEdge*> respect_edge_list,
+		DLIList<RefVertex*> respect_vertex_list,
+		CubitBoolean respect_imprints,
+                    CubitBoolean local_normals,
+		CubitBoolean preview);
+
+	CubitBoolean composite_curves(
+		RefEdge* seed_ref_edge,
+		RefEdge* ref_edge_ptr,
+		double angle_in);
+
 private:
 
     CubitStatus simplify_volume(
@@ -63,6 +89,7 @@
         DLIList<RefEdge*> respect_edge_list,
         CubitBoolean respect_rounds,
         CubitBoolean respect_imprints,
+        CubitBoolean local_normals,
         CubitBoolean preview);
 
     CubitStatus simplify_surfaces_in_volume(
@@ -72,6 +99,7 @@
         DLIList<RefEdge*> respect_edge_list,
         CubitBoolean respect_rounds,
         CubitBoolean respect_imprints,
+        CubitBoolean local_normals,
         CubitBoolean preview);
 
     CubitBoolean composite_surfaces(
@@ -89,6 +117,19 @@
         CubitVector &normal, 
         double &weight );
 
+  
+  CubitBoolean composite_surfaces_test_at_curves(RefFace* seed_ref_face,
+                                                RefFace* ref_face_ptr,
+                                                double angle_in);
+  
+
+
+  CubitBoolean maximum_angle_deviation(RefFace* seed_ref_face,
+                                       RefFace* ref_face_ptr,
+                                       double angle_in,
+                                       double &angle_out);
+  
+
 };
 
 #endif

Added: cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.cpp	                        (rev 0)
+++ cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,252 @@
+#include "SplitCompositeSurfaceTool.hpp"
+#include "GeometryModifyTool.hpp"
+#include "RefFace.hpp"
+#include "CompositeSurface.hpp"
+#include "CompositeCurve.hpp"
+#include "Curve.hpp"
+#include "Point.hpp"
+#include "GeometryModifyEngine.hpp"
+#include "GeometryQueryTool.hpp"
+
+SplitCompositeSurfaceTool *SplitCompositeSurfaceTool::instance_ = NULL;
+
+SplitCompositeSurfaceTool *SplitCompositeSurfaceTool::instance()
+{
+  if (instance_ == NULL) 
+    instance_ = new SplitCompositeSurfaceTool();
+                                                                                
+  return instance_;
+}
+
+CubitStatus SplitCompositeSurfaceTool::split_surface(RefFace *ref_face_ptr,
+                                                     DLIList<CubitVector*> &locations,
+                                                     DLIList<DLIList<CubitVector*>*> &vec_lists,
+                                                     CubitBoolean preview_flg,
+                                                     CubitBoolean create_ref_edges_flg,
+                                                     CubitBoolean clear_previous_previews)
+{
+   get_additional_split_points(ref_face_ptr->get_surface_ptr(), vec_lists);
+
+   return GeometryModifyTool::instance()->split_surface(ref_face_ptr,
+      locations, vec_lists, preview_flg, create_ref_edges_flg, clear_previous_previews);
+}
+
+CubitStatus SplitCompositeSurfaceTool::split_surface(DLIList<RefFace*> &ref_face_list,
+                                                     DLIList<CubitVector*> &locations,
+                                                     DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
+                                                     CubitBoolean preview_flg,
+                                                     CubitBoolean create_ref_edges_flg,
+                                                     CubitBoolean clear_previous_previews)
+{
+   for( int jj = ref_face_list.size() ; jj > 0 ; jj--)
+   {
+      DLIList<DLIList<CubitVector*>*> vec_lists = *( list_of_vec_lists.get_and_step() );
+      
+      get_additional_split_points(ref_face_list.get_and_step()->get_surface_ptr(), vec_lists );
+   }
+
+   return GeometryModifyTool::instance()->split_surface(ref_face_list,
+      locations, list_of_vec_lists, preview_flg, create_ref_edges_flg, clear_previous_previews);
+}
+
+void SplitCompositeSurfaceTool::find_faces_for_pos(CubitVector &pos, DLIList<Surface*> surf_list,
+                        CubitPointContainment &containment,
+                        DLIList<Surface*> &out_list)
+{
+  int j;
+
+  for(j=surf_list.size(); j>0; j--)
+  {
+    Surface *surf_ptr = surf_list.get_and_step();
+    containment = surf_ptr->point_containment(pos);
+    if(containment == CUBIT_PNT_INSIDE || containment == CUBIT_PNT_BOUNDARY)
+      out_list.append_unique(surf_ptr);
+  }
+}
+
+void SplitCompositeSurfaceTool::get_additional_split_points(Surface *surf,
+                            DLIList<DLIList<CubitVector*>*> &vec_lists)
+{
+  int i, j, k, num_surfs;
+  DLIList<Surface*> surf_list;
+
+  CompositeSurface *cs = dynamic_cast<CompositeSurface*>(surf);
+  if(cs && (num_surfs = cs->num_surfs()) > 1)
+  {
+    for(i=0; i<num_surfs; i++)
+    {
+      Surface *surf = cs->get_surface(i);
+      if(surf)
+        surf_list.append(surf);
+    }
+
+    DLIList<Curve*> hidden_curves;
+    cs->get_hidden_curves(hidden_curves);
+
+    for(i=vec_lists.size(); i--;)
+    {
+      // Remove any hidden curves that already have points on them.
+      DLIList<Curve*> hidden_curves_without_pts = hidden_curves;
+      DLIList<CubitVector*> *vec_list = vec_lists.get_and_step();
+      for(j=vec_list->size(); j--;)
+      {
+        CubitVector *cur_vec = vec_list->get_and_step();
+        DLIList<Curve*> crvs_to_remove;
+        for(k=hidden_curves_without_pts.size(); k>0; k--)
+        {
+          Curve *crv = hidden_curves_without_pts.get_and_step();
+          CubitVector foot;
+          crv->closest_point_trimmed(*cur_vec, foot);
+          if(foot.about_equal(*cur_vec))
+            crvs_to_remove.append_unique(crv);
+        }
+        hidden_curves_without_pts -= crvs_to_remove;
+      }
+
+      // Now we should only have hidden curves with no points on them.
+      if(hidden_curves_without_pts.size() > 0)
+      {
+        vec_list->reset();
+        CubitVector *cur_vec = vec_list->get();
+        CubitVector *last_vec = vec_list->prev();
+        while(cur_vec != last_vec)
+        {
+          vec_list->move_to(cur_vec);
+          CubitVector *next_vec = vec_list->next();
+          DLIList<CubitVector*> tmp_list;
+          DLIList<double> vals;
+          tmp_list.append(cur_vec);
+          tmp_list.append(next_vec);
+          vals.append(0.0);
+          vals.append(1.0);
+          Curve *hidden_curve = hidden_curves_without_pts.get();
+          CompositeCurve *cc = dynamic_cast<CompositeCurve*>(hidden_curve);
+          if(cc)
+            hidden_curve = cc->get_curve(0);
+          GeometryModifyEngine *gme = GeometryModifyTool::instance()->
+            get_engine(hidden_curve);
+          Point *pt1 = gme->make_Point(*cur_vec);
+          Point *pt2 = gme->make_Point(*last_vec);
+          Curve *tmp_crv = gme->make_Curve(STRAIGHT_CURVE_TYPE, pt1, pt2, NULL, CUBIT_FORWARD);
+          if(tmp_crv)
+          {
+            double arc_length = tmp_crv->get_arc_length();
+            for(j=hidden_curves_without_pts.size(); j--;)
+            {
+              CubitVector pos1, pos2;
+              double dist;
+              Curve *crv = hidden_curves_without_pts.get_and_step();
+              GeometryQueryTool::instance()->entity_entity_distance(crv, tmp_crv, pos1, pos2, dist);
+              CubitVector v1 = *cur_vec - pos1;
+              CubitVector v2 = *last_vec - pos1;
+              v1.normalize();
+              v2.normalize();
+              if(v1 % v2 < .3)
+              {
+                CubitVector *new_vec = new CubitVector(pos1);
+                v1 = (pt1->coordinates() - pos2);
+                double percent = v1.length()/arc_length;
+                if(percent > 1.0)
+                  percent = 1.0;
+                if(percent < 0.0)
+                  percent = 0.0;
+                tmp_list.reset();
+                vals.reset();
+                while(percent > vals.get())
+                {
+                  vals.step();
+                  tmp_list.step();
+                }
+                vals.back();
+                tmp_list.back();
+                vals.insert(percent);
+                tmp_list.insert(new_vec);
+              }
+            }
+            delete tmp_crv;
+          }
+          delete pt1;
+          delete pt2;
+          if(tmp_list.size() > 2)
+          {
+            vec_list->move_to(cur_vec);
+            tmp_list.reset();
+            tmp_list.step();
+            for(j=tmp_list.size(); j>2; j--)
+            {
+              vec_list->insert(tmp_list.get());
+              tmp_list.step();
+            }
+          }
+          cur_vec = next_vec;
+        }
+      }
+    }
+  }
+}
+
+// Passed in direction should be normalized by calling function.
+void SplitCompositeSurfaceTool::find_face_with_non_zero_param_dir(DLIList<Surface*> &surf_list, 
+                                        CubitVector &dir,
+                                        CubitVector &pos,
+                                        Surface *&ret_surf,
+                                        double &du, double &dv,
+                                        double &step)
+{
+  int i;
+  ret_surf = NULL;
+  for(i=surf_list.size(); i>0 && !ret_surf; i--)
+  {
+    Surface *surf = surf_list.get_and_step();
+    CubitPointContainment cont = surf->point_containment(pos);
+    if(cont == CUBIT_PNT_INSIDE)
+    {
+      double ulow, uhigh, vlow, vhigh;
+      surf->param_dir(dir, pos, du, dv);
+      surf->get_param_range_U(ulow, uhigh);
+      surf->get_param_range_V(vlow, vhigh);
+      double u_len = fabs(ulow-uhigh);
+      double v_len = fabs(vlow-vhigh);
+      double par_tol;
+      if(u_len > v_len)
+        par_tol = v_len/100.0;
+      else
+        par_tol = u_len/100.0;
+      par_tol *= par_tol;
+      double len = du*du + dv*dv;
+      if(len > par_tol)
+      {
+        step = sqrt(u_len*u_len + v_len*v_len)/20.0;
+        ret_surf = surf;
+      }
+    }
+    else if(cont == CUBIT_PNT_BOUNDARY)
+    {
+      double ulow, uhigh, vlow, vhigh;
+      surf->param_dir(dir, pos, du, dv);
+      surf->get_param_range_U(ulow, uhigh);
+      surf->get_param_range_V(vlow, vhigh);
+      double u_len = fabs(ulow-uhigh);
+      double v_len = fabs(vlow-vhigh);
+      double par_tol;
+      if(u_len > v_len)
+        par_tol = v_len/100.0;
+      else
+        par_tol = u_len/100.0;
+      par_tol *= par_tol;
+      double len = du*du + dv*dv;
+      if(len > par_tol)
+      {
+        double u, v;
+        surf->u_v_from_position(pos, u, v);
+        CubitVector new_pos = surf->position_from_u_v(u+du, v+dv);
+        CubitPointContainment new_cont = surf->point_containment(new_pos);
+        if(new_cont == CUBIT_PNT_INSIDE)
+        {
+          step = sqrt(u_len*u_len + v_len*v_len)/20.0;
+          ret_surf = surf;
+        }
+      }
+    }
+  }
+}

Added: cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.hpp	                        (rev 0)
+++ cgm/branches/cubit/geom/virtual/SplitCompositeSurfaceTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,49 @@
+#ifndef SPLITCOMPOSITESURFACETOOL_HPP
+#define SPLITCOMPOSITESURFACETOOL_HPP
+
+#include "CubitDefines.h"
+#include "Surface.hpp"
+
+class Surface;
+class RefFace;
+class CubitVector;
+template<class X> class DLIList;
+
+   
+class SplitCompositeSurfaceTool
+{
+  public:
+    static SplitCompositeSurfaceTool *instance();
+    CubitStatus split_surface( RefFace *ref_face_ptr,
+                             DLIList<CubitVector*> &locations,
+                             DLIList<DLIList<CubitVector*>*> &vec_lists,
+                             CubitBoolean preview_flg = CUBIT_FALSE,
+                             CubitBoolean create_ref_edges_flg = CUBIT_FALSE,
+                             CubitBoolean clear_previous_previews = CUBIT_TRUE );
+
+     CubitStatus split_surface( DLIList<RefFace*> &ref_face_list,
+                                DLIList<CubitVector*> &locations,
+                                DLIList<DLIList<DLIList<CubitVector*>*>*> &list_of_vec_lists,
+                                CubitBoolean preview_flg = CUBIT_FALSE,
+                                CubitBoolean create_ref_edges_flg =CUBIT_FALSE,
+                                CubitBoolean clear_previous_previews = CUBIT_TRUE );
+
+  private:
+                                                                                
+    void find_faces_for_pos(CubitVector &pos, DLIList<Surface*> surf_list,
+                        CubitPointContainment &containment,
+                        DLIList<Surface*> &out_list);
+    void get_additional_split_points(Surface *surf,
+                            DLIList<DLIList<CubitVector*>*> &vec_lists);
+    static SplitCompositeSurfaceTool *instance_;
+    void find_face_with_non_zero_param_dir(DLIList<Surface*> &surf_list, 
+                                        CubitVector &dir,
+                                        CubitVector &pos,
+                                        Surface *&ret_surf,
+                                        double &du, double &dv,
+                                        double &step);
+
+};
+
+#endif
+

Modified: cgm/branches/cubit/geom/virtual/SubCurve.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/SubCurve.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/SubCurve.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -435,9 +435,9 @@
     return CUBIT_SUCCESS;
   }
 
-  int i, junk;
+  int i;
   if( !real_curve()->get_geometry_query_engine()->
-    get_graphics( real_curve(), junk, &result ) )
+    get_graphics( real_curve(), &result ) )
     return CUBIT_FAILURE;
 
   if (0 == result.pointListCount)

Modified: cgm/branches/cubit/geom/virtual/SubSurface.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/SubSurface.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/SubSurface.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -35,8 +35,8 @@
   new SubEntitySet( real_surf, this );
 
   // ensure that the sense is the same on both entities
-  if( real_surf->bridge_sense() != this->bridge_sense() )
-    reverse_bridge_sense();
+  //if( real_surf->bridge_sense() != this->bridge_sense() )
+  //  reverse_bridge_sense();
 
   geometry_sense = CUBIT_FORWARD;
 }

Modified: cgm/branches/cubit/geom/virtual/VGLoopTool.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/VGLoopTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/VGLoopTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -681,10 +681,9 @@
   list.resize(0);
   
   do {
-    int num_pts;
     coedge->get_curve()->get_geometry_query_engine()->
-      get_graphics( coedge->get_curve(), num_pts, &gmem );
-    assert( num_pts == gmem.pointListCount );
+      get_graphics( coedge->get_curve(), &gmem );
+    int num_pts = gmem.pointListCount;
     if ( num_pts > 1 ) {
     
       int start = list.size();

Modified: cgm/branches/cubit/geom/virtual/VirtualQueryEngine.cpp
===================================================================
--- cgm/branches/cubit/geom/virtual/VirtualQueryEngine.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/VirtualQueryEngine.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -72,6 +72,9 @@
 #include "CAPartitionVG.hpp"
 #include "CAVirtualVG.hpp"
 
+#include "HiddenEntitySet.hpp"
+#include "SubEntitySet.hpp"
+
 // ********** END CUBIT INCLUDES           **********
 
 // ********** BEGIN STATIC DECLARATIONS    **********
@@ -109,10 +112,23 @@
 //		PRINT_WARNING("Not all virtual geometry has been removed.  "
 //		              "This is a bug (memory leak).  Please report it.\n");
 //	assert( virtual_entity_list_.size() == 0 );
+
+  PartitionEngine::delete_instance();
+  CompositeEngine::delete_instance();
+
   instance_ = NULL;
 }
 
+void VirtualQueryEngine::delete_instance()
+{
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}    
 
+
 //-------------------------------------------------------------------------
 // Purpose	 : Return a description of this ModelingEngine
 //
@@ -170,8 +186,7 @@
 // Creation Date : 
 //-------------------------------------------------------------------------
 CubitStatus VirtualQueryEngine::get_graphics(
-  Surface* surf_ptr, int& number_triangles,
-  int& number_points, int& number_facets,
+  Surface* surf_ptr, 
   GMem* gMem,
   unsigned short normal_tol,
   double dist_tol,
@@ -181,24 +196,19 @@
   PartitionSurface* ps_ptr = CAST_TO(surf_ptr, PartitionSurface );
   if( cs_ptr != NULL )
   {
-    return get_composite_surface_facetting( cs_ptr,
-                                            number_triangles, number_points,
-                                            number_facets, gMem,
+    return get_composite_surface_facetting( cs_ptr, gMem,
                                             normal_tol, dist_tol, max_edge_length );
   }
   else if( ps_ptr != NULL )
   {
-    return get_partition_surface_facetting( ps_ptr,
-                                            number_triangles, number_points,
-                                            number_facets, gMem,
+    return get_partition_surface_facetting( ps_ptr, gMem,
                                             normal_tol, dist_tol, max_edge_length );
   }
   else
   {
     PRINT_INFO("VirtualQueryEngine::get_graphics_facets"
-               "( s%p, %d, %d, %d, %p, %d, %f ) = CUBIT_FAILURE\n",
-               surf_ptr, number_triangles, 
-               number_points, number_facets, gMem, normal_tol, dist_tol);
+               "( s%p, %p, %d, %f ) = CUBIT_FAILURE\n",
+               surf_ptr, gMem, normal_tol, dist_tol);
     return CUBIT_FAILURE;
   }
 }
@@ -214,7 +224,6 @@
 // Creation Date : 10/10/97
 //-----------------------------------------------------------------------
 CubitStatus VirtualQueryEngine::get_graphics( Curve* curve_ptr,
-                                                 int& num_points,
                                                  GMem* gMem,
                                                  double ) const
 {
@@ -225,11 +234,11 @@
   
   if( ccurve != NULL )
   {
-    result = get_composite_curve_facetting( ccurve, num_points, gMem );
+    result = get_composite_curve_facetting( ccurve, gMem );
   }
   else if( pcurve != NULL )
   {
-    result = get_partition_curve_facetting( pcurve, num_points, gMem );
+    result = get_partition_curve_facetting( pcurve, gMem );
   }
   else
   {
@@ -278,13 +287,11 @@
 //-----------------------------------------------------------------------
 CubitStatus VirtualQueryEngine::get_composite_curve_facetting(
   CompositeCurve* ccurve_ptr,
-  int& num_points,
   GMem* gMem ) const
 {
     // Just return if gMem is NULL
   if (gMem == NULL)
   {
-    num_points = 0;
     return CUBIT_SUCCESS;
   }
   
@@ -304,11 +311,12 @@
       curve_ptr->get_geometry_query_engine();
     
       // Get the GME to facet the curve
-    int this_point_count = 0;
     CubitStatus current_status = 
-      GQE_ptr->get_graphics (curve_ptr, this_point_count, &current_gmem);
+      GQE_ptr->get_graphics (curve_ptr, &current_gmem);
     if( current_status == CUBIT_FAILURE )
       return CUBIT_FAILURE;
+    
+    int this_point_count = current_gmem.pointListCount;
       
     // Make sure the passed in gmem is big enough
     gMem->allocate_more_polylines(this_point_count-1);
@@ -355,7 +363,6 @@
     gMem->pointListCount = point_count;
   }
   
-  num_points = point_count;
   gMem->pointListCount = point_count;
   return CUBIT_SUCCESS;
 }
@@ -374,11 +381,10 @@
 // Creation Date : 10/10/97
 //-----------------------------------------------------------------------
 CubitStatus VirtualQueryEngine::get_partition_curve_facetting(
-  PartitionCurve* pcurve_ptr, int& num_steps, GMem* gMem ) const
+  PartitionCurve* pcurve_ptr, GMem* gMem ) const
 {
   assert( gMem != NULL );
   CubitStatus result = pcurve_ptr->get_graphics( *gMem );
-  num_steps = gMem->pointListCount;
   return result;
 }
 
@@ -394,9 +400,6 @@
 //-------------------------------------------------------------------------
 CubitStatus VirtualQueryEngine::get_composite_surface_facetting(
   CompositeSurface* surf_ptr,
-  int& number_triangles,
-  int& number_points,
-  int& number_facets,
   GMem* gMem,
   unsigned short normal_tol,
   double dist_tol,
@@ -407,20 +410,17 @@
     
   if (surf_ptr->get_graphics(*gMem))
   {
-    number_triangles = gMem->fListCount / 4;
-    number_points = gMem->pointListCount;
-    number_facets = gMem->fListCount;
     return CUBIT_SUCCESS;
   }
     
-  number_triangles = 0;
-  number_points = 0;
-  number_facets = 0;
 
     // Get the underlying Surfaces
   GeometryQueryEngine* gqe_ptr;
   GMem *gMem_list = new GMem[ surf_ptr->num_surfs() ];
   
+  int total_number_points = 0;
+  int total_number_facets = 0;
+  
     // Get the facets of each Surface
   int i;
   for(i = 0; i < surf_ptr->num_surfs(); i++)
@@ -431,21 +431,19 @@
     gqe_ptr = surface_ptr->get_geometry_query_engine();
     
     tri_count = pt_count = facet_count = 0;
-    gqe_ptr->get_graphics( surface_ptr, tri_count, 
-                                  pt_count, facet_count, &(gMem_list[i]),
+    gqe_ptr->get_graphics( surface_ptr, &(gMem_list[i]),
                                   normal_tol, dist_tol, longest_edge );
     
-    number_triangles += tri_count;
-    number_facets += gMem_list[i].fListCount;
-    number_points += gMem_list[i].pointListCount;
+    total_number_facets += gMem_list[i].fListCount;
+    total_number_points += gMem_list[i].pointListCount;
   }
   
   int point_offset = 0;
   int face_offset = 0;
-  gMem->replace_point_list(new GPoint[number_points],
-                           number_points, number_points);
-  gMem->replace_facet_list(new int[number_facets],
-                           number_facets, number_facets);
+  gMem->replace_point_list(new GPoint[total_number_points],
+                           total_number_points, total_number_points);
+  gMem->replace_facet_list(new int[total_number_facets],
+                           total_number_facets, total_number_facets);
   
   for( i = 0; i < surf_ptr->num_surfs(); i++ )
   {
@@ -480,7 +478,6 @@
   }
   
   gMem->consolidate_points(10*GEOMETRY_RESABS);
-  number_points = gMem->pointListCount;
 //     // Debug!!!
 //   int q;
 //   for (q = 0; q < bte_list.size(); q++)
@@ -533,9 +530,6 @@
 //-------------------------------------------------------------------------
 CubitStatus VirtualQueryEngine::get_partition_surface_facetting(
   PartitionSurface* surf_ptr,
-  int& num_triangles,
-  int& num_points,
-  int& num_facets,
   GMem* gMem,
   unsigned short ,
   double,
@@ -576,11 +570,6 @@
   gMem->fListCount = surf_facets.size() * 4;
   gMem->pointListCount = surf_points.size();
     
-    // set return values and if gMem is NULL return
-  num_triangles = surf_facets.size();
-  num_facets = gMem->fListCount;
-  num_points = gMem->pointListCount;
-  
     // put points in GMem and mark each point with
     // its index in the array
   surf_points.reset();
@@ -1019,6 +1008,55 @@
   return CUBIT_FALSE;
 }
 
+CubitBoolean VirtualQueryEngine::is_partition( RefEntity *ref_entity )
+{
+  RefEdge *ref_edge = CAST_TO( ref_entity, RefEdge );
+
+  if( ref_edge )
+  {
+    Curve *curve_ptr = ref_edge->get_curve_ptr();
+    PartitionCurve *part_curve = CAST_TO(curve_ptr, PartitionCurve);
+
+    if( part_curve )
+      return CUBIT_TRUE;
+  }
+
+  return CUBIT_FALSE;
+}
+
+CubitStatus VirtualQueryEngine::get_sister_partitions( RefEntity *ref_entity,
+                                                       DLIList<RefEntity*> &sisters)
+{
+  RefEdge *ref_edge = CAST_TO( ref_entity, RefEdge );
+
+  if( ref_edge )
+  {
+    Curve *curve_ptr = ref_edge->get_curve_ptr();
+    PartitionCurve *part_curve = CAST_TO(curve_ptr, PartitionCurve);
+
+    if( part_curve )
+    {
+      DLIList<TopologyBridge*> tb_list;
+      part_curve->sub_entity_set().get_owners( tb_list );
+      
+      int k;
+      for( k=tb_list.size(); k--; )
+      {
+        TopologyBridge *tmp_bridge = tb_list.get_and_step();
+        TopologyEntity *te = tmp_bridge->topology_entity();
+        if( te )
+        {
+          RefEntity *sister = CAST_TO(te, RefEntity ); 
+          if( sister )
+            sisters.append( sister );
+        }
+      }
+    }
+  }
+
+  return CUBIT_SUCCESS;
+}
+
 //-------------------------------------------------------------------------
 // Purpose	 : Sort a DLList of RefEdges to be used in the construction
 //		   of a CompositeCurve.
@@ -1190,6 +1228,28 @@
    return CUBIT_FAILURE;
 }
 
+int VirtualQueryEngine::curve_is_on_ignored_surface(Curve *curve_in, Surface *surf) 
+{ 
+  int i, ret = 0;
+
+  CompositeSurface *cs = dynamic_cast<CompositeSurface*>(surf);
+  if(cs && curve_in)
+  {
+    DLIList<Surface*> ignored_surfs;
+    cs->get_ignored_surfs(ignored_surfs);
+    for(i=ignored_surfs.size(); i>0 && !ret; i--)
+    {
+      Surface *surf = ignored_surfs.get_and_step();
+      DLIList<Curve*> crvs;
+      surf->curves(crvs);
+      if(crvs.is_in_list(curve_in))
+        ret = 1;
+    }
+  }
+
+  return ret;
+}
+
 //-------------------------------------------------------------------------
 // Purpose       : This function get underlying curves for virtual curves
 //
@@ -1261,6 +1321,77 @@
    return CUBIT_SUCCESS;
 }
 
+CubitStatus VirtualQueryEngine::get_underlying_bridges(TopologyBridge* bridge_ptr,
+                                        DLIList<TopologyBridge*>& bridge_list)
+{
+   assert (bridge_ptr);
+   CompositeSurface *comp_surf = CAST_TO(bridge_ptr, CompositeSurface);
+   PartitionSurface *part_surf = CAST_TO(bridge_ptr, PartitionSurface);
+   CompositeCurve *comp_curve = CAST_TO(bridge_ptr, CompositeCurve);
+   PartitionCurve *part_curve = CAST_TO(bridge_ptr, PartitionCurve);
+   CompositePoint *comp_point = CAST_TO(bridge_ptr, CompositePoint);
+   PartitionPoint *part_point = CAST_TO(bridge_ptr, PartitionPoint);
+
+   if ( comp_surf )
+   {
+     int i;
+     for (i = 0; i < comp_surf->num_surfs(); i ++)
+     {
+       part_surf = CAST_TO(comp_surf->get_surface(i), PartitionSurface);
+       if (!part_surf)
+         bridge_list.append_unique(CAST_TO(comp_surf->get_surface(i),
+                                  TopologyBridge));
+       else
+       {
+         if(dynamic_cast<Surface*>(part_surf->partitioned_entity()))
+         {
+           bridge_list.append_unique(CAST_TO(part_surf->partitioned_entity(),
+                                    TopologyBridge));
+         }
+       }
+     }
+   }
+   else if ( part_surf )
+     bridge_list.append(CAST_TO(part_surf->partitioned_entity(),
+                       TopologyBridge));
+   else if ( comp_curve )
+   {
+     int i;
+     for (i = 0; i < comp_curve->num_curves(); i ++)
+     {
+       part_curve = CAST_TO(comp_curve->get_curve(i), PartitionCurve);
+       if (!part_curve)
+         bridge_list.append_unique(CAST_TO(comp_curve->get_curve(i),
+                                  TopologyBridge));
+       else
+       {
+         if(dynamic_cast<Curve*>(part_curve->partitioned_entity()))
+         {
+           bridge_list.append_unique(CAST_TO(part_curve->partitioned_entity(),
+                                    TopologyBridge));
+         }
+       }
+     }
+   }
+   else if ( part_curve )
+     bridge_list.append(CAST_TO(part_curve->partitioned_entity(),
+                       TopologyBridge));
+   else if ( part_point )
+   {
+     TopologyBridge *tb_point = part_point->real_point();
+     if( tb_point )
+       bridge_list.append( tb_point ); 
+   }
+   else if ( comp_point )
+   {
+     TopologyBridge *tb_point = comp_point->get_point();
+     if( tb_point )
+       bridge_list.append( tb_point ); 
+   }
+   
+   return CUBIT_SUCCESS;
+}
+
 //================================================================================
 // Description: Find extrema position on an entity list
 // Author     : 
@@ -1393,7 +1524,7 @@
       for(j=geometry_entities_2.size(); j--;)
       {
         GeometryEntity *ge2 = geometry_entities_2.get_and_step();
-        GeometryQueryEngine *gqe2 = gqes_2.get_and_step();
+        //GeometryQueryEngine *gqe2 = gqes_2.get_and_step();
 
         CubitVector cur_pos1, cur_pos2;
         double cur_distance;
@@ -1654,16 +1785,163 @@
   return CUBIT_FAILURE;
 }
 
-CubitStatus VirtualQueryEngine::fire_ray(BodySM *,
-                                            const CubitVector &,
-                                            const CubitVector &,
-                                            DLIList<double>& ,
-                                            DLIList<GeometryEntity*> *) const
+CubitStatus VirtualQueryEngine::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_ptr) const
 {
-  PRINT_INFO("VirtualQueryEngine::fire_ray\n");
-  
-  default_error_message( "fire_ray()");
-  return CUBIT_FAILURE;
+  // Note: for now assume we will only get curves or surfaces
+
+  int i;
+  int prev_num_hits = ray_params.size();
+  GeometryQueryEngine *gqe = 0;
+  TopologyBridge *bridge_ptr;
+
+  // This is only needed because this function is "const"
+  VirtualQueryEngine *vqe = VirtualQueryEngine::instance();
+
+  at_entity_list.reset();
+  for( i=at_entity_list.size(); i--; )
+  {
+	prev_num_hits = ray_params.size();
+    bridge_ptr = at_entity_list.get_and_step();
+
+    gqe = bridge_ptr->get_geometry_query_engine();
+    if( !gqe )
+    {
+      PRINT_ERROR( "Unable to find geometry engine associated with an entity!\n" );
+      return CUBIT_FAILURE;
+    }
+
+    Curve *curve_ptr = CAST_TO( bridge_ptr, Curve );
+    if( curve_ptr )
+    {
+      DLIList<TopologyBridge*> tb_curve_list;
+      vqe->get_underlying_curves( curve_ptr, tb_curve_list );
+
+      if( tb_curve_list.size() > 0 )
+      {
+        gqe = tb_curve_list.get()->get_geometry_query_engine();
+
+        gqe->fire_ray( origin, direction, tb_curve_list, ray_params, max_hits,
+          ray_radius, hit_entity_list_ptr );
+
+		// If curve_ptr is a PartitionCurve, it could be smaller than the underlying curve.
+		// This means we have to check to make sure any hit points lie inside the curve. Remove if they don't.
+		if (CAST_TO(curve_ptr, PartitionCurve))
+		{
+			// start iterating at the first new ray_param
+			ray_params.reset();
+			ray_params.step(prev_num_hits);
+			hit_entity_list_ptr->reset();
+			hit_entity_list_ptr->step(prev_num_hits);
+			
+			int j;
+			for (j=prev_num_hits; j<ray_params.size(); j++)
+			{
+				CubitVector *loc_ptr;
+				double param = ray_params.get();
+
+				loc_ptr = new CubitVector;
+				origin.next_point( direction, param, *loc_ptr );
+				
+				CubitPointContainment containment = CUBIT_PNT_UNKNOWN;
+				containment = curve_ptr->point_containment(*loc_ptr);
+				if ( (containment != CUBIT_PNT_ON) && (containment != CUBIT_PNT_BOUNDARY) )
+				{
+					//remove from the hit list
+					ray_params.remove();
+					hit_entity_list_ptr->remove();
+				}
+				else
+				{
+					ray_params.step();
+					hit_entity_list_ptr->step();
+				}
+			}
+		}
+
+      }
+    }
+
+    Surface *surface_ptr = CAST_TO( bridge_ptr, Surface );
+    if( surface_ptr )
+    {
+      DLIList<TopologyBridge*> tb_surface_list;
+      vqe->get_underlying_surfaces( surface_ptr, tb_surface_list );
+
+      if( tb_surface_list.size() > 0 )
+      {
+        gqe = tb_surface_list.get()->get_geometry_query_engine();
+
+        gqe->fire_ray( origin, direction, tb_surface_list, ray_params, max_hits,
+          ray_radius, hit_entity_list_ptr );
+		
+		// If surface_ptr is a PartitionSurface, it could be smaller than the underlying surface.
+		// This means we have to check to make sure any hit points lie inside the surface. Remove if they don't.
+		if (CAST_TO(surface_ptr, PartitionSurface))
+		{
+			// start iterating at the first new ray_param
+			ray_params.reset();
+			ray_params.step(prev_num_hits);
+			hit_entity_list_ptr->reset();
+			hit_entity_list_ptr->step(prev_num_hits);
+			
+			int j;
+			for (j=prev_num_hits; j<ray_params.size(); j++)
+			{
+				CubitVector *loc_ptr;
+				double param = ray_params.get();
+
+				loc_ptr = new CubitVector;
+				origin.next_point( direction, param, *loc_ptr );
+				
+				CubitPointContainment containment = CUBIT_PNT_UNKNOWN;
+				containment = surface_ptr->point_containment(*loc_ptr);
+				if ( (containment != CUBIT_PNT_ON) && (containment != CUBIT_PNT_BOUNDARY) )
+				{
+					//remove from the hit list
+					ray_params.remove();
+					hit_entity_list_ptr->remove();
+				}
+				else
+				{
+					ray_params.step();
+					hit_entity_list_ptr->step();
+				}
+			}
+		}
+
+      }
+    }
+
+  }
+
+  if( hit_entity_list_ptr && hit_entity_list_ptr->size() != ray_params.size() )
+    PRINT_WARNING( "Hit entity list size not equal to number of hits\n" );
+
+  // Account for max hits
+  if( max_hits != 0 )
+  {
+    if( ray_params.size() <= max_hits )
+      return CUBIT_SUCCESS;
+
+    for( i=ray_params.size()-max_hits; i--; )
+    {
+      ray_params.last();
+      ray_params.remove();
+      if( hit_entity_list_ptr )
+      {
+        hit_entity_list_ptr->last();
+        hit_entity_list_ptr->remove();
+      }
+    }
+  }
+
+  return CUBIT_SUCCESS;
 }
 
 double VirtualQueryEngine::get_sme_resabs_tolerance() const
@@ -1860,6 +2138,32 @@
   return CUBIT_FAILURE;
 }
 
+//Function should only be called on volumes of multi-volume bodies
+CubitBoolean VirtualQueryEngine::volumes_overlap (Lump *lump1, Lump *lump2 ) const
+{
+  PartitionLump* partition_lump1 = dynamic_cast<PartitionLump*>(lump1);
+  PartitionLump* partition_lump2 = dynamic_cast<PartitionLump*>(lump2);
+
+  Lump *tmp_lump1 = lump1; 
+  if( partition_lump1 )
+    tmp_lump1 = partition_lump1->real_lump();
+
+  Lump *tmp_lump2 = lump2; 
+  if( partition_lump2 )
+    tmp_lump2 = partition_lump2->real_lump();
+
+  GeometryQueryEngine *gqe = tmp_lump1->get_geometry_query_engine();
+  if( gqe != tmp_lump2->get_geometry_query_engine() )
+  {
+    PRINT_ERROR("Volumes must be of the same type (ACIS, SolidWorks, etc) to\n"
+                "find if they overlap.\n");
+    return CUBIT_FALSE;
+  }
+
+  return gqe->volumes_overlap( tmp_lump1, tmp_lump2 );
+}
+
+
 CubitBoolean VirtualQueryEngine::bodies_overlap (BodySM *body_ptr_1, BodySM *body_ptr_2 ) const
 {
   PartitionBody* partition_body1 = dynamic_cast<PartitionBody*>(body_ptr_1);
@@ -1885,4 +2189,255 @@
 
 }
 
+TopologyBridge* VirtualQueryEngine::get_visible_entity_at_point(TopologyBridge* hidden_tb, CubitVector* point)
+{
+	// Determine entity type; should only be Curve or Point
 
+	int j, k;
+	bool added_entity = false;
+	TopologyBridge* bridge_ptr = hidden_tb;
+	TopologyBridge* tb_owner = NULL;
+	bool hidden = CUBIT_TRUE;
+
+	TopologyBridge* visible_tb = NULL;
+
+	while (hidden)
+	{
+		tb_owner = dynamic_cast<TopologyBridge*>(bridge_ptr->owner());
+		if( tb_owner )
+		{
+			if( tb_owner->topology_entity() )
+			{
+				visible_tb = tb_owner;
+				hidden = CUBIT_FALSE;
+				added_entity = true;
+				continue;
+			}
+			else
+				hidden = CUBIT_TRUE;      
+		}
+		else
+		{
+			if( bridge_ptr->topology_entity() )
+			{
+				visible_tb = bridge_ptr;
+				hidden = CUBIT_FALSE;
+				added_entity = true;
+				continue;
+			}
+			else
+			{
+				hidden = CUBIT_TRUE;
+			}
+		}
+
+
+		TopologyBridge *tb_ptr;
+		if( tb_owner )
+			tb_ptr = tb_owner;
+		else
+			tb_ptr = bridge_ptr;
+
+		TBOwner* tb_owner = tb_ptr->owner();
+		if (CAST_TO(tb_owner, HiddenEntitySet)) // virtual geometry
+		{
+			TopologyBridge* parent = NULL;
+			while (CAST_TO(tb_owner, HiddenEntitySet)) // virtual geometry
+			{
+				HiddenEntitySet* hidden_set_ptr = CAST_TO(tb_owner, HiddenEntitySet);
+				parent = dynamic_cast<TopologyBridge*>(hidden_set_ptr->owner());
+				if (parent)
+					tb_owner = parent->owner();
+			}
+			if (parent)
+			{
+				bridge_ptr = parent;
+				added_entity = true;
+				continue;
+			}
+		}
+		else if (CAST_TO(tb_owner, SubEntitySet)) // partition geometry
+		{
+			SubEntitySet* sub_set_ptr = CAST_TO(tb_owner, SubEntitySet);
+
+			DLIList<TopologyBridge*> owner_list;
+			sub_set_ptr->get_owners(owner_list);
+			owner_list.reset();
+			// need to traverse all the entities that make up the original geometry
+			//  if intersected a surface, and the surface is partitioned into mult surfaces,
+			//  which surface did we hit? Did we hit the curve in between? The vertices? gahhhh...
+			for (j=0; j<owner_list.size(); j++)
+			{
+				TopologyBridge* owner_partition = owner_list.get_and_step();
+				//determine geometry type and call point_containment
+
+				CubitPointContainment containment = CUBIT_PNT_UNKNOWN;
+
+				if (CAST_TO(owner_partition, Surface))
+				{
+					containment = CAST_TO(owner_partition, Surface)->point_containment(*point);
+					switch (containment)
+					{
+					case CUBIT_PNT_OFF:
+						break;
+					case CUBIT_PNT_ON:
+						bridge_ptr = owner_partition;
+						added_entity = true;
+						break;
+					case CUBIT_PNT_UNKNOWN:
+						break;
+					case CUBIT_PNT_BOUNDARY:
+						{
+							DLIList<TopologyBridge*> children, related_loops, related_coedges;
+							DLIList<TopologyBridge*> related_curves, temp;
+
+							// Goal: get curves (incl. virtual ones)
+							// Note: can't use ->curves() func b/c it won't grab the virtual curves
+
+							// get all Loops, including virtual
+							owner_partition->get_children( related_loops, true );
+
+							related_loops.reset();
+							int ii;
+
+							// get all CoEdges
+							for (ii = related_loops.size(); ii--;)
+							{
+								temp.clean_out();
+								related_loops.get_and_step()->get_children(temp, true);
+								related_coedges.merge_unique(temp);
+							}
+							// get all Curves
+							for (ii = related_coedges.size(); ii--;)
+							{
+								temp.clean_out();
+								related_coedges.get_and_step()->get_children(temp, true);
+								related_curves.merge_unique(temp);
+							}
+
+							CAST_LIST(related_curves, children, TopologyBridge);
+							for (k=0; k<children.size(); k++)
+							{
+								// CAST and do point_containment for each curve
+								containment = CUBIT_PNT_UNKNOWN;
+								TopologyBridge* partition_curve = children.get_and_step();
+								containment = CAST_TO(partition_curve, Curve)->point_containment(*point);
+								switch (containment)
+								{
+								case CUBIT_PNT_OFF:
+								case CUBIT_PNT_UNKNOWN:
+									break;
+								case CUBIT_PNT_ON:
+									bridge_ptr = partition_curve;
+									added_entity = true;
+									break;
+								case CUBIT_PNT_BOUNDARY:
+									{
+										// CAST and do point_containment for each vertex
+										children.clean_out();
+										partition_curve->get_children(children, true);
+										int kk;
+										for (kk=0; kk<children.size(); kk++)
+										{
+											TopologyBridge* partition_vertex = children.get_and_step();
+											containment = CUBIT_PNT_UNKNOWN;
+											CubitVector coords = CAST_TO(partition_vertex, Point)->coordinates();
+											if (coords.distance_between_squared(*point) < GEOMETRY_RESABS*GEOMETRY_RESABS)
+											{
+												containment = CUBIT_PNT_ON;
+												bridge_ptr = partition_vertex;
+												added_entity = true;
+												break;
+											}
+											else
+												containment = CUBIT_PNT_OFF;
+										}
+									}
+								}
+
+								if (added_entity)
+									break;
+							}                              
+							break;
+						}
+					}
+					if (added_entity)
+						break;
+				}
+				else if (CAST_TO(owner_partition, Curve))
+				{
+					// CAST and do point_containment for each curve
+					containment = CUBIT_PNT_UNKNOWN;
+					containment = CAST_TO(owner_partition, Curve)->point_containment(*point);
+					switch (containment)
+					{
+					case CUBIT_PNT_OFF:
+					case CUBIT_PNT_UNKNOWN:
+						break;
+					case CUBIT_PNT_ON:
+						bridge_ptr = owner_partition;
+						added_entity = true;
+						break;
+					case CUBIT_PNT_BOUNDARY:
+						{
+							// CAST and do point_containment for each vertex
+							DLIList<TopologyBridge*> children;
+							children.clean_out();
+							owner_partition->get_children(children, true);
+							int kk;
+							for (kk=0; kk<children.size(); kk++)
+							{
+								TopologyBridge* partition_vertex = children.get_and_step();
+								containment = CUBIT_PNT_UNKNOWN;
+								CubitVector coords = CAST_TO(partition_vertex, Point)->coordinates();
+								if (coords.distance_between_squared(*point) < GEOMETRY_RESABS*GEOMETRY_RESABS)
+								{
+									containment = CUBIT_PNT_ON;
+									bridge_ptr = partition_vertex;
+									added_entity = true;
+									break;
+								}
+								else
+									containment = CUBIT_PNT_OFF;
+							}
+							break;
+						}
+					}
+
+					if (added_entity)
+						break;
+				}
+
+				else if (CAST_TO(owner_partition, Point))
+				{
+					CubitVector coords = CAST_TO(owner_partition, Point)->coordinates();
+					if (coords.distance_between_squared(*point) < GEOMETRY_RESABS*GEOMETRY_RESABS)
+					{
+						containment = CUBIT_PNT_ON;
+						bridge_ptr = owner_partition;
+						added_entity = true;
+						break;
+					}
+					else
+						containment = CUBIT_PNT_OFF;
+				}
+
+				else
+					PRINT_WARNING("Hit unknown partition entity.\n");
+
+
+			}
+			if (!added_entity)
+			{
+				visible_tb = NULL;
+				hidden = CUBIT_FALSE;
+				//break;
+			}
+
+		}
+
+
+	} //while
+
+	return visible_tb;
+}

Modified: cgm/branches/cubit/geom/virtual/VirtualQueryEngine.hpp
===================================================================
--- cgm/branches/cubit/geom/virtual/VirtualQueryEngine.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/geom/virtual/VirtualQueryEngine.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -71,6 +71,8 @@
   
 public:
   
+  virtual int curve_is_on_ignored_surface(Curve *curve,
+                    Surface *surf);
   void remove_virtual_geometry( RefEntity* entity_ptr,
                                 CubitBoolean all_children );
   void remove_virtual_geometry( Body* body, bool all_children );
@@ -115,6 +117,8 @@
     //- Access to VirtualQueryEngine must be through this function.
     //- This forces single instance of the class. (constructor is protected)
   
+  static void delete_instance();
+
   void register_attributes();
    //-  VGE registers attributes required for virtual geometry
    // -- only call this once per session
@@ -139,9 +143,6 @@
   virtual bool is_intermediate_engine() {return TRUE;}
   
   virtual CubitStatus get_graphics( Surface* surface_ptr,
-                                           int& number_of_triangles,
-                                           int& number_of_points,
-                                           int& number_of_facets,
                                            GMem* gMem,
                                            unsigned short normal_tolerance,
                                            double distance_tolerance,
@@ -163,7 +164,6 @@
     //- all goes well, CUBIT_Success is retuned.
   
   virtual CubitStatus get_graphics( Curve* curve_ptr,
-                                    int& num_points,
                                     GMem* gMem = NULL,
                                     double tolerance = 0.0 ) const;
     //R CubitStatus
@@ -243,8 +243,11 @@
     //I- Return only entities visible in the model.
     //- Get any virtual geometry of the passed entity or its children.
   
+  virtual TopologyBridge* get_visible_entity_at_point(TopologyBridge* hidden_tb, CubitVector* point);
+   //R TopologyBridge*
+   //I hidden_tb, point
+   //I- Returns the lowest level visible entity that contains 'point.' (used for fire_ray())
 
-
   CubitBoolean virtuals_created() const;
     //- returns CUBIT_TRUE if there are virtual entities in the model
   
@@ -264,6 +267,11 @@
                           const CubitBoolean children_too = CUBIT_FALSE);
     //- returns CUBIT_TRUE if the entities passed in are virtual or
     //- contain any virtual entities
+
+  CubitBoolean is_partition( RefEntity *ref_entity );
+
+  CubitStatus get_sister_partitions( RefEntity *ref_entity,
+                                     DLIList<RefEntity*> &sisters);
   
   CubitStatus sort_edges( DLIList<RefEdge*>& edge_list ) const;
     //R CubitStatus
@@ -292,8 +300,11 @@
                              DLIList<TopologyBridge*>& curve_list);
   virtual CubitStatus get_underlying_surfaces(Surface * surf_ptr,
                                  DLIList<TopologyBridge*>& surf_list)  ;
+  virtual CubitStatus get_underlying_bridges(TopologyBridge* bridge_ptr,
+                                        DLIList<TopologyBridge*>& bridge_list);
 
   virtual CubitBoolean bodies_overlap (BodySM *body_ptr_1, BodySM *body_ptr_2 ) const;
+  virtual CubitBoolean volumes_overlap (Lump *lump1, Lump *lump2 ) const;
 
 protected:
   
@@ -305,25 +316,17 @@
 //**** Display related methods
   
   CubitStatus get_composite_curve_facetting( CompositeCurve* ccurve_ptr,
-                                             int& num_points,
                                              GMem* gMem ) const;
   CubitStatus get_partition_curve_facetting( PartitionCurve* pcurve_ptr,
-                                             int& num_points,
                                              GMem* gMem ) const;
   
   CubitStatus get_composite_surface_facetting( CompositeSurface* surf_ptr,
-                                               int& number_triangles,
-                                               int& number_points,
-                                               int& number_facets,
                                                GMem* gMem,
                                                unsigned short normal_tol,
                                                double absolute_tol,
                                                double longest_edge ) const;
 
   CubitStatus get_partition_surface_facetting( PartitionSurface* surf_ptr,
-                                               int& number_triangles,
-                                               int& number_points,
-                                               int& number_facets,
                                                GMem* gMem,
                                                unsigned short normal_tol,
                                                double absolute_tol,
@@ -386,11 +389,22 @@
   virtual CubitStatus delete_solid_model_entities( Curve* curve_ptr ) const;
   virtual CubitStatus delete_solid_model_entities( Point* point_ptr ) const;
 
-  virtual CubitStatus fire_ray(BodySM *body,
-                               const CubitVector &ray_point,
-                               const CubitVector &unit,
-                               DLIList<double> &ray_params,
-                               DLIList<GeometryEntity*> *entity_list = 0) const;
+  virtual CubitStatus 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=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.  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).
+    //- NOTE: returned entities hit might be "hidden" beneath virtual entities.
+    //-       To resolve to visible entities, use "get_visible_ents_for_hits"
+    //-       in GeometryQueryTool.
 
   virtual double get_sme_resabs_tolerance() const;
   virtual double set_sme_resabs_tolerance( double new_resabs );

Modified: cgm/branches/cubit/util/AppUtil.cpp
===================================================================
--- cgm/branches/cubit/util/AppUtil.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/AppUtil.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -12,8 +12,8 @@
 // Owner         : Darryl Melander
 //-------------------------------------------------------------------------
 
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
 #include <signal.h>
 #ifndef NT
 #  include <unistd.h>
@@ -174,6 +174,15 @@
   mProgressTool = NULL;
 }
 
+void AppUtil::delete_instance()
+{
+  if( NULL != instance_ )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}    
+
 #ifdef CAT
 // Returns how many days until the app expires.  A negative
 // number inicates it is already expired.  If there is
@@ -353,7 +362,7 @@
    }
 
      // Delete the singletons
-   delete CubitMessage::instance();
+   CubitMessage::delete_instance();
 
    CubitObserver::term_static_observers();
 

Modified: cgm/branches/cubit/util/AppUtil.hpp
===================================================================
--- cgm/branches/cubit/util/AppUtil.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/AppUtil.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -32,7 +32,7 @@
    static AppUtil* instance();
      //- Access to the application object
 
-  static void delete_instance() {if (instance_) delete instance_;};
+   static void delete_instance();
         
    void report_resource_usage() const;
      //- Prints out information about the session

Modified: cgm/branches/cubit/util/ArrayBasedContainer.cpp
===================================================================
--- cgm/branches/cubit/util/ArrayBasedContainer.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ArrayBasedContainer.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -5,8 +5,8 @@
 
 #include "ArrayBasedContainer.hpp"
 #include "CubitDefines.h"
-#include <string.h>
-#include <assert.h>
+#include <cstring>
+#include <cassert>
 
 unsigned int ArrayBasedContainer::currentAllocatedMemory = 0;
 unsigned int ArrayBasedContainer::maxAllocatedMemory = 0;

Modified: cgm/branches/cubit/util/CMakeLists.txt
===================================================================
--- cgm/branches/cubit/util/CMakeLists.txt	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CMakeLists.txt	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,6 +4,7 @@
 INCLUDE(${cubit_util_SOURCE_DIR}/UseUtil.cmake)
 
 SET(UTIL_SRCS
+    AllocMemManagersList.cpp
     AppUtil.cpp
     ArrayBasedContainer.cpp
     CpuTimer.cpp
@@ -27,6 +28,7 @@
     CubitStack.cpp
     CubitString.cpp
     CubitTransformMatrix.cpp
+    CubitUndo.cpp
     CubitUtil.cpp
     CubitVector.cpp
     DIntArray.cpp
@@ -34,6 +36,7 @@
     DynamicArray.cpp
     GetLongOpt.cpp
     GfxDebug.cpp
+    GlobalCommandFeedback.cpp
     GMem.cpp
     IntersectionTool.cpp
     MemoryBlock.cpp
@@ -52,12 +55,68 @@
     ToolDataUser.cpp
     Tree.cpp
     TtyProgressTool.cpp
-    CubitEventDefines.h
     )
 
-SET(EXTRA_UTIL_SRCS
-    AllocMemManagersList.cpp
-    )
+SET(UTIL_HDRS
+    AppUtil.hpp
+    ArrayBasedContainer.hpp
+    CpuTimer.hpp
+    CommandFeedback.hpp
+    Cubit2DPoint.hpp
+    CubitBox.hpp
+    CubitCollection.hpp
+    CubitContainer.hpp
+    CubitCoordinateSystem.hpp
+    CubitDefines.h
+    CubitDynamicLoader.hpp
+    CubitEntity.hpp
+    CubitEquation.hpp
+    CubitFile.hpp
+    CubitFileFEModel.hpp
+    CubitFileIOWrapper.hpp
+    CubitFileMetaData.hpp
+    CubitFileUtil.hpp
+    CubitMatrix.hpp
+    CubitMessage.hpp
+    CubitObservable.hpp
+    CubitObserver.hpp
+    CubitPlane.hpp
+    CubitStack.hpp
+    CubitString.hpp
+    CubitTransformMatrix.hpp
+    CubitUndo.hpp
+    CubitUtil.hpp
+    CubitVector.hpp
+    DIntArray.hpp
+    DLIList.hpp
+    DLList.hpp
+    DynamicArray.hpp
+    GetLongOpt.hpp
+    GfxDebug.hpp
+    GlobalCommandFeedback.hpp
+    GMem.hpp
+    IntersectionTool.hpp
+    MemoryBlock.hpp
+    MemoryManager.hpp
+    OrderedSet.hpp
+    OrderedMap.hpp
+    ParamCubitPlane.hpp
+    PlanarParamTool.hpp
+    Queue.hpp
+    RandomMersenne.hpp
+    SDLList.hpp
+    SettingHandler.hpp
+    SettingHolder.hpp
+    StubProgressTool.hpp
+    TDUPtr.hpp
+    TextProgressTool.hpp
+    ToolData.hpp
+    ToolDataUser.hpp
+    Tree.hpp
+    TtyProgressTool.hpp
+    CubitEventDefines.h
+    ${cubit_util_BINARY_DIR}/CubitUtilConfigure.h
+  )
 
 IF(TEMPLATE_DEFS_INCLUDED)
 SET(TEMPLATE_SRCS
@@ -74,17 +133,8 @@
     )
 ENDIF(TEMPLATE_DEFS_INCLUDED)
 
-IF(WIN32)
-  FOREACH(var ${UTIL_SRCS})
-    STRING(REGEX REPLACE ".cpp" ".hpp" header ${var})
-    SET(UTIL_HEADERS ${UTIL_HEADERS} ${header})
-  ENDFOREACH(var ${UTIL_SRCS})
-  SET(UTIL_HEADERS ${UTIL_HEADERS} CubitEquation.hpp)
-ENDIF(WIN32)
-
 ADD_DEFINITIONS(${CUBIT_UTIL_DEFINES})
 
-
 INCLUDE_DIRECTORIES(${cubit_util_BINARY_DIR})
 
 OPTION(CUBIT_UTIL_BUILD_SHARED_LIBS "Build Cubit_Util as shared library" OFF)
@@ -92,37 +142,52 @@
   SET(CUBIT_UTIL_BUILD_SHARED_LIBS ON CACHE BOOL "Build Cubit_Util as shared library" FORCE)
 ENDIF(BUILD_SHARED_LIBS)
 
-IF(CUBIT_UTIL_BUILD_SHARED_LIBS)
-  ADD_LIBRARY(cubit_util SHARED ${UTIL_SRCS} ${UTIL_HEADERS} ${TEMPLATE_SRCS} ${EXTRA_UTIL_SRCS})
-
-  IF(CUBIT_COPY_DIR)
-    # The cubit copy dir should only be set on windows.
-    STRING(REGEX REPLACE "/" "\\\\" winbin "${CUBIT_COPY_DIR}")
-    IF(${CMAKE_GENERATOR} MATCHES "Visual Studio")
-      ADD_CUSTOM_COMMAND(TARGET cubit_util POST_BUILD
-                         COMMAND ${CMAKE_COMMAND}
-                         ARGS -E copy
-                           $\(TargetPath\) ${winbin}\\$\(TargetName\).dll)
-    ELSE(${CMAKE_GENERATOR} MATCHES "Visual Studio")
-      STRING(REGEX REPLACE "/" "\\\\" winsrc "${LIBRARY_OUTPUT_PATH}")
-      ADD_CUSTOM_COMMAND(TARGET cubit_util POST_BUILD
-                         COMMAND ${CMAKE_COMMAND}
-                         ARGS -E copy
-                           ${winsrc}\\cubit_util.dll
-                           ${winlib}\\cubit_util.dll)
-    ENDIF(${CMAKE_GENERATOR} MATCHES "Visual Studio")
-  ENDIF(CUBIT_COPY_DIR)
-ELSE(CUBIT_UTIL_BUILD_SHARED_LIBS)
-  ADD_LIBRARY(cubit_util ${UTIL_SRCS} ${UTIL_HEADERS} ${TEMPLATE_SRCS} ${EXTRA_UTIL_SRCS})
-ENDIF(CUBIT_UTIL_BUILD_SHARED_LIBS)
-
 CONFIGURE_FILE(${cubit_util_SOURCE_DIR}/CubitUtilConfigure.h.in
                ${cubit_util_BINARY_DIR}/CubitUtilConfigure.h
                @ONLY)
 
+IF(NOT CUBIT_UTIL_NAME)
+  SET(CUBIT_UTIL_NAME cubit_util)
+ENDIF(NOT CUBIT_UTIL_NAME)
 
-SET(CMAKE_INSTALL_BINARY_DIR "bin" CACHE PATH "Install directory for binaries")
 IF(CUBIT_UTIL_BUILD_SHARED_LIBS)
-  INSTALL_TARGETS(/${CMAKE_INSTALL_BINARY_DIR} cubit_util)
+  ADD_LIBRARY(${CUBIT_UTIL_NAME} SHARED ${UTIL_SRCS} ${UTIL_HDRS} ${TEMPLATE_SRCS})
+ELSE(CUBIT_UTIL_BUILD_SHARED_LIBS)
+  ADD_LIBRARY(${CUBIT_UTIL_NAME} ${UTIL_SRCS} ${UTIL_HDRS} ${TEMPLATE_SRCS})
 ENDIF(CUBIT_UTIL_BUILD_SHARED_LIBS)
 
+TARGET_LINK_LIBRARIES(${CUBIT_UTIL_NAME} ${CMAKE_DL_LIBS})
+
+IF(CUBIT_LIBRARY_PROPERTIES)
+  SET_TARGET_PROPERTIES(${CUBIT_UTIL_NAME}
+                        PROPERTIES ${CUBIT_LIBRARY_PROPERTIES})
+ENDIF(CUBIT_LIBRARY_PROPERTIES)
+
+
+IF(NOT CMAKE_INSTALL_BINARY_DIR)
+  SET(CMAKE_INSTALL_BINARY_DIR bin)
+ENDIF(NOT CMAKE_INSTALL_BINARY_DIR)
+
+IF(NOT CMAKE_INSTALL_INCLUDE_DIR)
+  SET(CMAKE_INSTALL_INCLUDE_DIR include)
+ENDIF(NOT CMAKE_INSTALL_INCLUDE_DIR)
+
+IF(CUBIT_UTIL_INSTALL_NO_DEVELOPMENT)
+  IF(CUBIT_UTIL_BUILD_SHARED_LIBS)
+    INSTALL(TARGETS ${CUBIT_UTIL_NAME} ${CUBIT_UTIL_EXPORT_GROUP}
+            RUNTIME DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+            LIBRARY DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime)
+  ENDIF(CUBIT_UTIL_BUILD_SHARED_LIBS)
+ELSE(CUBIT_UTIL_INSTALL_NO_DEVELOPMENT)
+INSTALL(TARGETS ${CUBIT_UTIL_NAME} ${CUBIT_UTIL_EXPORT_GROUP}
+        RUNTIME DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+        LIBRARY DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Runtime
+        ARCHIVE DESTINATION ${CMAKE_INSTALL_BINARY_DIR} COMPONENT Development)
+
+IF(NOT CUBIT_UTIL_INSTALL_NO_DEVELOPMENT_HEADERS)
+INSTALL(FILES ${UTIL_HDRS}
+        DESTINATION ${CMAKE_INSTALL_INCLUDE_DIR} COMPONENT Development)
+ENDIF(NOT CUBIT_UTIL_INSTALL_NO_DEVELOPMENT_HEADERS)
+
+ENDIF(CUBIT_UTIL_INSTALL_NO_DEVELOPMENT)
+

Modified: cgm/branches/cubit/util/CastTo.hpp
===================================================================
--- cgm/branches/cubit/util/CastTo.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CastTo.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -47,6 +47,7 @@
    { \
       (classOneList).reset(); \
       (classTwoList).clean_out(); \
+      (classTwoList).reserve((classOneList).size()); \
       for (int CAST_LIST_IT = (classOneList).size(); CAST_LIST_IT > 0; CAST_LIST_IT--) \
         (classTwoList).append((classOneList).get_and_step()); \
    }

Added: cgm/branches/cubit/util/CommandFeedback.hpp
===================================================================
--- cgm/branches/cubit/util/CommandFeedback.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/CommandFeedback.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,62 @@
+#ifndef CUBIT_COMMANDFEEDBACK_HPP
+#define CUBIT_COMMANDFEEDBACK_HPP
+
+#include <typeinfo>
+#include <cassert>
+
+// Base class for all command feedback.
+class CommandFeedback
+{
+public:
+  typedef const std::type_info& Type;
+
+  CommandFeedback()
+  {}
+
+  virtual ~CommandFeedback()
+  {}
+
+  virtual Type this_type() const = 0;
+
+  template <typename target_type>
+    target_type& get_reference()
+  {
+    assert(this->this_type() == target_type::type());
+    return *(dynamic_cast<target_type*>(this));
+  }
+
+  template <typename target_type>
+    const target_type& get_reference() const
+  {
+    assert(this->this_type() == target_type::type());
+    return *(dynamic_cast<const target_type*>(this));
+  }
+};
+
+// The rest of this file is an example to show how to use CommandFeedback
+#include "CubitString.hpp"
+
+class DeprecatedCommandError : public CommandFeedback
+{
+public:
+  DeprecatedCommandError(const CubitString &some_string)
+    : myString(some_string), myInt(27)
+  {}
+
+  int wow_an_integer() const
+  { return myInt; }
+  CubitString wow_a_string() const
+  { return myString; }
+
+  static CommandFeedback::Type type()
+  { return typeid(DeprecatedCommandError); }
+
+  CommandFeedback::Type this_type() const
+  { return DeprecatedCommandError::type(); }
+
+private:
+  int myInt;
+  CubitString myString;
+};
+
+#endif

Modified: cgm/branches/cubit/util/CpuTimer.cpp
===================================================================
--- cgm/branches/cubit/util/CpuTimer.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CpuTimer.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,4 +1,4 @@
-#include <stdio.h>
+#include <cstdio>
 #include "CpuTimer.hpp"
 
 #include "CubitMessage.hpp"
@@ -9,7 +9,7 @@
   #include <sys/times.h>
 #endif
 
-#include <time.h>	
+#include <time.h>
 #ifdef SOLARIS
 #include <unistd.h>
 #endif
@@ -43,8 +43,12 @@
 
   // Added by Cat for NT port
 #ifdef NT
-  nt_times(&current);    
+  nt_times(&current);
+  wallTimeInitial = clock();
+  wallTime = wallTimeInitial;
 #else
+  gettimeofday(&wallTimeInitial, NULL);
+  wallTime = wallTimeInitial;
   times( &current );
 #endif
   
@@ -84,24 +88,76 @@
 }
 
 double
-CpuTimer::elapsed()
+CpuTimer::clock_secs()
 {
-  tms current;
+  double elapsed_time;
+#ifdef NT
+  clock_t current;
+  current = clock();
+  elapsed_time = double( current - wallTime );
+  elapsed_time = elapsed_time / HZ;
 
+  wallTime = current;
+#else
+  timeval current;
+  gettimeofday( &current, NULL );
+  double prev_time = wallTime.tv_sec;
+  prev_time += double( wallTime.tv_usec ) / 1000000.0;
+  
+  elapsed_time = current.tv_sec;
+  elapsed_time += double( current.tv_usec ) / 1000000.0;
+  elapsed_time = elapsed_time - prev_time;
+  
+  wallTime = current;
+#endif
+  
+  return elapsed_time;
+}
+
+double
+CpuTimer::elapsed(bool wall_time)
+{
+  if( wall_time )
+  {
+    double elapsed;
+#ifdef NT
+    clock_t current;
+    current = clock();
+    elapsed = double( current - wallTimeInitial);
+    elapsed = elapsed / HZ;
+#else    
+    double current_time;
+    timeval current;
+    gettimeofday( &current, NULL );
+    double initial_time;
+    initial_time = wallTimeInitial.tv_sec;
+    initial_time += double(wallTimeInitial.tv_usec) / 1000000.0;
+    current_time = current.tv_sec;
+    current_time += double( current.tv_usec ) / 1000000.0;
+    
+    elapsed = current_time - initial_time;
+#endif
+    return elapsed;
+  }
+  else
+  {
+    tms current;
+
 // Added by Cat for NT port
 #ifdef NT
-  nt_times(&current);    
+    nt_times(&current);    
 #else
-  times( &current );
+    times( &current );
 #endif
 // Store totals
   
-  time_t cpu_now = current.tms_utime +
-    current.tms_stime +
-    current.tms_cutime +
-    current.tms_cstime;
-  time_t elapsed = cpu_now - cpuInitial;
-  return (double) elapsed / HZ;
+    time_t cpu_now = current.tms_utime +
+        current.tms_stime +
+        current.tms_cutime +
+        current.tms_cstime;
+    time_t elapsed = cpu_now - cpuInitial;
+    return (double) elapsed / HZ;
+  }
 }
 
 

Modified: cgm/branches/cubit/util/CpuTimer.hpp
===================================================================
--- cgm/branches/cubit/util/CpuTimer.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CpuTimer.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -3,27 +3,39 @@
 #if !defined(CPU_TIMER)
 #define CPU_TIMER
 #include <sys/types.h>
+#ifndef NT
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
 #include "CubitUtilConfigure.h"
 
 
 class CUBIT_UTIL_EXPORT CpuTimer {
 public:
   CpuTimer();			//- initialise to current system time
-  double cpu_secs();		//- return CPU time in seconds since last
-                                //- to cpu_secs();
-  double elapsed();             //- return CPU time in seconds since 'birth'
+  double cpu_secs();		        //- return CPU time in seconds since last
+                                //- call to cpu_secs();
+  double clock_secs();          //- return wall clock time in seconds since last
+                                //- call to clock_secs();
+  double elapsed(bool wall_time = false);    //- return CPU time in seconds since 'birth' if 
+                                             //- wall_time is false, else returns the wall clock time.
   
 private:
   time_t cpu;			//- cpu time in 1/HZ units since last call
                                 //- to cpu_secs()
   time_t cpuInitial;             //- cpu time in 1/HZ units since construction.
 
- // Added by Cat for NT port
+
+    // Added by Cat for NT port
   #ifdef NT
   void  nt_times(struct tms *);
+  clock_t wallTimeInitial;
+  clock_t wallTime;
+  #else
+  timeval wallTimeInitial;     //- Time at construction.
+  timeval wallTime;            //- Time since last call.
   #endif
-
-
 };
 
 #endif

Modified: cgm/branches/cubit/util/CubitBox.cpp
===================================================================
--- cgm/branches/cubit/util/CubitBox.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitBox.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -3,9 +3,9 @@
 //- Owner: Greg Sjaardema
 //- Checked by:
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cassert>
 
 #include "CubitBox.hpp"
 #include "CubitVector.hpp"
@@ -433,3 +433,85 @@
           vect.z() <= minimum_.z() ||
           vect.z() >= maximum_.z() );
 }
+
+/* 
+Fast Ray-Box Intersection
+by Andrew Woo
+from "Graphics Gems", Academic Press, 1990
+*/
+
+#define NUMDIM	3
+#define RIGHT	0
+#define LEFT	1
+#define MIDDLE	2
+
+//char HitBoundingBox(minB,maxB, origin, dir,coord)
+//double minB[NUMDIM], maxB[NUMDIM];		/*box */
+//double origin[NUMDIM], dir[NUMDIM];		/*ray */
+//double coord[NUMDIM];				/* hit point */
+bool CubitBox::intersect(const CubitVector* ray_origin, const CubitVector* ray_direction,
+                         CubitVector* intersection_pt)
+{
+	bool inside = true;
+	int quadrant[NUMDIM];
+	register int i;
+	int whichPlane;
+	double maxT[NUMDIM];
+	double candidatePlane[NUMDIM];
+
+	/* Find candidate planes; this loop can be avoided if
+   	rays cast all from the eye(assume perpsective view) */
+	for (i=0; i<NUMDIM; i++)
+		if((*ray_origin)[i] < (this->minimum())[i]) {
+			quadrant[i] = LEFT;
+			candidatePlane[i] = (this->minimum())[i];
+			inside = false;
+		}else if ( (*ray_origin)[i] > (this->maximum())[i]) {
+			quadrant[i] = RIGHT;
+			candidatePlane[i] = (this->maximum())[i];
+			inside = false;
+		}else	{
+			quadrant[i] = MIDDLE;
+		}
+
+	/* Ray origin inside bounding box */
+	if(inside)
+    {
+		intersection_pt = new CubitVector(*ray_origin);
+		return true;
+	}
+
+
+	/* Calculate T distances to candidate planes */
+	for (i = 0; i < NUMDIM; i++)
+		if (quadrant[i] != MIDDLE && (*ray_direction)[i] !=0.)
+			maxT[i] = ( candidatePlane[i]-(*ray_origin)[i]) / ((*ray_direction)[i]);
+		else
+			maxT[i] = -1.;
+
+	/* Get largest of the maxT's for final choice of intersection */
+	whichPlane = 0;
+	for (i = 1; i < NUMDIM; i++)
+		if (maxT[whichPlane] < maxT[i])
+			whichPlane = i;
+
+	/* Check final candidate actually inside box */
+	double intersection_coords[3];
+
+    if (maxT[whichPlane] < 0.)
+        return false;
+
+	for (i = 0; i < NUMDIM; i++)
+    {
+		if (whichPlane != i)
+        {
+			intersection_coords[i] = (*ray_origin)[i] + maxT[whichPlane] * (*ray_direction)[i];
+			if (intersection_coords[i] < (this->minimum())[i] || intersection_coords[i] > (this->maximum())[i])
+				return false;
+		}
+        else
+        	intersection_coords[i] = candidatePlane[i];
+    }
+
+	return true;  /* ray hits box */
+}

Modified: cgm/branches/cubit/util/CubitBox.hpp
===================================================================
--- cgm/branches/cubit/util/CubitBox.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitBox.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -80,6 +80,10 @@
     //- Check if boxes are within passed tolerance of each other.
     //- If tolerance is 0, use && or || operator.
   
+  bool intersect(const CubitVector* ray_origin, const CubitVector* ray_direction,
+      CubitVector* intersection_pt = NULL);
+    //- Check if ray intersects box
+
     //- Heading: Operators
 
     // Operators that modify {this}
@@ -133,14 +137,14 @@
 
     // Operators that return a modification of {this}.
     // {this} itself is not modified.
-  friend CubitBox operator|(const CubitBox& lhs, const CubitBox& rhs);
-  friend CubitBox operator|(const CubitBox& lhs, const CubitVector& rhs);
-  friend CubitBox operator&(const CubitBox& lhs, const CubitBox& rhs);
-  friend CubitBox operator*(const CubitBox& lhs, double rhs);
-  friend CubitBox operator*(double rhs, const CubitBox& lhs);
-  friend CubitBox operator/(const CubitBox& lhs, double rhs);
-  friend CubitBox operator+(const CubitBox& lhs, const CubitVector& rhs);
-  friend CubitBox operator-(const CubitBox& lhs, const CubitVector& rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator|(const CubitBox& lhs, const CubitBox& rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator|(const CubitBox& lhs, const CubitVector& rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator&(const CubitBox& lhs, const CubitBox& rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator*(const CubitBox& lhs, double rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator*(double rhs, const CubitBox& lhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator/(const CubitBox& lhs, double rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator+(const CubitBox& lhs, const CubitVector& rhs);
+  friend CUBIT_UTIL_EXPORT CubitBox operator-(const CubitBox& lhs, const CubitVector& rhs);
   
 #ifdef BOYD15
   double distance( const CubitVector& position ) const;

Modified: cgm/branches/cubit/util/CubitColorConstants.hpp
===================================================================
--- cgm/branches/cubit/util/CubitColorConstants.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitColorConstants.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,14 +4,14 @@
 const int CUBIT_DEFAULT_COLOR = -1;
 const int CUBIT_BLACK         =  0;
 const int CUBIT_GREY          =  1;
-const int CUBIT_GREEN         =  2;
-const int CUBIT_YELLOW        =  3;
-const int CUBIT_RED           =  4;
-const int CUBIT_MAGENTA       =  5;
-const int CUBIT_CYAN          =  6;
-const int CUBIT_BLUE          =  7;
-const int CUBIT_WHITE         =  8;
-const int CUBIT_ORANGE        =  9;
+const int CUBIT_ORANGE        =  2;
+const int CUBIT_RED           =  3;
+const int CUBIT_GREEN         =  4;
+const int CUBIT_YELLOW        =  5;
+const int CUBIT_MAGENTA       =  6;
+const int CUBIT_CYAN          =  7;
+const int CUBIT_BLUE          =  8;
+const int CUBIT_WHITE         =  9;
 const int CUBIT_BROWN         = 10;
 const int CUBIT_GOLD          = 11;
 const int CUBIT_LIGHTBLUE     = 12;

Modified: cgm/branches/cubit/util/CubitCoordinateSystem.cpp
===================================================================
--- cgm/branches/cubit/util/CubitCoordinateSystem.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitCoordinateSystem.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,7 +1,7 @@
 
 #include "CubitCoordinateSystem.hpp"
 
-#include <assert.h>
+#include <cassert>
 
 #include "CubitMessage.hpp"
 

Modified: cgm/branches/cubit/util/CubitDefines.h
===================================================================
--- cgm/branches/cubit/util/CubitDefines.h	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitDefines.h	2010-01-06 19:22:14 UTC (rev 3423)
@@ -18,6 +18,7 @@
 
 #ifdef NT
 #pragma warning ( 4 : 4291 4244 4305 4018 4786)
+#pragma warning(error : 4239)
 #endif
 /* Adds DBL_MIN, DBL_MAX definitions on some platforms*/
 #include <float.h> 
@@ -75,8 +76,10 @@
 
 enum FirmnessType {LIMP, SOFT, FIRM, HARD};
 /* Firmness continuum - how bad does the user want something? 
-   LIMP means "don't care" or "unset", SOFT means "about right" or
-   "automatically set", HARD means "user set" or "must be this way".
+   LIMP - default setting--i.e. "don't care" or "unset"
+   SOFT - determined by basic geometric criteria--"about right" or "automatically set"
+   FIRM - determined by advanced heuristic data, including adjacent environmental data
+   HARD - user set--"must be this way"
 */
 
 /* Relationships between types of objects in the Entity Relationship

Modified: cgm/branches/cubit/util/CubitDynamicLoader.cpp
===================================================================
--- cgm/branches/cubit/util/CubitDynamicLoader.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitDynamicLoader.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,6 +1,6 @@
 
 // We have 4 different implementations here
-// Windows, Unix, MacOSX, HP-UX
+// Windows, Unix, , HP-UX
 
 #include "CubitDynamicLoader.hpp"
 
@@ -48,6 +48,10 @@
     }
   }
   
+  // one more final attempt
+  if (stat(library, &buf) == 0)
+    return CUBIT_TRUE;
+
   return CUBIT_FALSE;
 }
 
@@ -188,83 +192,6 @@
   return ".sl";
 }
 
-#elif defined(__APPLE__)
-
-#include <mach-o/dyld.h>
-
-CubitDynamicLoader::LibraryHandle CubitDynamicLoader::InvalidLibraryHandle = NULL;
-
-CubitDynamicLoader::LibraryHandle CubitDynamicLoader::load_library(const char* lib)
-{
-  NSObjectFileImageReturnCode rc;
-  NSObjectFileImage image;
-  
-  LibraryHandle handle = InvalidLibraryHandle;
-  
-  // if absolute path, test it directly
-  if(absolute_path(lib))
-  {
-    rc = NSCreateObjectFileImageFromFile(lib, &image);
-    handle = NSLinkModule(image, lib, TRUE);
-  }
-  else
-  { 
-    // try finding with our search paths
-    for(int i=0; i<gSearchPaths.size(); i++)
-    {
-      CubitString path = gSearchPaths[i]+CubitString("/")+lib;
-      rc = NSCreateObjectFileImageFromFile(path.c_str(), &image);
-      handle = NSLinkModule(image, lib, TRUE);
-      if(handle != InvalidLibraryHandle)
-        return handle;
-    }
-  }
-  
-  // one more final attempt
-  rc = NSCreateObjectFileImageFromFile(lib, &image);
-  handle = NSLinkModule(image, lib, TRUE);
-  return handle;
-}
-
-CubitString CubitDynamicLoader::get_error()
-{
-  return CubitString();
-}
-
-CubitStatus CubitDynamicLoader::unload_library(CubitDynamicLoader::LibraryHandle lib)
-{
-  return NSUnLinkModule(static_cast<NSModule>(lib), FALSE) == 0 ? CUBIT_SUCCESS : CUBIT_FAILURE;
-}
-
-void* CubitDynamicLoader::get_symbol_address(CubitDynamicLoader::LibraryHandle, const char* sym)
-{
-  void *result = 0;
-  // global 'C' symbols names are preceded with an underscore '_'
-  char *_sym = new char[ strlen(sym) + 2 ];
-  strcpy( _sym + 1, sym );
-  _sym[0] = '_';
-  if( NSIsSymbolNameDefined(_sym) )
-  {
-    NSSymbol symbol = NSLookupAndBindSymbol(_sym);
-    if(symbol)
-    {
-      result = NSAddressOfSymbol(symbol);
-    }
-  }
-  delete[] _sym;
-  return result;
-}
-
-const char* CubitDynamicLoader::library_prefix()
-{
-  return "lib";
-}
-
-const char* CubitDynamicLoader::library_extension()
-{
-  return ".so";
-}
-
 #else
 
 #include <dlfcn.h>

Modified: cgm/branches/cubit/util/CubitEntity.cpp
===================================================================
--- cgm/branches/cubit/util/CubitEntity.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitEntity.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -11,8 +11,8 @@
 #endif
 
 
-#include <assert.h>
-#include <string.h>
+#include <cassert>
+#include <cstring>
 
 #include "CubitDefines.h"
 #include "CubitVector.hpp"
@@ -65,7 +65,7 @@
 
 int  CubitEntity::id() const { return entityId; }
 
-void CubitEntity::set_id(int i) {entityId = i;}
+void CubitEntity::set_id(int i) { entityId = i; }
     //- set the id of this entity to i
 
 int CubitEntity::validate()

Modified: cgm/branches/cubit/util/CubitEventDefines.h
===================================================================
--- cgm/branches/cubit/util/CubitEventDefines.h	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitEventDefines.h	2010-01-06 19:22:14 UTC (rev 3423)
@@ -13,6 +13,8 @@
                    /* A ModelEntity was deleted */
                  COMPARISON_FOUND,
                    /* A partner entity was found (they compare successfully) */
+                 DEVELOPER_COMMAND_FLAG_MODIFIED,
+                  /* The 'set developer command on/off' was issued */
                  ENTITY_SURVIVED_MERGE,
                    /* An entity was involved in a merge and survived */
                  MERGE_COMPLETED,
@@ -34,6 +36,22 @@
                     * was changed.  Used for virtual topology. */
                  GEOMETRY_MODIFIED,
                    /* The geometry of a RefEntity was altered. */
+                 HEALER_COMPLETED,
+                   /* Notifies that the healer completed */
+                 COMPOSITE_CREATION_COMPLETED,
+                   /* Notifies that a composite was created */
+                 SPLIT_SURFACE_COMPLETED,
+                   /* Notifies that a split face operation is done */
+                 COLLAPSE_CURVE_COMPLETED,
+                   /* Notifies that a collapse curve operation is done */
+                 AUTO_CLEAN_COMPLETED,
+                   /* Notifies that an auto_clean operation is done */
+                 REMOVE_SURFACE_COMPLETED,
+                   /* Notifies that a remove surface operation is done */
+                 REMOVE_TOPOLOGY_COMPLETED,
+                   /* Notifies that a remove_topology operation is done */
+                 REGULARIZE_ENTITY_COMPLETED,
+                   /* Notifies that a regularize entity operation is done */
                  NEW_ENTITY_UNMERGED,
                    /*A surface, curve, or vertex was unmerged. */
                  DAG_NODE_DESTRUCTED,
@@ -94,19 +112,30 @@
                    // Block, nodeset or sideset was deleted.
                  GENESIS_ENTITY_MODIFIED,
                    // Block, nodeset or sideset was modified.
+                 MATERIAL_CREATED,
+                   // Material created
+                 MATERIAL_MODIFIED,
+                   // Material modified
+                 MATERIAL_DELETED,
+                   // Material deleted
                  SUSPEND_GENESIS_PROCESSING,
                    // Suspend processing (in CubitInterface) for Genesis events
                  RESUME_GENESIS_PROCESSING,
                    // Resume processing (in CubitInterface) for Genesis events
                  UPDATE_GENESIS_DISPLAY,
                    // Force an update of all genesis entity display
+                 UNDO_STATE_CHANGED,
+                   // Undo has been changed in some way
+                 UNDO_COMPLETE,
+                   // Undo has completed its processing
 
-
                    // ******** Assembly Events  *********
                    //   All assembly events pass an AssemblyEvent
                    //   object.  The functions used to get valid
                    //   data for a particular event type is listed
                    //   right after the event type name.
+                 WEBCUT_COMPLETED,
+                   // Inform regarding the completion of a webcut operation
                  
                  ASSEMBLY_ADD_CHILD,
                    // (get_assembly(), get_node())
@@ -147,7 +176,7 @@
                    // Sent just after a property of the tree changes.
                    // These are properties that apply to the tree as a whole,
                    // not to any individual AssemblyNode.
-                 
+
                    // 
                    // ********* End of Assembly Events **********
 };

Modified: cgm/branches/cubit/util/CubitFile.cpp
===================================================================
--- cgm/branches/cubit/util/CubitFile.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFile.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -30,7 +30,7 @@
 #include "CubitFileIOWrapper.hpp"
 #include "CubitFileMetaData.hpp"
 #include "CubitFileFEModel.hpp"
-#include <string.h>
+#include <cstring>
 
 using namespace NCubitFile;
 
@@ -40,7 +40,7 @@
 
 /* Note: some platforms define both BIG_ENDIAN and LITTLE_ENDIAN
    so don't do if defined(LITTLE_ENDIAN) here.  Compare to BYTE_ORDER instead. */
-#if defined(NT) || defined(DA) || defined(CUBIT_LINUX) || (defined(LITTLE_ENDIAN) && (BYTE_ORDER==LITTLE_ENDIAN)) /* should be little endian platforms */
+#if defined(NT) || defined(__LITTLE_ENDIAN__) || defined(CUBIT_LINUX) || (defined(LITTLE_ENDIAN) && (BYTE_ORDER==LITTLE_ENDIAN)) /* should be little endian platforms */
     const UnsignedInt32 CCubitFile::mintNativeEndian = 0;
 #else // big endian platforms
     const UnsignedInt32 CCubitFile::mintNativeEndian = 0xFFFFFFFF;
@@ -451,7 +451,7 @@
     
     // Initialize the new model's table entry.
     mpaWriteModels[mWriteContents.mintNumModels].mintModelHandle =
-        xintModel = mintNextModelID++;
+        xintModel;// = mintNextModelID++;
     mpaWriteModels[mWriteContents.mintNumModels].mintModelOffset = 0;
     mpaWriteModels[mWriteContents.mintNumModels].mintModelLength = 0;
     mpaWriteModels[mWriteContents.mintNumModels].mintModelType = xeModelType;
@@ -975,6 +975,7 @@
 
 UnsignedInt32 CCubitFile::WriteBlock(UnsignedInt32 xintIndex,
                                      UnsignedInt32 xintBlockID,
+                                     int unique_id,
                                      UnsignedInt32 xintBlockType,
                                      UnsignedInt32 xintBlockColor,
                                      UnsignedInt32 xintMixedElemType,
@@ -991,7 +992,7 @@
     try {
         if(!mpWriteFEModel)
             throw eOrderError;
-        mpWriteFEModel->WriteBlock(xintIndex, xintBlockID, xintBlockType,
+        mpWriteFEModel->WriteBlock(xintIndex, xintBlockID, unique_id, xintBlockType,
             xintBlockColor, xintMixedElemType, xintDefPyramidType,
             xintMaterialID, xintBlockDimension, xintNumTypes, xpaBlockData,
             xintAttributeOrder, xpadblAttributes);
@@ -1003,18 +1004,20 @@
 
 UnsignedInt32 CCubitFile::WriteNodeSet(UnsignedInt32 xintIndex,
                                        UnsignedInt32 xintNodeSetID,
+                                       int unique_id,
                                        UnsignedInt32 xintColor,
                                        UnsignedInt32 xintPointSymbol,
                                        UnsignedInt32 xintNumTypes,
-                                       SNodeSetData* xpaNodeSetData)
+                                       SNodeSetData* xpaNodeSetData,
+                                       const std::vector<char>& bcdata)
 // Try to write the membership of the passed group index to the writable file.
 // RETURNS: 0 on success, other values indicate error code.
 {
     try {
         if(!mpWriteFEModel)
             throw eOrderError;
-        mpWriteFEModel->WriteNodeSet(xintIndex, xintNodeSetID, xintColor,
-            xintPointSymbol, xintNumTypes, xpaNodeSetData);
+        mpWriteFEModel->WriteNodeSet(xintIndex, xintNodeSetID, unique_id, xintColor,
+            xintPointSymbol, xintNumTypes, xpaNodeSetData, bcdata);
         return eSuccess;
     }
     catch(EErrorCode xeErrorCode)  {  return xeErrorCode;  }
@@ -1023,21 +1026,23 @@
 
 UnsignedInt32 CCubitFile::WriteSideSet_11(UnsignedInt32 xintIndex,
                                        UnsignedInt32 xintSideSetID,
+                                       int unique_id,
                                        UnsignedInt32 xintColor,
                                        UnsignedInt32 xintUseShells,
                                        UnsignedInt32 xintNumTypes,
                                        SSideSetData_11* xpaSideSetData,
                                        UnsignedInt32 xintNumDistFact,
-                                       double* xpadblDistribution)
+                                       double* xpadblDistribution,
+                                       const std::vector<char>& bcdata)
 // Try to write the membership of the passed group index to the writable file.
 // RETURNS: 0 on success, other values indicate error code.
 {
     try {
         if(!mpWriteFEModel)
             throw eOrderError;
-        mpWriteFEModel->WriteSideSet_11(xintIndex, xintSideSetID, xintColor,
+        mpWriteFEModel->WriteSideSet_11(xintIndex, xintSideSetID, unique_id, xintColor,
             xintUseShells, xintNumTypes, xpaSideSetData, xintNumDistFact,
-            xpadblDistribution);
+            xpadblDistribution, bcdata);
         return eSuccess;
     }
     catch(EErrorCode xeErrorCode)  {  return xeErrorCode;  }
@@ -1216,6 +1221,7 @@
 
 UnsignedInt32 CCubitFile::ReadBlock(UnsignedInt32 xintIndex,
                                     UnsignedInt32& xintBlockID,
+                                    int& unique_id,
                                     UnsignedInt32& xintBlockType,
                                     UnsignedInt32& xintBlockColor,
                                     UnsignedInt32& xintMixedElemType,
@@ -1234,7 +1240,7 @@
     try {
         if(!mpReadFEModel)
             throw eOrderError;
-        mpReadFEModel->ReadBlock(xintIndex, xintBlockID,
+        mpReadFEModel->ReadBlock(xintIndex, xintBlockID, unique_id,
             xintBlockType, xintBlockColor, xintMixedElemType,
             xintDefPyramidType, xintMaterialID, xintBlockDimension,
             xintNumTypes, xpaBlockData, xintAttributeOrder, xpadblAttributes);
@@ -1256,10 +1262,12 @@
 
 UnsignedInt32 CCubitFile::ReadNodeSet(UnsignedInt32 xintIndex,
                                       UnsignedInt32& xintNodeSetID,
+                                      int& unique_id,
                                       UnsignedInt32& xintColor,
                                       UnsignedInt32& xintPointSymbol,
                                       UnsignedInt32& xintNumTypes,
-                                      SNodeSetData*& xpaNodeSetData)
+                                      SNodeSetData*& xpaNodeSetData,
+                                      std::vector<char>& bcdata)
 // Try to read the membership of the passed node set index from the read-only file.
 // Note: The 
 // RETURNS: 0 on success, other values indicate error code.
@@ -1268,8 +1276,8 @@
     try {
         if(!mpReadFEModel)
             throw eOrderError;
-        mpReadFEModel->ReadNodeSet(xintIndex, xintNodeSetID,
-            xintColor, xintPointSymbol, xintNumTypes, xpaNodeSetData);
+        mpReadFEModel->ReadNodeSet(xintIndex, xintNodeSetID, unique_id,
+            xintColor, xintPointSymbol, xintNumTypes, xpaNodeSetData, bcdata);
         return eSuccess;
     }
     catch(EErrorCode xeErrorCode) {
@@ -1318,12 +1326,14 @@
 
 UnsignedInt32 CCubitFile::ReadSideSet_11(UnsignedInt32 xintIndex,
                                       UnsignedInt32& xintSideSetID,
+                                      int& unique_id,
                                       UnsignedInt32& xintColor,
                                       UnsignedInt32& xintUseShells,
                                       UnsignedInt32& xintNumTypes,
                                       SSideSetData_11*& xpaSideSetData,
                                       UnsignedInt32& xintNumDistFact,
-                                      double*& xpadblDistribution)
+                                      double*& xpadblDistribution,
+                                      std::vector<char>& bcdata)
 // Try to read the membership of the passed side set index from the read-only file.
 // Note: The 
 // RETURNS: 0 on success, other values indicate error code.
@@ -1332,9 +1342,9 @@
     try {
         if(!mpReadFEModel)
             throw eOrderError;
-        mpReadFEModel->ReadSideSet_11(xintIndex, xintSideSetID,
+        mpReadFEModel->ReadSideSet_11(xintIndex, xintSideSetID, unique_id,
             xintColor, xintUseShells, xintNumTypes, xpaSideSetData,
-            xintNumDistFact, xpadblDistribution);
+            xintNumDistFact, xpadblDistribution, bcdata);
         return eSuccess;
     }
     catch(EErrorCode xeErrorCode) {

Modified: cgm/branches/cubit/util/CubitFile.hpp
===================================================================
--- cgm/branches/cubit/util/CubitFile.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFile.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -30,9 +30,10 @@
 #ifndef CubitFile_HPP
 #define CubitFile_HPP
 
-#include <stdio.h>
+#include <cstdio>
 #include <memory.h>
 #include "CubitUtilConfigure.h"
+#include <vector>
 
 namespace NCubitFile {
 
@@ -159,21 +160,30 @@
                            ConstCharPtr xpachrGroupName,
                            UnsignedInt32 xintNumTypes, SGroupData* xpaGroupData);
   UnsignedInt32 WriteBlock(UnsignedInt32 xintIndex,
-                           UnsignedInt32 xintBlockID, UnsignedInt32 xintBlockType,
+                           UnsignedInt32 xintBlockID, 
+                           int block_unique_id, 
+                           UnsignedInt32 xintBlockType,
                            UnsignedInt32 xintBlockColor, UnsignedInt32 xintMixedElemType,
                            UnsignedInt32 xintDefPyramidType, UnsignedInt32 xintMaterialID,
                            UnsignedInt32 xintBlockDimension,
                            UnsignedInt32 xintNumTypes, SBlockData* xpaBlockData,
                            UnsignedInt32 xintAttributeOrder, double* xpadblAttributes);
   UnsignedInt32 WriteNodeSet(UnsignedInt32 xintIndex,
-                             UnsignedInt32 xintNodeSetID, UnsignedInt32 xintColor,
+                             UnsignedInt32 xintNodeSetID, 
+                             int nodeset_unique_id, 
+                             UnsignedInt32 xintColor,
                              UnsignedInt32 xintPointSymbol,
-                             UnsignedInt32 xintNumTypes, SNodeSetData* xpaNodeSetData);
+                             UnsignedInt32 xintNumTypes, SNodeSetData* xpaNodeSetData,
+                             const std::vector<char>& bcdata
+                             );
   UnsignedInt32 WriteSideSet_11(UnsignedInt32 xintIndex,
-                             UnsignedInt32 xintSideSetID, UnsignedInt32 xintColor,
+                             UnsignedInt32 xintSideSetID,
+                             int sideset_unique_id, 
+                             UnsignedInt32 xintColor,
                              UnsignedInt32 xintUseShells,
                              UnsignedInt32 xintNumTypes, SSideSetData_11* xpaSideSetData,
-                             UnsignedInt32 xintNumDistFact, double* xpadblDistribution);
+                             UnsignedInt32 xintNumDistFact, double* xpadblDistribution,
+                             const std::vector<char>& bcdata);
   UnsignedInt32 EndWriteFEModel();
   
   UnsignedInt32 BeginReadFEModel(HModel xintFEModel,
@@ -194,16 +204,17 @@
   UnsignedInt32 ReadGroupMembers(UnsignedInt32 xintIndex,
                                  UnsignedInt32& xintNumTypes, SGroupData*& xpaGroupData);
     UnsignedInt32 ReadBlock(UnsignedInt32 xintIndex,
-        UnsignedInt32& xintBlockID, UnsignedInt32& xintBlockType,
+        UnsignedInt32& xintBlockID, int& unique_id, UnsignedInt32& xintBlockType,
         UnsignedInt32& xintBlockColor, UnsignedInt32& xintMixedElemType,
         UnsignedInt32& xintDefPyramidType, UnsignedInt32& xintMaterialID,
         UnsignedInt32& xintBlockDimension,
         UnsignedInt32& xintNumTypes, SBlockData*& xpaBlockData,
         UnsignedInt32& xintAttributeOrder, double*& xpadblAttributes);
     UnsignedInt32 ReadNodeSet(UnsignedInt32 xintIndex,
-        UnsignedInt32& xintNodeSetID, UnsignedInt32& xintColor,
+        UnsignedInt32& xintNodeSetID, int& unique_id, UnsignedInt32& xintColor,
         UnsignedInt32& xintPointSymbol,
-        UnsignedInt32& xintNumTypes, SNodeSetData*& xpaNodeSetData);
+        UnsignedInt32& xintNumTypes, SNodeSetData*& xpaNodeSetData,
+        std::vector<char>& bcdata);
 
     // read old sideset format
     UnsignedInt32 ReadSideSet_10(UnsignedInt32 xintIndex,
@@ -214,10 +225,11 @@
     
     // read new sideset format
     UnsignedInt32 ReadSideSet_11(UnsignedInt32 xintIndex,
-        UnsignedInt32& xintSideSetID, UnsignedInt32& xintColor,
+        UnsignedInt32& xintSideSetID, int& unique_id, UnsignedInt32& xintColor,
         UnsignedInt32& xintUseShells,
         UnsignedInt32& xintNumTypes, SSideSetData_11*& xpaSideSetData,
-        UnsignedInt32& xintNumDistFact, double*& xpadblDistribution);
+        UnsignedInt32& xintNumDistFact, double*& xpadblDistribution,
+        std::vector<char>& bcdata);
     
     UnsignedInt32 EndReadFEModel();
 

Modified: cgm/branches/cubit/util/CubitFileFEModel.cpp
===================================================================
--- cgm/branches/cubit/util/CubitFileFEModel.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFileFEModel.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -396,6 +396,7 @@
 
 void CFEModel::WriteBlock(UnsignedInt32 xintIndex,
                           UnsignedInt32 xintBlockID,
+                          int unique_id,
                           UnsignedInt32 xintBlockType,
                           UnsignedInt32 xintBlockColor,
                           UnsignedInt32 xintMixedElemType,
@@ -464,6 +465,9 @@
         }
         if(xintAttributeOrder)
             lpIO->Write(xpadblAttributes, xintAttributeOrder);
+
+        lpIO->Write("id", 2);
+        lpIO->Write(reinterpret_cast<UnsignedInt32*>(&unique_id), 1);
         
         mpaBlocks[xintIndex].mintBlockLength = lpIO->EndWriteBlock();
         mFEModel.mintFEModelLength += mpaBlocks[xintIndex].mintBlockLength;
@@ -478,10 +482,12 @@
 
 void CFEModel::WriteNodeSet(UnsignedInt32 xintIndex,
                             UnsignedInt32 xintNodeSetID,
+                            int unique_id,
                             UnsignedInt32 xintColor,
                             UnsignedInt32 xintPointSymbol,
                             UnsignedInt32 xintNumTypes,
-                            SNodeSetData* xpaNodeSetData)
+                            SNodeSetData* xpaNodeSetData,
+                            const std::vector<char>& bcdata)
 {
     if(!mpWriteFile)
         throw CCubitFile::eFileWriteError;
@@ -528,6 +534,17 @@
                 xpaNodeSetData[lintNodeSet].mintMemberCount);
         }
         
+        UnsignedInt32 size = bcdata.size();
+        if(size)
+        {
+          lpIO->Write("bc", 2);
+          lpIO->Write(&size, 1);
+          lpIO->Write(&bcdata[0], size);
+        }
+
+        lpIO->Write("id", 2);
+        lpIO->Write(reinterpret_cast<UnsignedInt32*>(&unique_id), 1);
+        
         mpaNodeSets[xintIndex].mintNodeSetLength = lpIO->EndWriteBlock();
         mFEModel.mintFEModelLength += mpaNodeSets[xintIndex].mintNodeSetLength;
         delete lpIO;
@@ -541,12 +558,14 @@
 
 void CFEModel::WriteSideSet_11(UnsignedInt32 xintIndex,
                             UnsignedInt32 xintSideSetID,
+                            int unique_id,
                             UnsignedInt32 xintColor,
                             UnsignedInt32 xintUseShells,
                             UnsignedInt32 xintNumTypes,
                             SSideSetData_11* xpaSideSetData,
                             UnsignedInt32 xintNumDistFact,
-                            double* xpadblDistribution)
+                            double* xpadblDistribution,
+                            const std::vector<char>& bcdata)
 {
     if(!mpWriteFile)
         throw CCubitFile::eFileWriteError;
@@ -621,7 +640,18 @@
         }
         if(xintNumDistFact)
             lpIO->Write(xpadblDistribution, xintNumDistFact);
+
+        UnsignedInt32 size = bcdata.size();
+        if(size)
+        {
+          lpIO->Write("bc", 2);
+          lpIO->Write(&size, 1);
+          lpIO->Write(&bcdata[0], size);
+        }
         
+        lpIO->Write("id", 2);
+        lpIO->Write(reinterpret_cast<UnsignedInt32*>(&unique_id), 1);
+        
         mpaSideSets[xintIndex].mintSideSetLength = lpIO->EndWriteBlock();
         mFEModel.mintFEModelLength += mpaSideSets[xintIndex].mintSideSetLength;
         delete lpIO;
@@ -991,6 +1021,7 @@
 
 void CFEModel::ReadBlock(UnsignedInt32 xintIndex,
                          UnsignedInt32& xintBlockID,
+                         int& unique_id,
                          UnsignedInt32& xintBlockType,
                          UnsignedInt32& xintBlockColor,
                          UnsignedInt32& xintMixedElemType,
@@ -1002,6 +1033,7 @@
                          UnsignedInt32& xintAttributeOrder,
                          double*& xpadblAttributes)
 {
+  unique_id = 0;
     if(!mpReadFile)
         throw CCubitFile::eFileReadError;
     if(xintIndex >= mFEModel.mintBlockCount)
@@ -1035,6 +1067,7 @@
         CIOWrapper* lpIO = new CIOWrapper(mpReadFile, mFEModel.mintFEModelEndian);
         lpIO->BeginReadBlock(mintFEModelOffset,
             mpaBlocks[xintIndex].mintMemberOffset);
+        long start_location = lpIO->GetLocation();
         for(UnsignedInt32 lintType = 0; lintType < xintNumTypes; lintType++) {
             lpIO->Read(&xpaBlockData[lintType].mintMemberType, 1);
             lpIO->Read(&xpaBlockData[lintType].mintMemberCount, 1);
@@ -1053,6 +1086,23 @@
         }
         if(xintAttributeOrder)
             lpIO->Read(xpadblAttributes, xintAttributeOrder);
+        
+        // see if there is more data
+        int diff = lpIO->GetLocation() - start_location;
+        int remaining = diff - mpaBlocks[xintIndex].mintBlockLength;
+        while(remaining)
+        {
+          // remaining data could be bc data
+          char type[2];
+          lpIO->Read(type, 2);
+          if(type[0] == 'i' && type[1] == 'd')
+          {
+            lpIO->Read(reinterpret_cast<UnsignedInt32*>(&unique_id), 1);
+          }
+          remaining = (lpIO->GetLocation() - start_location) -
+            mpaBlocks[xintIndex].mintBlockLength;
+        }
+
         lpIO->EndReadBlock();
         delete lpIO;
     }
@@ -1064,11 +1114,14 @@
 
 void CFEModel::ReadNodeSet(UnsignedInt32 xintIndex,
                            UnsignedInt32& xintNodeSetID,
+                           int& unique_id,
                            UnsignedInt32& xintColor,
                            UnsignedInt32& xintPointSymbol,
                            UnsignedInt32& xintNumTypes,
-                           SNodeSetData*& xpaNodeSetData)
+                           SNodeSetData*& xpaNodeSetData,
+                           std::vector<char>& bcdata)
 {
+  unique_id = 0;
     if(!mpReadFile)
         throw CCubitFile::eFileReadError;
     if(xintIndex >= mFEModel.mintNodeSetCount)
@@ -1081,7 +1134,8 @@
     xintPointSymbol = mpaNodeSets[xintIndex].mintNodeSetPointSym;
     xintColor = mpaNodeSets[xintIndex].mintNodeSetColor;
 
-    if(xintNumTypes) {
+    if(xintNumTypes) 
+    {
         // Resize the node set return buffer if necessary and then set the return
         // pointers to the buffer.
         xpaNodeSetData = AdjustBuffer(xintNumTypes,
@@ -1095,6 +1149,7 @@
         CIOWrapper* lpIO = new CIOWrapper(mpReadFile, mFEModel.mintFEModelEndian);
         lpIO->BeginReadBlock(mintFEModelOffset,
             mpaNodeSets[xintIndex].mintMemberOffset);
+        long start_location = lpIO->GetLocation();
         for(UnsignedInt32 lintType = 0; lintType < xintNumTypes; lintType++) {
             lpIO->Read(&xpaNodeSetData[lintType].mintMemberType, 1);
             lpIO->Read(&xpaNodeSetData[lintType].mintMemberCount, 1);
@@ -1111,6 +1166,31 @@
 
             lpIDs = &lpIDs[lintNumMembers];
         }
+        
+        // see if there is more data
+        int diff = lpIO->GetLocation() - start_location;
+        int remaining = diff - mpaNodeSets[xintIndex].mintNodeSetLength;
+        while(remaining)
+        {
+          // remaining data could be bc data
+          char type[2];
+          lpIO->Read(type, 2);
+          if(type[0] == 'b' && type[1] == 'c')
+          {
+            // get serialize data size
+            UnsignedInt32 size;
+            lpIO->Read(&size, 1);
+            bcdata.resize(size);
+            lpIO->Read(&bcdata[0], size);
+          }
+          else if(type[0] == 'i' && type[1] == 'd')
+          {
+            lpIO->Read(reinterpret_cast<UnsignedInt32*>(&unique_id), 1);
+          }
+          remaining = (lpIO->GetLocation() - start_location) -
+            mpaNodeSets[xintIndex].mintNodeSetLength;
+        }
+
         lpIO->EndReadBlock();
         delete lpIO;
     }
@@ -1220,13 +1300,16 @@
 
 void CFEModel::ReadSideSet_11(UnsignedInt32 xintIndex,
                            UnsignedInt32& xintSideSetID,
+                           int& unique_id,
                            UnsignedInt32& xintColor,
                            UnsignedInt32& xintUseShells,
                            UnsignedInt32& xintNumTypes,
                            SSideSetData_11*& xpaSideSetData,
                            UnsignedInt32& xintNumDistFact,
-                           double*& xpadblDistribution)
+                           double*& xpadblDistribution,
+                           std::vector<char>& bcdata)
 {
+  unique_id = 0;
     if(!mpReadFile)
         throw CCubitFile::eFileReadError;
     if(xintIndex >= mFEModel.mintSideSetCount)
@@ -1263,6 +1346,7 @@
         CIOWrapper* lpIO = new CIOWrapper(mpReadFile, mFEModel.mintFEModelEndian);
         lpIO->BeginReadBlock(mintFEModelOffset,
             mpaSideSets[xintIndex].mintMemberOffset);
+        long start_location = lpIO->GetLocation();
         for(UnsignedInt32 lintType = 0; lintType < xintNumTypes; lintType++) {
             lpIO->Read(&xpaSideSetData[lintType].mintMemberCount, 1);
             
@@ -1300,6 +1384,32 @@
         }
         if(xintNumDistFact)
             lpIO->Read(xpadblDistribution, xintNumDistFact);
+
+        // see if there is more data
+        int diff = lpIO->GetLocation() - start_location;
+        int remaining = diff - mpaSideSets[xintIndex].mintSideSetLength;
+        while(remaining)
+        {
+          // remaining data could be bc data
+          char type[2];
+          lpIO->Read(type, 2);
+          if(type[0] == 'b' && type[1] == 'c')
+          {
+            // get serialize data size
+            UnsignedInt32 size;
+            lpIO->Read(&size, 1);
+            bcdata.resize(size);
+            lpIO->Read(&bcdata[0], size);
+          }
+          // or unique id
+          else if(type[0] == 'i' && type[1] == 'd')
+          {
+            lpIO->Read(reinterpret_cast<UnsignedInt32*>(&unique_id), 1);
+          }
+          remaining = (lpIO->GetLocation() - start_location) -
+            mpaSideSets[xintIndex].mintSideSetLength;
+        }
+
         lpIO->EndReadBlock();
         delete lpIO;
     }

Modified: cgm/branches/cubit/util/CubitFileFEModel.hpp
===================================================================
--- cgm/branches/cubit/util/CubitFileFEModel.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFileFEModel.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -27,12 +27,13 @@
 
 *******************************************************************************/
 
+#ifndef CubitFileFEModel_HPP
+#define CubitFileFEModel_HPP
+
 #include "CubitFileMetaData.hpp"
 #include "CubitUtilConfigure.h"
+#include <vector>
 
-#ifndef CubitFileFEModel_HPP
-#define CubitFileFEModel_HPP
-
 namespace NCubitFile {
 
 class CUBIT_UTIL_EXPORT CFEModel {
@@ -53,21 +54,23 @@
         UnsignedInt32 xintGroupType, const char* xpachrGroupName,
         UnsignedInt32 xintNumTypes, SGroupData* xpaGroupData);
     void WriteBlock(UnsignedInt32 xintIndex,
-        UnsignedInt32 xintBlockID, UnsignedInt32 xintBlockType,
+        UnsignedInt32 xintBlockID, int unique_id, UnsignedInt32 xintBlockType,
         UnsignedInt32 xintBlockColor, UnsignedInt32 xintMixedElemType,
         UnsignedInt32 xintDefPyramidType, UnsignedInt32 xintMaterialID,
         UnsignedInt32 xintBlockDimension,
         UnsignedInt32 xintNumTypes, SBlockData* xpaBlockData,
         UnsignedInt32 xintAttributeOrder, double* xpadblAttributes);
     void WriteNodeSet(UnsignedInt32 xintIndex,
-        UnsignedInt32 xintNodeSetID, UnsignedInt32 xintColor,
+        UnsignedInt32 xintNodeSetID, int unique_id, UnsignedInt32 xintColor,
         UnsignedInt32 xintPointSymbol,
-        UnsignedInt32 xintNumTypes, SNodeSetData* xpaNodeSetData);
+        UnsignedInt32 xintNumTypes, SNodeSetData* xpaNodeSetData,
+        const std::vector<char>& bcdata);
     void WriteSideSet_11(UnsignedInt32 xintIndex,
-        UnsignedInt32 xintSideSetID, UnsignedInt32 xintColor,
+        UnsignedInt32 xintSideSetID, int unique_id, UnsignedInt32 xintColor,
         UnsignedInt32 xintUseShells,
         UnsignedInt32 xintNumTypes, SSideSetData_11* xpaSideSetData,
-        UnsignedInt32 xintNumDistFact, double* xpadblDistribution);
+        UnsignedInt32 xintNumDistFact, double* xpadblDistribution,
+        const std::vector<char>& bcdata);
     UnsignedInt32 EndWrite();
     
     void InitRead(FILE* xpFile, UnsignedInt32 xintAbsoluteOffset,
@@ -84,26 +87,28 @@
     void ReadGroupMembers(UnsignedInt32 xintIndex,
         UnsignedInt32& xintNumTypes, SGroupData*& xpaGroupData);
     void ReadBlock(UnsignedInt32 xintIndex,
-        UnsignedInt32& xintBlockID, UnsignedInt32& xintBlockType,
+        UnsignedInt32& xintBlockID, int& unique_id, UnsignedInt32& xintBlockType,
         UnsignedInt32& xintBlockColor, UnsignedInt32& xintMixedElemType,
         UnsignedInt32& xintDefPyramidType, UnsignedInt32& xintMaterialID,
         UnsignedInt32& xintBlockDimension,
         UnsignedInt32& xintNumTypes, SBlockData*& xpaBlockData,
         UnsignedInt32& xintAttributeOrder, double*& xpadblAttributes);
     void ReadNodeSet(UnsignedInt32 xintIndex,
-        UnsignedInt32& xintNodeSetID, UnsignedInt32& xintColor,
+        UnsignedInt32& xintNodeSetID, int& unique_id, UnsignedInt32& xintColor,
         UnsignedInt32& xintPointSymbol,
-        UnsignedInt32& xintNumTypes, SNodeSetData*& xpaNodeSetData);
+        UnsignedInt32& xintNumTypes, SNodeSetData*& xpaNodeSetData,
+        std::vector<char>& bcdata);
     void ReadSideSet_10(UnsignedInt32 xintIndex,
         UnsignedInt32& xintSideSetID, UnsignedInt32& xintColor,
         UnsignedInt32& xintUseShells,
         UnsignedInt32& xintNumTypes, SSideSetData_10*& xpaSideSetData,
         UnsignedInt32& xintNumDistFact, double*& xpadblDistribution);
     void ReadSideSet_11(UnsignedInt32 xintIndex,
-        UnsignedInt32& xintSideSetID, UnsignedInt32& xintColor,
+        UnsignedInt32& xintSideSetID, int& unique_id, UnsignedInt32& xintColor,
         UnsignedInt32& xintUseShells,
         UnsignedInt32& xintNumTypes, SSideSetData_11*& xpaSideSetData,
-        UnsignedInt32& xintNumDistFact, double*& xpadblDistribution);
+        UnsignedInt32& xintNumDistFact, double*& xpadblDistribution,
+        std::vector<char>& bcdata);
     void EndRead();
     
     CMetaData& GetGeomMetaData();

Modified: cgm/branches/cubit/util/CubitFileIOWrapper.cpp
===================================================================
--- cgm/branches/cubit/util/CubitFileIOWrapper.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFileIOWrapper.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -27,7 +27,7 @@
 *******************************************************************************/
 
 #include "CubitFileIOWrapper.hpp"
-#include <string.h>
+#include <cstring>
 
 using namespace NCubitFile;
 
@@ -240,4 +240,9 @@
 {
     mintBlockStart = mintBlockEnd = 0;
 }
+    
+long CIOWrapper::GetLocation()
+{
+  return ftell(mpFile);
+}
 

Modified: cgm/branches/cubit/util/CubitFileIOWrapper.hpp
===================================================================
--- cgm/branches/cubit/util/CubitFileIOWrapper.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFileIOWrapper.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -63,6 +63,8 @@
     virtual char* Read();
     virtual void EndReadBlock();
     virtual UnsignedInt32 get_endian() { return mintSwapEndian; }  
+    
+    virtual long GetLocation();
 
 private:
     FILE* mpFile;

Modified: cgm/branches/cubit/util/CubitFileMetaData.cpp
===================================================================
--- cgm/branches/cubit/util/CubitFileMetaData.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFileMetaData.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -28,7 +28,7 @@
 
 #include "CubitFileMetaData.hpp"
 #include "CubitFileIOWrapper.hpp"
-#include <string.h>
+#include <cstring>
 
 using namespace NCubitFile;
 

Modified: cgm/branches/cubit/util/CubitFileUtil.cpp
===================================================================
--- cgm/branches/cubit/util/CubitFileUtil.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitFileUtil.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -17,7 +17,7 @@
   #include <sys/types.h>
   #include <sys/stat.h>
   #include <dirent.h>
-  #include <stdlib.h>
+  #include <cstdlib>
   #include <sys/param.h>
   #include <unistd.h>
   #include <pwd.h>

Modified: cgm/branches/cubit/util/CubitInputFile.hpp
===================================================================
--- cgm/branches/cubit/util/CubitInputFile.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitInputFile.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -2,7 +2,7 @@
 #define CUBITINPUTFILE_HPP
 
 #include "CubitString.hpp"
-#include <stdio.h>
+#include <cstdio>
 #include "CubitMessage.hpp"
 
 struct CubitInputFile

Modified: cgm/branches/cubit/util/CubitMatrix.cpp
===================================================================
--- cgm/branches/cubit/util/CubitMatrix.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitMatrix.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -3,7 +3,7 @@
 //- Owner: Dan Goodrich
 //- Checked by:
 
-#include <assert.h>
+#include <cassert>
 
 #include "CubitMatrix.hpp"
 #include "CubitMessage.hpp"
@@ -394,7 +394,6 @@
       assert( fabs(det) > CUBIT_DBL_MIN );
     
       matrix_inverse.set(0,0, matrixPtr[0][0]);
-      matrix_inverse *= det_inv;
     }
 
     if ( numRows == 2 ) {
@@ -402,7 +401,6 @@
       matrix_inverse.set(1,0,-matrixPtr[1][0]);
       matrix_inverse.set(0,1,-matrixPtr[0][1]);
       matrix_inverse.set(1,1, matrixPtr[0][0]);
-      matrix_inverse *= det_inv;
     }
 
     if ( numRows == 3 ) {

Modified: cgm/branches/cubit/util/CubitMessage.cpp
===================================================================
--- cgm/branches/cubit/util/CubitMessage.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitMessage.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -6,8 +6,8 @@
 #include "CubitDefines.h"
 #include "CubitString.hpp"
 #include "CubitUtil.hpp"
-#include <assert.h>
-#include <string.h>
+#include <cassert>
+#include <cstring>
 #include <vector>
 
 #include "SettingHandler.hpp"
@@ -33,6 +33,7 @@
 int CubitMessage::infoFlag = CUBIT_TRUE;
 int CubitMessage::diagnosticFlag = CUBIT_FALSE;
 int CubitMessage::warningFlag = CUBIT_TRUE;
+int CubitMessage::errorFlag = CUBIT_TRUE;
 std::ofstream* CubitMessage::loggingStream = NULL;
 CubitString* CubitMessage::loggingFile = NULL;
 std::ofstream* CubitMessage::loggingErrorStream = NULL;
@@ -56,6 +57,7 @@
 {
   infoFlag      = CUBIT_TRUE;
   warningFlag   = CUBIT_TRUE;
+  errorFlag     = CUBIT_TRUE;
   diagnosticFlag= CUBIT_FALSE;
   loggingStream = NULL;
   loggingFile   = NULL;
@@ -66,108 +68,108 @@
     // Initialize the debugFlag array
   static MessageFlag staticDebugFlag[] =
   {
-    MessageFlag( 0, "UNUSED"),
-    MessageFlag( 1, "Debug Graphics toggle for some debug options."),
-    MessageFlag( 2, "Whisker weaving information"),
-    MessageFlag( 3, "Timing information for 3D Meshing routines."),
-    MessageFlag( 4, "Graphics Debugging (DrawingTool)"),
-    MessageFlag( 5, "FastQ debugging"),
-    MessageFlag( 6, "Submapping graphics debugging"),
-    MessageFlag( 7, "Knife progress whisker weaving information"),
-    MessageFlag( 8, "Mapping Face debug / Linear Programing debug "),
-    MessageFlag( 9, "Paver Debugging"),
-    MessageFlag(10, "WW: removed hex seam flag"),
-    MessageFlag(11, "Nodeset Associativity debugging"),
-    MessageFlag(12, "Fastq activity"),
-    MessageFlag(13, "Mesh entities"),
-    MessageFlag(14, "Model activity"),
-    MessageFlag(15, "2.5D Debugging (Project, Translate, Rotate)"),
-    MessageFlag(16, "RefFace activity"),
-    MessageFlag(17, "Use Count debugging"),
-    MessageFlag(18, "Webcut debugging"),
-    MessageFlag(19, "Feature Merge / Unmerge debugging"),
-    MessageFlag(20, "Parallel meshing activity"),
-    MessageFlag(21, "Boundary Layer Tool Debugging"),
-    MessageFlag(22, "ExodusMesh sizing function debugging"),
-    MessageFlag(23, "Draw after joining chords in WW"),
-    MessageFlag(24, "SelfCrossingLoop (and derivatives) debug info"),
-    MessageFlag(25, "Extra invalidity checking in WW"),
-    MessageFlag(26, "Surface Smoothing"),
-    MessageFlag(27, "Primal Construction debugging, see also flag 70"),
-    MessageFlag(28, "Plastering debugging"),
-    MessageFlag(29, "Volume SubMapping"),
-    MessageFlag(30, "Volume Mapping"),
-    MessageFlag(31, "CleanUp debugging"),
-    MessageFlag(32, "Pyramid debugging"),
-    MessageFlag(33, "Whisker Weaving inside chord list face drawing"),
-    MessageFlag(34, "If on Whisker Weaving doesn't merge sheets"),
-    MessageFlag(35, "If on WW query displays sheets before joining chords"),
-    MessageFlag(36, "Enable/Disable idr_keyword_debugger function"),
-    MessageFlag(37, "Superdrive debugging"),
-    MessageFlag(38, "WW hex formation messages"),
-    MessageFlag(39, "Doublet Pillower graphics output"),
-    MessageFlag(40, "Element Quality debugging output"),
-    MessageFlag(41, "Check_join adjacency check"),
-    MessageFlag(42, "Auto vertex type and sweep verification"),
-    MessageFlag(43, "Programmer Errors for SubMapping"),
-    MessageFlag(44, "Submapping Graphics Debugging"),
-    MessageFlag(45, "Pillow Sheet debugging"),
-    MessageFlag(46, "Paver breakout detection (expensive)"),
-    MessageFlag(47, "Extra LP debugging (see flag 8 also)"),
-    MessageFlag(48, "Geometry sizing function."),
-    MessageFlag(49, "Draws Face by Face Creation in Paving"),
-    MessageFlag(50, "Debugging for AutoSchemeSelect"),
-    MessageFlag(51, "Modified Paver (row by row, more intersection checking)"),
-    MessageFlag(52, "User Interface: If flag is enabled, filenames being\n"
-                "\t\t\tused for input will be echoed and each input line\n"
-                "\t\t\twill be echoed prior to being parsed."),
-    MessageFlag(53, "Surface Morpher debugging"),
-    MessageFlag(54, "Parser debugging"),
-    MessageFlag(55, "Stairtool general debugging"),
-    MessageFlag(56, "Stairtool face intersection debugging"),
-    MessageFlag(57, "Relative Interval/Length setting"),
-    MessageFlag(58, "StcVertex debugging of Whisker Weaving" ),
-    MessageFlag(59, "VGI developer error"),
-    MessageFlag(60, "StcVertex debugging of Looping" ),
-    MessageFlag(61, "List number of points used in curve faceting" ),
-    MessageFlag(62, "Print verbose information on group operations"),
-    MessageFlag(63, "Label Whisker Weaving diagrams tersely"),
-    MessageFlag(64, "No label on Whisker Weaving diagrams"),
-    MessageFlag(65, "Volume Morpher debugging"),
-    MessageFlag(66, "Print debug information on importing Pro/E geometry"),
-    MessageFlag(67, "List number of triangles used in surface faceting" ),
-    MessageFlag(68, "Debug information on tetrizing volumes" ),
-    MessageFlag(69, "Debug information on tet mesher geometry access" ),
-    MessageFlag(70, "STC Pillowing, see also flag 27" ),
-    MessageFlag(71, "Hex-Tet Debug Flag"),
-    MessageFlag(72, "DoubletPillower text messages"),
-    MessageFlag(73, "Auto Surface debugging (use new auto surf select)"),
-    MessageFlag(74, "Feature-based decomposition info"),
-    MessageFlag(75, "Many-to-many sweep imprint debugging"),
-    MessageFlag(76, "Virtual point and partition curve"),
-    MessageFlag(77, "Volume interval matching"),
-    MessageFlag(78, "Tipton Smoother jacobian modification enabler"),
-    MessageFlag(79, "VoidCleanupTool debugging"),
-    MessageFlag(80, "Hex-Tet informational messages"),
-    MessageFlag(81, "Curve Morpher Debugging"),
-    MessageFlag(82, "Diamond debugging"),
-    MessageFlag(83, "AutoSizer debugging"),
-    MessageFlag(84, "Surface auto decomposition"),
-    MessageFlag(85, "U-SubMapping debugging"),
-    MessageFlag(86, "Virtual curve and partition surface"),
-    MessageFlag(87, "Composite curve and composite surface"),
-    MessageFlag(88, "Volume partitioning"),
-    MessageFlag(89, "Tet meshing warning and debug messages"),
-    MessageFlag(90, "Geometry attributes"),
-    MessageFlag(91, "Smoothing Debug Output"),
-    MessageFlag(92, "Print name changed warnings"),
-    MessageFlag(93, "Hex Fix Up"),
-    MessageFlag(94, "Entity name attribute"),
-    MessageFlag(95, "Group imprint errors"),
-    MessageFlag(96, "GraftTool debugging"),
-    MessageFlag(97, "Quality details"),
-    MessageFlag(98, "Color code imported THEX meshes"),
-    MessageFlag(99, "Geometry creation"),
+    MessageFlag(  0, "UNUSED"),
+    MessageFlag(  1, "Debug Graphics toggle for some debug options."),
+    MessageFlag(  2, "Whisker weaving information"),
+    MessageFlag(  3, "Timing information for 3D Meshing routines."),
+    MessageFlag(  4, "Graphics Debugging (DrawingTool)"),
+    MessageFlag(  5, "FastQ debugging"),
+    MessageFlag(  6, "Submapping graphics debugging"),
+    MessageFlag(  7, "Knife progress whisker weaving information"),
+    MessageFlag(  8, "Mapping Face debug / Linear Programing debug "),
+    MessageFlag(  9, "Paver Debugging"),
+    MessageFlag( 10, "WW: removed hex seam flag"),
+    MessageFlag( 11, "Nodeset Associativity debugging"),
+    MessageFlag( 12, "Fastq activity"),
+    MessageFlag( 13, "Mesh entities"),
+    MessageFlag( 14, "Model activity"),
+    MessageFlag( 15, "2.5D Debugging (Project, Translate, Rotate)"),
+    MessageFlag( 16, "RefFace activity"),
+    MessageFlag( 17, "Use Count debugging"),
+    MessageFlag( 18, "Webcut debugging"),
+    MessageFlag( 19, "Feature Merge / Unmerge debugging"),
+    MessageFlag( 20, "Parallel meshing activity"),
+    MessageFlag( 21, "Boundary Layer Tool Debugging"),
+    MessageFlag( 22, "ExodusMesh sizing function debugging"),
+    MessageFlag( 23, "Draw after joining chords in WW"),
+    MessageFlag( 24, "SelfCrossingLoop (and derivatives) debug info"),
+    MessageFlag( 25, "Extra invalidity checking in WW"),
+    MessageFlag( 26, "Surface Smoothing"),
+    MessageFlag( 27, "Primal Construction debugging, see also flag 70"),
+    MessageFlag( 28, "Plastering debugging"),
+    MessageFlag( 29, "Volume SubMapping"),
+    MessageFlag( 30, "Volume Mapping"),
+    MessageFlag( 31, "CleanUp debugging"),
+    MessageFlag( 32, "Pyramid debugging"),
+    MessageFlag( 33, "Whisker Weaving inside chord list face drawing"),
+    MessageFlag( 34, "If on Whisker Weaving doesn't merge sheets"),
+    MessageFlag( 35, "If on WW query displays sheets before joining chords"),
+    MessageFlag( 36, "Enable/Disable idr_keyword_debugger function"),
+    MessageFlag( 37, "Superdrive debugging"),
+    MessageFlag( 38, "WW hex formation messages"),
+    MessageFlag( 39, "Doublet Pillower graphics output"),
+    MessageFlag( 40, "Element Quality debugging output"),
+    MessageFlag( 41, "Check_join adjacency check"),
+    MessageFlag( 42, "Auto vertex type and sweep verification"),
+    MessageFlag( 43, "Programmer Errors for SubMapping"),
+    MessageFlag( 44, "Submapping Graphics Debugging"),
+    MessageFlag( 45, "Pillow Sheet debugging"),
+    MessageFlag( 46, "Paver breakout detection (expensive)"),
+    MessageFlag( 47, "Extra LP debugging (see flag 8 also)"),
+    MessageFlag( 48, "Geometry sizing function."),
+    MessageFlag( 49, "Draws Face by Face Creation in Paving"),
+    MessageFlag( 50, "Debugging for AutoSchemeSelect"),
+    MessageFlag( 51, "Modified Paver: row by row, more intersection checks"),
+    MessageFlag( 52, "User Interface: If flag is enabled, filenames being\n"
+                "\t\t\t\tused for input will be echoed and each input\n"
+                "\t\t\t\tline will be echoed prior to being parsed."),
+    MessageFlag( 53, "Surface Morpher debugging"),
+    MessageFlag( 54, "Parser debugging"),
+    MessageFlag( 55, "Stairtool general debugging"),
+    MessageFlag( 56, "Stairtool face intersection debugging"),
+    MessageFlag( 57, "Relative Interval/Length setting"),
+    MessageFlag( 58, "StcVertex debugging of Whisker Weaving" ),
+    MessageFlag( 59, "VGI developer error"),
+    MessageFlag( 60, "StcVertex debugging of Looping" ),
+    MessageFlag( 61, "List number of points used in curve faceting" ),
+    MessageFlag( 62, "Print verbose information on group operations"),
+    MessageFlag( 63, "Label Whisker Weaving diagrams tersely"),
+    MessageFlag( 64, "No label on Whisker Weaving diagrams"),
+    MessageFlag( 65, "Volume Morpher debugging"),
+    MessageFlag( 66, "Print debug information on importing Pro/E geometry"),
+    MessageFlag( 67, "List number of triangles used in surface faceting" ),
+    MessageFlag( 68, "Debug information on tetrizing volumes" ),
+    MessageFlag( 69, "Debug information on tet mesher geometry access" ),
+    MessageFlag( 70, "STC Pillowing, see also flag 27" ),
+    MessageFlag( 71, "Hex-Tet Debug Flag"),
+    MessageFlag( 72, "DoubletPillower text messages"),
+    MessageFlag( 73, "Auto Surface debugging (use new auto surf select)"),
+    MessageFlag( 74, "Feature-based decomposition info"),
+    MessageFlag( 75, "Many-to-many sweep imprint debugging"),
+    MessageFlag( 76, "Virtual point and partition curve"),
+    MessageFlag( 77, "Volume interval matching"),
+    MessageFlag( 78, "Tipton Smoother jacobian modification enabler"),
+    MessageFlag( 79, "VoidCleanupTool debugging"),
+    MessageFlag( 80, "Hex-Tet informational messages"),
+    MessageFlag( 81, "Curve Morpher Debugging"),
+    MessageFlag( 82, "Diamond debugging"),
+    MessageFlag( 83, "AutoSizer debugging"),
+    MessageFlag( 84, "Surface auto decomposition"),
+    MessageFlag( 85, "U-SubMapping debugging"),
+    MessageFlag( 86, "Virtual curve and partition surface"),
+    MessageFlag( 87, "Composite curve and composite surface"),
+    MessageFlag( 88, "Volume partitioning"),
+    MessageFlag( 89, "Tet meshing warning and debug messages"),
+    MessageFlag( 90, "Geometry attributes"),
+    MessageFlag( 91, "Smoothing Debug Output"),
+    MessageFlag( 92, "Print name changed warnings"),
+    MessageFlag( 93, "Hex Fix Up"),
+    MessageFlag( 94, "Entity name attribute"),
+    MessageFlag( 95, "Group imprint errors"),
+    MessageFlag( 96, "GraftTool debugging"),
+    MessageFlag( 97, "Quality details"),
+    MessageFlag( 98, "Color code imported THEX meshes"),
+    MessageFlag( 99, "Geometry creation"),
     MessageFlag(100, "Skew Control debugging"),
     MessageFlag(101, "Parsing debugging"),
     MessageFlag(102, "CAEntityId debugging"),
@@ -179,7 +181,7 @@
     MessageFlag(108, "Simulog tetmesher debugging"),
     MessageFlag(109, "Transition schemes debugging"),
     MessageFlag(110, "Mesh Defined Geometry"),
-    MessageFlag(111, "Tri mesher debugging"),
+    MessageFlag(111, "TriAdvance mesher debugging"),
     MessageFlag(112, "Auto Detail Suppression"),
     MessageFlag(113, "Extra Multi-sweep/sweep debugging"),
     MessageFlag(114, "Blend Finder Debugging"),
@@ -191,8 +193,8 @@
     MessageFlag(120, "Print unassociated node locations on import mesh"),
     MessageFlag(121, "Print verbose infeasible match interval messages"),
     MessageFlag(122, "Mesh-Based Geometry Debug Information"),
-    MessageFlag(123, "Collect memory statistics from Tetmesh-GHS3D"),
-    MessageFlag(124, "Print verbose debugging information from Tetmesh-GHS3D"),
+    MessageFlag(123, "Collect memory statistics from Tetmesher"),
+    MessageFlag(124, "Print verbose Tetmesher debugging information"),
     MessageFlag(125, "Mesh refinement debugging"),
     MessageFlag(126, "Surface Splicer debugging"),
     MessageFlag(127, "SculptingTool debug flag"),
@@ -225,7 +227,7 @@
     MessageFlag(154, "Split Surface Debugging"),
     MessageFlag(155, "Meshing Benchmarks Summary"),
     MessageFlag(156, "CAMAL Paver CleanUp debuging"),
-    MessageFlag(157, "Skeleton Sizing Function Debugging (timing & counts)"),
+    MessageFlag(157, "Skeleton Sizing Function timing and counts"),
     MessageFlag(158, "Write a CAMAL debug file"),
     MessageFlag(159, "Read a CAMAL debug file"),
     MessageFlag(160, "CAMAL debug file format is binary"),
@@ -244,9 +246,44 @@
     MessageFlag(173, "Enable Quad-Coarsening Pinch inside corners"),
     MessageFlag(174, "Enable Quad-Coarsening Pinch outside corners"),
     MessageFlag(175, "Disable creation of crashbackup.cub during crash"),
-    MessageFlag(176, "Disable UCP Curve Smoothing"),
-    MessageFlag(177, "Enable Unconstrained Plastering Debug Drawing")
-
+    MessageFlag(176, "Enable UCP database checking"),
+    MessageFlag(177, "Enable Unconstrained Plastering Debug Drawing"),
+    MessageFlag(178, "Enable Harris instead of Parrish hex refinement"),
+    MessageFlag(179, "Enable Camal Sweeper for UCP Front Advancements.\n"
+                "\t\t\t\tIgnored if debug 189 is on"),
+    MessageFlag(180, "DecompAide (decomposition helper) debugging"),
+    MessageFlag(181, "MBG.  Draw curve paths."),
+    MessageFlag(182, "UCP Detailed Debug Printing." ),
+    MessageFlag(183, "Use legacy tools for multisweep meshing." ),
+    MessageFlag(184, "Enable old sheet refinement command." ),
+    MessageFlag(185, "Enable straddle elements on hardlines." ),
+    MessageFlag(186, "Disable parametric coordinates in TriAdvMesher" ),
+    MessageFlag(187, "Custom Autoscheme" ),
+    MessageFlag(188, "Tolerant Triangle Meshing" ),
+    MessageFlag(189, "Enable Tri-Based Surface offset in UCP.\n"
+                "\t\t\t\tTakes precedence over debug flag 179." ),
+    MessageFlag(190, "Count CAMAL calls to move_to and normal_at" ),
+    MessageFlag(191, "Auto clean messages" ),
+    MessageFlag(192, "MBG - nonmanifold edge check" ),
+    MessageFlag(193, "Tetmesh with stand-alone INRIA execuable thru files" ),
+    MessageFlag(194, "Hex Mesh Matching Debug drawing" ),
+    MessageFlag(195, "CaptureMeshTool print debug information" ),
+    MessageFlag(196, "TriAdvance mesher debug timings" ),
+    MessageFlag(197, "CAMAL Paver debugging (no Cubit smoothing, etc.)" ),
+    MessageFlag(198, "Auto Midsurface debugging" ),
+    MessageFlag(199, "Angle smoothing debugging" ),
+    MessageFlag(200, "Paver quality data output" ),
+    MessageFlag(201, "Paver cleanup edge metrics" ),
+    MessageFlag(202, "Disable Paver cleanup 3-3 replace"),
+    MessageFlag(203, "Disable Paver cleanup 3-offset-3/5 replace"),
+    MessageFlag(204, "Enable Paver cleanup 3-valent quad cluster" ),
+    MessageFlag(205, "Enable Paver cleanup partial chord collapse"),
+    MessageFlag(206, "Hex Mesh Matching, match chords one at a time." ),
+    MessageFlag(207, "Defeature and Geometry tolerant meshing" ),
+    MessageFlag(208, "unassigned" ),
+    MessageFlag(209, "unassigned" ),
+    MessageFlag(210, "unassigned" )
+    
       // IMPORTANT!!!
       // If you add a new debug flag, make sure that you change
       // the result of CubitMessage::number_of_debug_flags().
@@ -290,6 +327,15 @@
   instance_ = 0;
 }
 
+void CubitMessage::delete_instance()
+{
+  if( NULL != instance )
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+}
+
 int CubitMessage::number_of_debug_flags()
 {
   return NUM_DEBUG_FLAGS;
@@ -307,10 +353,12 @@
   switch (message_type)
   {
     case CUBIT_ERROR:
-
-       print_it = CUBIT_TRUE;
-       prefix = "ERROR: ";
-       break;
+      if (errorFlag)
+      {
+        print_it = CUBIT_TRUE;
+        prefix = "ERROR: ";
+      }
+      break;
     case CUBIT_WARNING:
       if (warningFlag)
       {
@@ -718,6 +766,11 @@
   return cubit_intr;
 }
 
+void CubitMessage::clear_Interrupt()
+{
+  cubit_intr = CUBIT_FALSE;
+}
+
 void CubitMessage::set_message_handler(CubitMessageHandler *handler)
 {
   CubitMessage::mHandler = handler;
@@ -744,7 +797,7 @@
 }
 
 
-void CubitMessage::set_logging_file_setting(char* filename)
+void CubitMessage::set_logging_file_setting(const char* filename)
 {
   if (loggingFile && *loggingFile == filename)
      return;
@@ -765,11 +818,17 @@
   }
 }
 
-void CubitMessage::set_error_logging_file_setting(char* filename)
+void CubitMessage::set_error_logging_file_setting(const char* filename, CubitBoolean resume_flag)
 {
   if (loggingErrorFile && *loggingErrorFile == filename)
      return;
 
+  if(loggingFile && *loggingFile == filename)
+  {
+    PRINT_ERROR("Can't explicitly set the Error logging file to be the same as the logging file.\n");
+    return;
+  }
+ 
   if (CubitUtil::compare(filename,"terminal")) { // Filename is 'terminal'
     if (loggingErrorStream != NULL) {
       loggingErrorStream->close();
@@ -782,7 +841,10 @@
   }
   else {
     loggingErrorFile   = new CubitString(filename);
-    loggingErrorStream = new std::ofstream(filename, std::ios::out | std::ios::app );
+    if(resume_flag)
+        loggingErrorStream = new std::ofstream(filename, std::ios::out | std::ios::app );
+    else
+        loggingErrorStream = new std::ofstream(filename );
   }
 }
 

Modified: cgm/branches/cubit/util/CubitMessage.hpp
===================================================================
--- cgm/branches/cubit/util/CubitMessage.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitMessage.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -14,7 +14,7 @@
 
 #include <fstream>
 
-#include <stdarg.h>
+#include <cstdarg>
 #include "CubitDefines.h"
 #include "CubitUtilConfigure.h"
 
@@ -214,7 +214,40 @@
 #define PRINT_DEBUG_175 PRINT_DEBUG(175)
 #define PRINT_DEBUG_176 PRINT_DEBUG(176)
 #define PRINT_DEBUG_177 PRINT_DEBUG(177)
-#define NUM_DEBUG_FLAGS 177
+#define PRINT_DEBUG_178 PRINT_DEBUG(178)
+#define PRINT_DEBUG_179 PRINT_DEBUG(179)
+#define PRINT_DEBUG_180 PRINT_DEBUG(180)
+#define PRINT_DEBUG_181 PRINT_DEBUG(181)
+#define PRINT_DEBUG_182 PRINT_DEBUG(182)
+#define PRINT_DEBUG_183 PRINT_DEBUG(183)
+#define PRINT_DEBUG_184 PRINT_DEBUG(184)
+#define PRINT_DEBUG_185 PRINT_DEBUG(185)
+#define PRINT_DEBUG_186 PRINT_DEBUG(186)
+#define PRINT_DEBUG_187 PRINT_DEBUG(187)
+#define PRINT_DEBUG_188 PRINT_DEBUG(188)
+#define PRINT_DEBUG_189 PRINT_DEBUG(189)
+#define PRINT_DEBUG_190 PRINT_DEBUG(190)
+#define PRINT_DEBUG_191 PRINT_DEBUG(191)
+#define PRINT_DEBUG_192 PRINT_DEBUG(192)
+#define PRINT_DEBUG_193 PRINT_DEBUG(193)
+#define PRINT_DEBUG_194 PRINT_DEBUG(194)
+#define PRINT_DEBUG_195 PRINT_DEBUG(195)
+#define PRINT_DEBUG_196 PRINT_DEBUG(196)
+#define PRINT_DEBUG_197 PRINT_DEBUG(197)
+#define PRINT_DEBUG_198 PRINT_DEBUG(198)
+#define PRINT_DEBUG_199 PRINT_DEBUG(199)
+#define PRINT_DEBUG_200 PRINT_DEBUG(200)
+#define PRINT_DEBUG_201 PRINT_DEBUG(201)
+#define PRINT_DEBUG_202 PRINT_DEBUG(202)
+#define PRINT_DEBUG_203 PRINT_DEBUG(203)
+#define PRINT_DEBUG_204 PRINT_DEBUG(204)
+#define PRINT_DEBUG_205 PRINT_DEBUG(205)
+#define PRINT_DEBUG_206 PRINT_DEBUG(206)
+#define PRINT_DEBUG_207 PRINT_DEBUG(207)
+#define PRINT_DEBUG_208 PRINT_DEBUG(208)
+#define PRINT_DEBUG_209 PRINT_DEBUG(209)
+#define PRINT_DEBUG_210 PRINT_DEBUG(210)
+#define NUM_DEBUG_FLAGS 210
 
 #define PRINT_ERROR CubitMessage::instance()->print_error
 #define PRINT_WARNING CubitMessage::instance()->print_warning
@@ -226,6 +259,8 @@
 #define SET_INFO_FLAG CubitMessage::instance()->set_info_flag
 #define SET_WARNING_FLAG CubitMessage::instance()->set_warning_flag
 #define GET_WARNING_FLAG CubitMessage::instance()->get_warning_flag
+#define SET_ERROR_FLAG CubitMessage::instance()->set_error_flag
+#define GET_ERROR_FLAG CubitMessage::instance()->get_error_flag
 #define DEBUG_FLAG_SET CubitMessage::instance()->is_debug_flag_set
 #define PRINT_DEBUG(x) if(!DEBUG_FLAG_SET(x));else CubitMessage::instance()->print_debug
 
@@ -284,6 +319,9 @@
   static int warningFlag;
   //- warning flag, used with internal_error
 
+  static int errorFlag;
+  //- error flag, used with internal_error
+
   static int diagnosticFlag;
   //- diagnostic flag, used with internal_error
 
@@ -335,6 +373,7 @@
   virtual ~CubitMessage();
   //- Class Destructor.
 
+  static void delete_instance();
 
   void set_logging_file_setting(const CubitString &filename, CubitBoolean resume_flag = CUBIT_FALSE);
   void set_debug_file_setting(const int index, const CubitString &filename);
@@ -356,6 +395,12 @@
   int  number_of_debug_flags();
   //- debug flag, used with internal_error
 
+  virtual void set_debug_flag_gui(bool flag){};
+  virtual int is_debug_flag_gui_set(){return 0;};
+  virtual int print_debug_gui( const char *format, ... ){return 0;};
+  //- write out a debug message (from GUI only)
+  //- used for GUI Debugging (CAT-only)
+
   static bool get_info_flag();
   static void set_info_flag(bool flag);
   //- info flag, used with internal_error
@@ -364,6 +409,10 @@
   static void set_warning_flag(bool flag);
   //- warning flag, used with internal_error
 
+  static bool get_error_flag();
+  static void set_error_flag(bool flag);
+  //- error flag, used with internal_error
+
   static bool get_diagnostic_flag();
   static void set_diagnostic_flag(bool flag);
   //- diagnostic flag, used with internal_error
@@ -416,8 +465,8 @@
   void output_logging_information();
 
   static char* get_logging_file_setting();
-  static void set_logging_file_setting(char* file);
-  static void set_error_logging_file_setting(char* file);
+  static void set_logging_file_setting(const char* file);
+  static void set_error_logging_file_setting(const char* file, CubitBoolean resume_flag = CUBIT_FALSE);
 
   static void initialize_settings();
 
@@ -425,6 +474,10 @@
     //- passes back value of interrupt flag (see CubitDefines.h for how
     //- this flag is stored)
 
+  virtual void clear_Interrupt();
+    //- clears the value of interrupt flag (see CubitDefines.h for how
+    //- this flag is stored)
+
   static void set_message_handler(CubitMessageHandler *handler);
   static CubitMessageHandler* get_message_handler();
 
@@ -455,6 +508,14 @@
 {warningFlag = flag;}
 
 inline bool
+CubitMessage::get_error_flag()
+{return !!errorFlag;}
+
+inline void
+CubitMessage::set_error_flag(bool flag)
+{errorFlag = flag;}
+
+inline bool
 CubitMessage::get_diagnostic_flag()
 {return !!diagnosticFlag;}
 

Modified: cgm/branches/cubit/util/CubitPlane.cpp
===================================================================
--- cgm/branches/cubit/util/CubitPlane.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitPlane.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,8 +4,8 @@
 //- Checked by:
 
 
-#include <stdio.h>
-#include <stdlib.h>
+#include <cstdio>
+#include <cstdlib>
 #include <math.h>
 #include "CubitPlane.hpp"
 #include "CubitVector.hpp"
@@ -128,11 +128,11 @@
 
 CubitVector CubitPlane::point_on_plane() const
 {
-  if (normal_.x() != 0)
+  if ( fabs( normal_.x() ) > CUBIT_RESABS )
     return CubitVector(-d_ / normal_.x(), 0, 0);
-  else if (normal_.y() != 0)
+  else if ( fabs( normal_.y() ) > CUBIT_RESABS )
     return CubitVector(0, -d_ / normal_.y(), 0);
-  else if (normal_.z() != 0)
+  else if ( fabs( normal_.z() ) > CUBIT_RESABS )
     return CubitVector(0, 0, -d_ / normal_.z());
     // If A B and C are all zero, the plane is invalid,
     // Just return <0,0,0>
@@ -200,7 +200,7 @@
   else if (dir2.y() > dir2.x() && dir2.y() > CUBIT_RESABS)
   {
       // then get a point on the XZ plane
-    invdet = 1.0 / vector.y();
+    invdet = -1.0 / vector.y();
     
       // solve < pl1.x * origin.x + pl1.z * origin.z = -pl1.w >
       //       < plane2n.x * origin.x + plane2n.z * origin.z = -plane2n.w >

Modified: cgm/branches/cubit/util/CubitPlane.hpp
===================================================================
--- cgm/branches/cubit/util/CubitPlane.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitPlane.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -99,6 +99,10 @@
   CubitVector project( const CubitVector& point ) const;
     //- Project a point onto plane
   
+  void reverse()
+  { normal_ = -normal_; d_ = -d_; }
+    //- flip the normal of the plane
+
   CubitPlane& operator=(const CubitPlane &plane);
     //- assignment
   

Modified: cgm/branches/cubit/util/CubitStack.cpp
===================================================================
--- cgm/branches/cubit/util/CubitStack.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitStack.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -5,7 +5,7 @@
 //- Checked by:
 //- Version: $Id: 
 
-#include <string.h>
+#include <cstring>
 #include "CubitStack.hpp"
 
 

Modified: cgm/branches/cubit/util/CubitString.cpp
===================================================================
--- cgm/branches/cubit/util/CubitString.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitString.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -9,10 +9,10 @@
 
 #include <iomanip>
 
-#include <stddef.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
+#include <cstddef>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
 
 class CubitStringRep
 {
@@ -114,7 +114,7 @@
  // Create the empty string rep
   if (!sEmptyStringRep)
   {
-    static char dummy = CubitStringRep::initialize_empty_string_rep();
+    CubitStringRep::initialize_empty_string_rep();
   }
   rep = sEmptyStringRep;
   rep->increment();
@@ -136,7 +136,7 @@
 {
     // Use a static variable in order to call a function
     // once and only once.
-  static char dummy = CubitStringRep::initialize_empty_string_rep();
+  CubitStringRep::initialize_empty_string_rep();
   
     // If it's an empty string...
   if (!s || s[0] == '\0')
@@ -387,10 +387,14 @@
     else
     {
         // Append character the lazy way
-      char buf[2];
-      buf[0] = c;
-      buf[1] = '\0';
-      operator+=(buf);
+      size_t new_count = length() + 1;
+      char *buf = new char[new_count + 1];
+      memcpy(buf, rep->chars, length());
+      buf[new_count -1] = c;
+      buf[new_count] = '\0';
+      rep->decrement();
+      rep = new CubitStringRep(buf, 1);
+      rep->increment();
     }
   }
 }
@@ -441,6 +445,17 @@
   to_upper(p);
 }
 
+void CubitString::tokenize( char *delimiter, std::vector<CubitString> &strings )
+{
+  char* tmp_word;
+  tmp_word = strtok( rep->chars, delimiter );
+  if( tmp_word != NULL )
+    strings.push_back( CubitString( tmp_word ) );
+
+  while( tmp_word=strtok( NULL, delimiter ) )
+    strings.push_back( CubitString( tmp_word ) );
+}
+
 bool CubitString::operator==(const CubitString& s2) const
 {
   return (rep == s2.rep) || (strcmp(rep->chars, s2.rep->chars) == 0);

Modified: cgm/branches/cubit/util/CubitString.hpp
===================================================================
--- cgm/branches/cubit/util/CubitString.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitString.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -15,12 +15,13 @@
 #if !defined(STRING_HPP)
 #define STRING_HPP
 
-#include <assert.h>
-#include <stdlib.h>
+#include <cassert>
+#include <cstdlib>
 #include <ctype.h>
 #include "CubitDefines.h"
 
 #include <iostream>
+#include <vector>
 
 #include "CubitUtilConfigure.h"
 
@@ -91,8 +92,10 @@
   static void to_lower(char *string);
   void to_upper();
   static void to_upper(char *string);
-  static void trim(char* &string);
   //- Subscripting
+
+  void tokenize( char *delimiter, std::vector<CubitString> &strings );
+
   
   size_t find(const CubitString& s, size_t pos = 0) const;
   size_t find_first_of(const CubitString& s, size_t pos = 0) const;
@@ -136,16 +139,6 @@
   }
 }
 
-inline void CubitString::trim(char* &string)
-{
-	while(isspace(*string))
-		string++;
-	char *p = (string + strlen(string)) - 1;
-	while(isspace(*p))
-		p--;
-	p++;
-	*p = '\0';
-}
 
 #endif
 

Modified: cgm/branches/cubit/util/CubitTransformMatrix.cpp
===================================================================
--- cgm/branches/cubit/util/CubitTransformMatrix.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitTransformMatrix.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -396,3 +396,78 @@
   return mat;
 }
 
+void CubitTransformMatrix::get_rotation_axis_and_angle(CubitVector &rotation_axis, double &angle)
+{
+    double cos_theta = (this->get(0,0) + this->get(1,1) + this->get(2,2) - 1) / 2;
+
+    double x = 0;
+    double y = 0;
+    double z = 0; 
+    
+    if (fabs(cos_theta - 1) < .0001)
+    {
+        // theta is 1 or almost 1
+        angle = 0;
+        x = 0;
+        y = 0;
+        z = 1;
+    }
+    else if (fabs(cos_theta + 1) > .0001)
+    {
+        // theta is NOT -1 or almost -1
+        angle = acos(cos_theta);
+        angle =  (angle * 180.0) / CUBIT_PI; // convert to degrees
+        double sin_theta = sqrt(1 - cos_theta * cos_theta);
+        x = ( (this->get(2,1) - this->get(1,2)) / 2 ) / sin_theta;
+        y = ( (this->get(0,2) - this->get(2,0)) / 2 ) / sin_theta;
+        z = ( (this->get(1,0) - this->get(0,1)) / 2 ) / sin_theta;
+    }
+    else
+    {
+        angle = 180;
+        if (this->get(0,0) >= this->get(1,1))
+        {
+
+            if (this->get(0,0) >= this->get(2,2)) 
+            {
+                // 0,0 is maximal diagonal term
+                x = sqrt(this->get(0,0) - this->get(1,1) - this->get(2,2) + 1) / 2;
+                double half_inverse = 1 / (2 * x);
+                y = half_inverse * this->get(0,1);
+                z = half_inverse * this->get(0,2);
+            } 
+            else
+            {
+                // 2,2 is maximal diagonal term
+                z = sqrt(this->get(2,2) - this->get(0,0) - this->get(1,1) + 1) / 2;
+                double half_inverse = 1 / (2 * z);
+                x = half_inverse * this->get(0,2);
+                y = half_inverse * this->get(1,2);
+            }
+        }
+        else
+        {
+            if (this->get(1,1) >= this->get(2,2))
+            {
+                // 1,1 is maximal diagonal term
+                y = sqrt(this->get(1,1) - this->get(0,0) - this->get(2,2) + 1) / 2;
+                double half_inverse = 1 / (2 * y);
+                x = half_inverse * this->get(0,1);
+                z = half_inverse * this->get(1,2);
+            } 
+            else
+            {
+                // 2,2 is maximal diagonal term
+                z = sqrt(this->get(2,2) - this->get(0,0) - this->get(1,1) + 1) / 2;
+                double half_inverse = 1 / (2 * z);
+                x = half_inverse * this->get(0,2);
+                y = half_inverse * this->get(1,2);
+            }
+        }
+
+    }
+
+    rotation_axis.x(x);
+    rotation_axis.y(y);
+    rotation_axis.z(z);
+}

Modified: cgm/branches/cubit/util/CubitTransformMatrix.hpp
===================================================================
--- cgm/branches/cubit/util/CubitTransformMatrix.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitTransformMatrix.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -31,6 +31,8 @@
   CubitTransformMatrix& rotate(double degrees, char axis);
   CubitTransformMatrix& rotate(double degrees, const CubitVector& axis_from,
                         const CubitVector& axis_to);
+
+  void get_rotation_axis_and_angle(CubitVector &rotation_axis, double &angle);
   
   CubitTransformMatrix& reflect(const CubitVector& vector);
 

Added: cgm/branches/cubit/util/CubitUndo.cpp
===================================================================
--- cgm/branches/cubit/util/CubitUndo.cpp	                        (rev 0)
+++ cgm/branches/cubit/util/CubitUndo.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,243 @@
+//- Class:       UndoCommands
+//- Description: Provides main undo capability for Cubit system
+//- Owner:       Ray J. Meyers
+//- Checked by:
+//- Version: $Id: 
+
+#include "CubitUndo.hpp"
+#include "CubitString.hpp"
+
+CubitUndo* CubitUndo::mInstance = 0;
+
+CubitUndo::CubitUndo()
+{
+  if(mInstance)
+  {
+    assert(0);
+    // if you want a new instance in place of a previous one,
+    // delete the previous one first
+  }
+  mInstance = this;
+}
+
+CubitUndo::~CubitUndo()
+{
+  mInstance = 0;
+}
+
+void CubitUndo::start_undo_group()
+{
+  if(!mInstance ) return;
+  mInstance->p_start_undo_group(); 
+}
+
+void CubitUndo::end_undo_group()
+{
+  if(!mInstance ) return;
+  mInstance->p_end_undo_group(); 
+}
+
+void CubitUndo::set_undo_enabled(bool value)
+{
+  if(!mInstance ) return;
+  mInstance->p_set_undo_enabled( value );
+}
+
+bool CubitUndo::get_undo_enabled()
+{
+  if(!mInstance ) return false;
+  return mInstance->p_get_undo_enabled();
+}
+
+void CubitUndo::clear_undo_groups()
+{
+  if(!mInstance ) return;
+  mInstance->p_clear_undo_groups();
+}
+
+int CubitUndo::execute_undo()
+{
+  if(!mInstance ) 
+    return 0;
+
+  return mInstance->p_execute_undo();
+}
+
+void CubitUndo::remove_last_undo()
+{
+  if(!mInstance ) return;
+  mInstance->p_remove_last_undo();
+}
+
+
+void CubitUndo::remove_last_undo_group()
+{
+  if(!mInstance ) return;
+  mInstance->p_remove_last_undo_group();
+}
+
+void CubitUndo::save_state()
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state();
+}
+
+void CubitUndo::save_state_with_cubit_file(DLIList<RefVolume*> &volumes_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( volumes_to_save );
+}
+
+void CubitUndo::save_state_with_cubit_file(RefFace *face_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( face_to_save );
+}
+
+void CubitUndo::save_state_with_cubit_file(RefVolume *volume_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( volume_to_save );
+}
+
+void CubitUndo::save_state_with_cubit_file( DLIList<MRefVolume*> &volumes_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( volumes_to_save );
+}
+void CubitUndo::save_state_with_cubit_file(DLIList<RefFace*> &faces_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( faces_to_save );
+}
+
+void CubitUndo::save_state_with_cubit_file(DLIList<RefEdge*> &edges_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( edges_to_save );
+}
+
+void CubitUndo::save_state_with_cubit_file(DLIList<RefVertex*> &verts_to_save,
+                                           bool save_only_if_free )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( verts_to_save, save_only_if_free );
+}
+
+void CubitUndo::save_state_with_cubit_file( DLIList<Body*> &bodies_to_save,
+                                            DLIList<RefEntity*> *free_ents_to_save )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_state_with_cubit_file( bodies_to_save, free_ents_to_save );
+}
+
+void CubitUndo::note_result_body( Body *body_to_delete )
+{
+  if(!mInstance ) return;
+  mInstance->p_note_result_body( body_to_delete );
+}
+
+void CubitUndo::note_result_bodies( DLIList<Body*> &bodies_to_delete )
+{
+  if(!mInstance ) return;
+  mInstance->p_note_result_bodies( bodies_to_delete );
+}
+
+void CubitUndo::note_result_entity( RefEntity *entity_to_delete ) 
+{
+  if(!mInstance ) return;
+  mInstance->p_note_result_entity( entity_to_delete );
+}
+
+void CubitUndo::note_result_entities( DLIList<MRefVolume*> &vols_to_delete )
+{
+  if(!mInstance ) return;
+  mInstance->p_note_result_entities( vols_to_delete );
+}
+
+void CubitUndo::note_result_entities( DLIList<RefEntity*> &entities_to_delete )
+{
+  if(!mInstance ) return;
+  mInstance->p_note_result_entities( entities_to_delete );
+}
+
+void CubitUndo::set_undo_by_restoring_state()
+{
+  if(!mInstance ) return;
+  mInstance->p_set_undo_by_restoring_state();
+}
+
+void CubitUndo::set_undo_by_command(CubitString undo_command_string)
+{
+  if(!mInstance ) return;
+  mInstance->p_set_undo_by_command( undo_command_string );
+}
+
+int CubitUndo::number_undo_groups()
+{
+  if(!mInstance ) return 0;
+  return mInstance->p_number_undo_groups();
+}
+
+void CubitUndo::create_dummy_undo_object()
+{
+  if(!mInstance ) return;
+  mInstance->p_create_dummy_undo_object();
+}
+
+bool CubitUndo::inside_undo_group()
+{
+  if(!mInstance ) return false;
+  return mInstance->p_inside_undo_group();
+}
+
+void CubitUndo::save_mesh_size_data( MRefEntity *entity )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_mesh_size_data( entity );
+}
+
+void CubitUndo::save_mesh_scheme_data( MRefEntity *entity )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_mesh_scheme_data( entity );
+}
+
+void CubitUndo::save_smooth_scheme_data( MRefEntity *entity )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_smooth_scheme_data( entity );
+}
+
+void CubitUndo::save_all_mesh_data( MRefEntity *entity )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_all_mesh_data( entity );
+}
+
+void CubitUndo::save_merge_data( DLIList<RefEntity*> &ents, bool merging )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_merge_data( ents, merging );
+}
+
+void CubitUndo::save_mesh_state_before_smoothing( MRefEntity *entity )
+{
+  if(!mInstance ) return;
+  DLIList<MRefEntity*> ents_to_smooth(1);
+  ents_to_smooth.append( entity );
+  mInstance->p_save_mesh_state_before_smoothing( ents_to_smooth ); 
+}
+
+void CubitUndo::save_mesh_state_before_smoothing( DLIList<MRefEntity*> &ents_to_smooth )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_mesh_state_before_smoothing( ents_to_smooth ); 
+}
+
+void CubitUndo::save_mesh_state_before_smoothing( DLIList<MeshEntity*> &ents_to_smooth )
+{
+  if(!mInstance ) return;
+  mInstance->p_save_mesh_state_before_smoothing( ents_to_smooth ); 
+}
+

Added: cgm/branches/cubit/util/CubitUndo.hpp
===================================================================
--- cgm/branches/cubit/util/CubitUndo.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/CubitUndo.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,137 @@
+//- Class:       UndoCommands
+//- Description: Provides undo capability for Cubit system
+//- Owner:       Ray J. Meyers
+//- Checked by:
+//- Version: $Id: 
+
+
+#ifndef CUBITUNDO_HPP
+#define CUBITUNDO_HPP
+
+#include <stack>
+#include "DLIList.hpp"
+
+class UndoCommand;
+class CubitString;
+class RefEntity;
+class Body;
+class RefVolume;
+class RefFace;
+class RefEdge;
+class RefVertex;
+class MRefEntity;
+class MRefVolume;
+class MeshEntity;
+
+class CUBIT_UTIL_EXPORT CubitUndo 
+{
+  // the one instance of the Cubit Undo object
+  // creating a second instance will delete and replace the first instance.
+  static CubitUndo* mInstance;
+
+public:
+  
+  CubitUndo();
+  virtual ~CubitUndo();
+
+  static void start_undo_group();
+  static void end_undo_group();
+  static void set_undo_enabled(bool value);
+  static bool get_undo_enabled();
+  static void clear_undo_groups();
+  static int  execute_undo();
+  static void set_undo_by_restoring_state();
+  static void set_undo_by_command(CubitString command);
+
+  static void save_state_with_cubit_file( DLIList<Body*> &bodies_to_save,
+                                          DLIList<RefEntity*> *free_ents_to_save = NULL );
+  static void save_state_with_cubit_file( DLIList<RefVolume*> &volumes_to_save );
+  static void save_state_with_cubit_file( DLIList<RefFace*> &faces_to_save );
+  static void save_state_with_cubit_file( RefFace* face_to_save );
+  static void save_state_with_cubit_file( RefVolume* volume_to_save );
+  static void save_state_with_cubit_file( DLIList<MRefVolume*> &volumes_to_save );
+  static void save_state_with_cubit_file( DLIList<RefEdge*> &edges_to_save );
+  static void save_state_with_cubit_file( DLIList<RefVertex*> &vertices_to_save, 
+                                          bool save_if_free = false );
+
+  static void save_state(); 
+  static  int number_undo_groups();
+  static void note_result_bodies( DLIList<Body*> &bodies_to_delete );
+  static void note_result_body( Body* body_to_delete );
+  static void note_result_entities( DLIList<RefEntity*> &entities_to_delete );
+  static void note_result_entities( DLIList<MRefVolume*> &vols_to_delete );
+  static void note_result_entity( RefEntity *entity_to_delete );
+  static void remove_last_undo();
+  static void remove_last_undo_group();
+  static void create_dummy_undo_object();
+  static bool inside_undo_group();
+
+  //meshing data
+  static void save_mesh_size_data( MRefEntity *entity );
+  static void save_mesh_scheme_data( MRefEntity *entity );
+  static void save_smooth_scheme_data( MRefEntity *entity );
+  static void save_all_mesh_data( MRefEntity *entity );
+
+  //merging
+  static void save_merge_data( DLIList<RefEntity*> &ents, bool merging = true );
+
+  //smoothing
+  static void save_mesh_state_before_smoothing( MRefEntity *entity );
+  static void save_mesh_state_before_smoothing( DLIList<MRefEntity*> &ents );
+  static void save_mesh_state_before_smoothing( DLIList<MeshEntity*> &ents );
+
+protected:
+  
+  virtual void p_start_undo_group() = 0;
+  virtual void p_end_undo_group() = 0;
+
+  virtual void p_set_undo_enabled(bool value)=0;
+  virtual bool p_get_undo_enabled()=0;
+  virtual void p_clear_undo_groups()=0;
+  virtual int p_execute_undo()=0;
+  virtual void p_set_undo_by_restoring_state()=0;
+  virtual void p_set_undo_by_command(CubitString command)=0;
+
+  virtual void p_save_state_with_cubit_file( DLIList<Body*> &bodies_to_save, 
+                                             DLIList<RefEntity*> *free_ref_ents = NULL )=0;
+  virtual void p_save_state_with_cubit_file( DLIList<RefVolume*> &volumes_to_save )=0;
+  virtual void p_save_state_with_cubit_file( DLIList<RefFace*> &faces_to_save )=0;
+  virtual void p_save_state_with_cubit_file( RefFace *face_to_save )=0;
+  virtual void p_save_state_with_cubit_file( RefVolume* volume_to_save )=0;
+  virtual void p_save_state_with_cubit_file( DLIList<MRefVolume*> &volumes_to_save )=0;
+  virtual void p_save_state_with_cubit_file( DLIList<RefEdge*> &edges_to_save )=0;
+  virtual void p_save_state_with_cubit_file( DLIList<RefVertex*> &vertices_to_save,
+                                             bool save_only_if_free = false )=0;
+
+  virtual void p_save_state()=0; 
+  virtual  int p_number_undo_groups()=0;
+  virtual void p_note_result_bodies( DLIList<Body*> &bodies_to_delete )=0;
+  virtual void p_note_result_body( Body* body_to_delete )=0;
+  virtual void p_note_result_entities( DLIList<RefEntity*> &entities_to_delete )=0;
+  virtual void p_note_result_entities( DLIList<MRefVolume*> &vols_to_delete )=0;
+  virtual void p_note_result_entity( RefEntity *entity_to_delete )=0;
+  virtual void p_remove_last_undo_group()=0;
+  virtual void p_remove_last_undo()=0;
+  virtual void p_create_dummy_undo_object()=0;
+  virtual bool p_inside_undo_group()=0;
+
+  //meshing data
+  virtual void p_save_mesh_size_data( MRefEntity *entity )=0;
+  virtual void p_save_mesh_scheme_data( MRefEntity *entity )=0;
+  virtual void p_save_smooth_scheme_data( MRefEntity *entity )=0;
+  virtual void p_save_all_mesh_data( MRefEntity *entity )=0;
+  
+  //merging
+  virtual void p_save_merge_data( DLIList<RefEntity*> &ents, bool merging = true)=0;
+
+  //smoothing
+ virtual void p_save_mesh_state_before_smoothing( DLIList<MRefEntity*> &ents_to_smooth )=0;
+ virtual void p_save_mesh_state_before_smoothing( DLIList<MeshEntity*> &ents_to_smooth )=0;
+
+}; 
+
+#endif
+
+
+
+

Modified: cgm/branches/cubit/util/CubitUtil.cpp
===================================================================
--- cgm/branches/cubit/util/CubitUtil.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitUtil.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -21,7 +21,10 @@
 #include "AppUtil.hpp"
 #include <ctype.h>
 #include <time.h>
+#include <fstream>
+using std::ifstream;
 
+
 #ifdef NT
 #include "Windows.h"
 #else
@@ -468,19 +471,31 @@
 
     // If the path is not writeable, use the current directory instead
     DWORD atts = GetFileAttributes(temp_path);
+#if _MSC_VER > 1200 // after VC6.0
     if (atts == INVALID_FILE_ATTRIBUTES ||      // File doesn't exist
         (atts & FILE_ATTRIBUTE_DIRECTORY) == 0 || // File isn't a directory
         atts & FILE_ATTRIBUTE_READONLY)         // File is read only
+#else
+    if ((atts & FILE_ATTRIBUTE_DIRECTORY) == 0 || // File isn't a directory
+        atts & FILE_ATTRIBUTE_READONLY)         // File is read only
+#endif
     {
       if (DEBUG_FLAG(141))
       {
         PRINT_DEBUG_141("\nUsing cwd because ");
+#if _MSC_VER > 1200
         if (atts == INVALID_FILE_ATTRIBUTES)
           PRINT_DEBUG_141("directory doesn't exist: %s\n", temp_path);
         else if ((atts & FILE_ATTRIBUTE_DIRECTORY) == 0)
           PRINT_DEBUG_141("file isn't a directory: %s\n", temp_path);
         else if (atts & FILE_ATTRIBUTE_READONLY)         
           PRINT_DEBUG_141("directory is read only: %s\n", temp_path);
+#else
+        if ((atts & FILE_ATTRIBUTE_DIRECTORY) == 0)
+          PRINT_DEBUG_141("file isn't a directory: %s\n", temp_path);
+        else if (atts & FILE_ATTRIBUTE_READONLY)         
+          PRINT_DEBUG_141("directory is read only: %s\n", temp_path);
+#endif
       }
       temp_path[0] = '.';
       temp_path[1] = '\0';
@@ -525,7 +540,8 @@
 
   CubitString tmpdir = get_temp_directory();
   const char* filepattern = "CBT.XXXXXX";
-  char *temp_file_name = new char[tmpdir.length() + strlen(filepattern) + 1];
+    //needs to be two longer because of the "/"?
+  char *temp_file_name = new char[tmpdir.length() + strlen(filepattern) + 2];
   sprintf(temp_file_name, "%s/%s", tmpdir.c_str(), filepattern);
 
   // make an empty file and return the name for it
@@ -659,3 +675,139 @@
   sleep(duration_in_seconds);
 #endif
 }
+
+int CubitUtil::find_available_file_name(char* buffer)
+{
+  int num_files;
+      
+    // If a bell character was encountered in the string, we need to 
+    // expand it to the next available number.
+
+  char* ten_ptr = 0;  //Pointer to the tens-digit in the string
+  char* one_ptr = 0;  //Pointer to the ones-digit in the string
+  CubitBoolean file_already_exists = CUBIT_FALSE;
+    
+  char* ptr;
+  
+    // Find the tens- and ones-digit in the string.
+    // We marked them with bell characters before, so
+    // that strftime() would ignore them.
+  for( ptr = buffer; *ptr; ptr++ )
+  {
+    if( (*ptr == '\007') && (*(ptr+1) == '\007') )
+    {
+      ten_ptr = ptr;
+      one_ptr = ptr + 1;
+      *ten_ptr = '0';
+      *one_ptr = '0';
+      break;
+    }
+  }
+  assert(ten_ptr != 0);
+  
+    //Search for next available number with two digits.
+
+  for(int i=0; i<10; ++i) 
+  {
+    *ten_ptr = (char)(i + '0');
+    for(int j=0; j<10; ++j) 
+    {
+      file_already_exists = CUBIT_FALSE;
+        
+      if (i==0 && j==0)
+	        continue; // Don't want cubit00.jou
+	    
+      *one_ptr = (char)(j + '0');
+      ifstream test_stream(buffer);
+        
+      if(!test_stream)
+      {
+          // File does not exist, use it
+        num_files = i*10 + j;
+         // Break out of both loops.
+        i = 10;
+        j = 10;
+                
+        file_already_exists = CUBIT_FALSE;
+      }
+      else
+          file_already_exists = CUBIT_TRUE;
+        
+      test_stream.close();  // File exists, close it and try next.
+    }
+  }
+
+    //Search for next available file with three digits
+  if(file_already_exists)
+  {
+  
+      // Find the tens- and ones-digit in the string.
+      //We should only be in here if they are both 9
+    char* ptr;
+    char* hun_ptr = 0;  //Pointer to the hundreds-digit in the string
+    char* temp_ptr = 0;
+  
+    for( ptr = buffer; *ptr; ptr++ )
+    {
+      if( (*ptr == '9') && (*(ptr+1) == '9') )
+      {
+        hun_ptr = ptr;
+        ten_ptr = ptr + 1;
+        one_ptr = ptr + 2;
+        temp_ptr = one_ptr;
+      
+        do
+        {
+          temp_ptr++;
+        }
+        while(*temp_ptr !='\0');
+
+        one_ptr = temp_ptr;
+        temp_ptr ++;
+      
+        do{
+          *temp_ptr = *one_ptr;
+          one_ptr--;
+          temp_ptr--;
+        }
+        while(one_ptr != ten_ptr);
+        one_ptr++;
+      
+        *hun_ptr = '1';
+        *ten_ptr = '0';
+        *one_ptr = '0';
+        break;
+      }
+    }
+    assert(ten_ptr != 0);
+  
+      //Search for next available number.
+    
+    for(int k = 1; k<10 ; ++k)
+    {
+      *hun_ptr = (char)(k+'0');
+    
+      for(int i=0; i<10  ; ++i) 
+      {
+        *ten_ptr = (char)(i + '0');
+        for(int j=0; j<10  ; ++j) 
+        {
+          *one_ptr = (char)(j + '0');
+          ifstream test_stream(buffer);
+          num_files = k*100 + i * 10 + j;
+          if(!test_stream)
+          {
+              // File does not exist, use it
+              //Break out of loop
+            k = 10;
+            i = 10;
+            j = 10;
+            
+          }
+          test_stream.close();  // File exists, close it and try next.
+        }
+      }
+    }
+  }
+  return num_files;
+}

Modified: cgm/branches/cubit/util/CubitUtil.hpp
===================================================================
--- cgm/branches/cubit/util/CubitUtil.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitUtil.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -19,7 +19,7 @@
 #ifndef CUBIT_UTIL_HPP
 #define CUBIT_UTIL_HPP
 
-#include <string.h>
+#include <cstring>
 #include "DLIList.hpp"
 #include "CubitDefines.h"
 #include "CubitUtilConfigure.h"
@@ -107,7 +107,11 @@
   static void util_strdup_free(char* s1){free(s1);}
 
   static void cubit_sleep(int duration_in_seconds);
-
+    //Send in a string (in buffer) with two \007 characters next to each other
+    //This function will search from 00 up to 999 to find the next available
+    //filename
+  static int find_available_file_name(char* buffer);
+  
 private:
   CubitUtil(){}
 

Modified: cgm/branches/cubit/util/CubitUtilConfigure.h.in
===================================================================
--- cgm/branches/cubit/util/CubitUtilConfigure.h.in	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitUtilConfigure.h.in	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,15 +4,23 @@
 
 #cmakedefine CUBIT_UTIL_BUILD_SHARED_LIBS
 
-#if defined(WIN32) && defined(CUBIT_UTIL_BUILD_SHARED_LIBS)
+#if defined(CUBIT_UTIL_BUILD_SHARED_LIBS)
 #if defined(cubit_util_EXPORTS)
-#define CUBIT_UTIL_EXPORT __declspec(dllexport)
+# if defined(WIN32)
+#  define CUBIT_UTIL_EXPORT __declspec(dllexport)
+# elif defined(__GNUC__) && __GNUC__ >= 4
+#  define CUBIT_UTIL_EXPORT __attribute__ ((visibility("default")))
+# endif
 #else
-#define CUBIT_UTIL_EXPORT __declspec(dllimport)
+# if defined(WIN32)
+#  define CUBIT_UTIL_EXPORT __declspec(dllimport)
+# endif
 #endif
-#else
-#define CUBIT_UTIL_EXPORT
 #endif
 
+#ifndef CUBIT_UTIL_EXPORT
+#define CUBIT_UTIL_EXPORT
 #endif
 
+#endif // CUBIT_UTIL_EXPORTS_H
+

Modified: cgm/branches/cubit/util/CubitVector.cpp
===================================================================
--- cgm/branches/cubit/util/CubitVector.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitVector.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -44,6 +44,24 @@
   return(sqrt(x*x + y*y + z*z));
 }
 
+double CubitVector::distance_from_infinite_line(const CubitVector& point_on_line,
+                                                const CubitVector& line_direction) const
+{
+  return sqrt(distance_from_infinite_line_squared(point_on_line, line_direction));
+}
+
+double CubitVector::distance_from_infinite_line_squared(
+  const CubitVector& point_on_line,
+  const CubitVector& line_direction) const
+{
+  if (line_direction == CubitVector(0, 0, 0))
+    return distance_between_squared(point_on_line);
+
+  CubitVector v = *this - point_on_line;
+  double v_dot_d = v % line_direction;
+  return fabs(v.length_squared() - v_dot_d * v_dot_d / line_direction.length_squared());
+}
+
 // double CubitVector::distance_between(const CubitVector& test_vector, RefEdge* test_edge)
 // {
 //   return( test_edge->get_arc_length(*this, test_vector) );
@@ -204,7 +222,10 @@
   double y = vec2 % ry;
 
   double angle;
-  assert(x != 0.0 || y != 0.0);
+  if( x == 0.0 && y == 0.0 )
+  {
+    return 0.0;
+  }
 
   angle = atan2(y, x);
 
@@ -244,6 +265,11 @@
   return CubitVector(xAxis + yAxis);
 }
 
+#ifdef __APPLE__
+// optimization issues on mac osx.
+#pragma optimization_level 0
+#endif
+
 double CubitVector::vector_angle(const CubitVector &vector1,
                                  const CubitVector &vector2) const
 {
@@ -333,6 +359,10 @@
   return angle;
 }
 
+#ifdef __APPLE__
+#pragma optimization_level reset
+#endif
+
 CubitBoolean CubitVector::within_tolerance( const CubitVector &vectorPtr2,
                                             double tolerance) const
 {
@@ -475,3 +505,14 @@
   return;
 }
 
+//- Project this vector onto the plane specified by the input plane normal
+void CubitVector::project_to_plane( const CubitVector &planenormal )
+{
+    // Cross the vector with the normal to get a vector on the plane
+    CubitVector planevec = planenormal * (*this);
+
+    // Cross the vector on the plane with the normal to get the 
+    // projection of the vector on the plane
+    *this = planevec * planenormal;
+}
+

Modified: cgm/branches/cubit/util/CubitVector.hpp
===================================================================
--- cgm/branches/cubit/util/CubitVector.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/CubitVector.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -102,6 +102,9 @@
   void rotate(double angle, double );
     //- transform function.
     //- transform  (x,y) to (r,theta) to (r,theta+angle) to (x',y')
+
+  void project_to_plane( const CubitVector &planenormal );
+    //- project this vector onto a plane.
   
   void reflect_about_xaxis(double dummy, double );
     //- dummy argument to make it a transform function
@@ -125,7 +128,17 @@
   double distance_between_squared(const CubitVector& test_vector) const;
     //- Calculate the distance squared from the head of one vector
     //  to the head of the test_vector.
+
+  double distance_from_infinite_line(const CubitVector& point_on_line,
+                                     const CubitVector& line_direction) const;
+    //- Calculate the minimum distance between the head of this vector and a 
+    // line of infinite length.
   
+  double distance_from_infinite_line_squared(const CubitVector& point_on_line,
+                                     const CubitVector& line_direction) const;
+    //- Calculate the square of the minimum distance between the head of this 
+    //  vector and a line of infinite length.
+  
   double length_squared() const;
     //- Calculate the squared length of the vector.
     //- Faster than {length()} since it eliminates the square root if
@@ -211,6 +224,9 @@
   
   CubitVector operator-() const;
     //- unary negation.
+
+  double operator[](int i) const;
+    //- return the ith value of the vector (x, y, z)
   
   friend CubitVector operator~(const CubitVector &vec);
     //- normalize. Returns a new vector which is a copy of {vec},
@@ -472,6 +488,14 @@
   return CubitVector(-xVal, -yVal, -zVal);
 }
 
+inline double CubitVector::operator[](int i) const
+{
+  assert(i > -1 && i < 3);
+  if      (i == 0) return xVal;
+  else if (i == 1) return yVal;
+  else             return zVal;
+}
+
 inline CubitVector operator+(const CubitVector &vector1,
                       const CubitVector &vector2)
 {

Modified: cgm/branches/cubit/util/DIntArray.cpp
===================================================================
--- cgm/branches/cubit/util/DIntArray.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/DIntArray.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,7 +4,7 @@
 //- Checked by:
 
 #include "DIntArray.hpp"
-#include <assert.h>
+#include <cassert>
 
 void DIntArray::append(int item) 
 {

Modified: cgm/branches/cubit/util/DLIList.cpp
===================================================================
--- cgm/branches/cubit/util/DLIList.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/DLIList.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -71,6 +71,23 @@
       delete [] listArray;
 }
 
+template <class X> MY_INLINE void DLIList<X>::reserve(int min_size)
+{
+  if (min_size > listLength)
+  {
+    X* temp_list = new X [min_size];
+
+    // If the list wasn't empty, copy over the old stuff
+    if (listLength)
+    {
+      memcpy (temp_list, listArray, listLength*sizeof(X));
+      delete [] listArray;
+    }
+    listLength = min_size;
+    listArray = temp_list;
+  }
+}
+
 template <class X> MY_INLINE void DLIList<X>::lengthen_list(int by_how_much,
                                                   double by_what_factor)
 {
@@ -78,16 +95,7 @@
   int new_size = 
     (int) ((double)listLength * by_what_factor)
     + by_how_much;
-  X* temp_list = new X [new_size];
-
-    // If the list wasn't empty, copy over the old stuff
-  if (listLength)
-  {
-    memcpy (temp_list, listArray, listLength*sizeof(X));
-    delete [] listArray;
-  }
-  listLength = new_size;
-  listArray = temp_list;
+  reserve(new_size);
 }
 
 //- put new item in list after current item and make it current
@@ -124,39 +132,7 @@
 void DLIList<X>::merge_unique ( const DLIList<X>& merge_list, 
                                 bool  merge_list_unique )
 {
-     // MJP Note:
-     // This procedure could be much more efficient if sorted lists
-     // are used. However, I need this procedure at this time to merge
-     // DLILists that already exist. These were not created as sorted
-     // lists (SDLILists) and it would be painful to convert them to
-     // SDLILists. It would be a lot easier if one could simply sort 
-     // a DLIList based on the numeric values of its items.
-
-     // Save the current index of the merge_list
-   int old_size = size();   
-   int i, j, check_index;
-
-   X new_item;
-   
-   for ( i = 0; i < merge_list.size(); i++)
-   {
-        // Get the item from the merge_list and insert it into "this"
-        // list if it doesn't already exist there.
-      new_item = merge_list.next(i);
-      check_index = merge_list_unique ? old_size : size();
-
-      for ( j = 0; j < check_index; j++ )
-      {
-        if ( listArray[j] == new_item )
-        {
-          check_index = -1;
-          break;
-        }
-      }
-      if ( check_index != -1 )
-        append(new_item);
-//      append_unique(new_item);
-   }
+  this->casting_merge_unique(merge_list, merge_list_unique);
 }
 
 template <class X> MY_INLINE void DLIList<X>::intersect_unordered( 
@@ -216,10 +192,10 @@
      remove_all_with_value(NULL);
 }
 
-template <class X> MY_INLINE void DLIList<X>::intersect ( void* merge_list )
-{
-  intersect( *(DLIList<X>*)merge_list );
-}
+//template <class X> MY_INLINE void DLIList<X>::intersect ( void* merge_list )
+//{
+//  intersect( *(DLIList<X>*)merge_list );
+//}
 
 
 //- remove the item at the current location and return a pointer to it.
@@ -397,36 +373,7 @@
    itemCount += from.itemCount;
    return *this;
 }
-template <class X> MY_INLINE DLIList<X>& DLIList<X>::
-                       operator+=(void* from)
-{
-  DLIList<X>* cast_from = (DLIList<X>*)from;
-  
-     // Don't do anything if the list being appended is empty.
-   if (cast_from->itemCount == 0)
-      return *this;
 
-     // Make sure the array is big enough
-   int tmp_itemCount = itemCount + cast_from->itemCount;
-   if (tmp_itemCount >= listLength)
-      lengthen_list(tmp_itemCount - listLength, 2.0 );
-     // factor of 1.0 can cause huge inefficiencies
-
-     // Now add the 'from' items to the list
-   if (cast_from->itemCount == 1)
-   {
-      listArray[itemCount] = cast_from->listArray[0];
-   }
-   else
-   {
-      memcpy (&listArray[itemCount], cast_from->listArray,
-              cast_from->itemCount*sizeof(X));
-   }
-
-     // Increase the itemCount
-   itemCount += cast_from->itemCount;
-   return *this;
-}
 template <class X> MY_INLINE DLIList<X>& DLIList<X>::
                        operator-=(const DLIList<X>& from)
 {
@@ -705,10 +652,6 @@
 
 template <class X> MY_INLINE CubitBoolean DLIList<X>::move_between(X item1, X item2)
 {
-//  if (nullItem && (((X)nullItem == item1 ||
-//                    ((X)nullItem == item2))))
-//     return CUBIT_FALSE;
-//  else
   {
     assert(item1 != NULL && item2 != NULL);
     if ( !itemCount )

Modified: cgm/branches/cubit/util/DLIList.hpp
===================================================================
--- cgm/branches/cubit/util/DLIList.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/DLIList.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,19 +1,4 @@
 //- Class: DLIList
-//- Description: DLIList is a doubly linked intrinsic list class that accepts
-//-              any type of object.  It uses a template to allow the same
-//-              list class definition for any data type.  Because the list
-//-              makes a copy of each item added to the list, this type of
-//-              list should only be used for simple data types such as
-//-              integers, doubles, and enumerated types.  Other data types
-//-              should use the DLList, which keeps list of pointers.
-//-              The list is implemented as an array that is grown by a
-//-              specified amount when the list becomes full.
-//-              Insertions and deletions at any point other than the end
-//-              of the list are handled inefficiently at the current time
-//-              since all data from that point to the end is bubbled
-//-              down/up to fill/create the void. Operators {+} and {+=} 
-//-              are provided as an efficient means of assigning one list
-//-              to another or appending one list onto another.
 //-
 //- Assumptions: All data are stored contiguously in the array with 
 //-              empty slots at the end of the array.
@@ -25,219 +10,529 @@
 
 #include "CubitDefines.h"
 #include "CubitMessage.hpp"
-#include <string.h>
-#include <assert.h>
+#include <cstring>
+#include <cassert>
 
 #define DLI_COUNT_INCREMENT 8
 #define DLI_COUNT_FACTOR 1.5
 template<class X> class DLIListIterator;
 
+//! A list class, similar to a std::vector<>.
+/*! DLIList is implemented as an array that is grown by a
+specified amount when the list becomes full.
+Most insertions and deletions at any point other than the end
+of the list are handled inefficiently 
+since all data from that point to the end is bubbled
+down/up to fill/create the void. Operators {+} and {+=} 
+are provided as an efficient means of assigning one list
+to another or appending one list onto another.  The list has
+a current position, which is a zero-based index into the 
+list.  Many of the member functions operate on the current 
+item (the item at the current position) or move the current
+position.
+*/
 template<class X> class DLIList
 {
 public:
   friend class DLIListIterator<X>;
   
+  //! Constructor: Create a list, allocating enough storage for \a size elements.
+  /*! Although enough space is allocated for \a size elements, the list starts
+  out empty (the size() function will return 0).  If the requested memory size
+  is 0, then storage is not allocated until the first element is added to the list. 
+  Additional storage space will be allocated if the list grows beyond its
+  original size.
+  \param size The amount of storage to pre-allocate for this list.
+  */
   explicit DLIList (int size = 0);
-    //- Constructor: Create a list with initial size 'size'. Memory for the
-    //- list is not allocated until the first element is added to the list. 
   
-  DLIList(const DLIList<X>& from);  //- Copy Constructor
+  //! Copy constructor.
+  /*! \param from The list to be copied. */
+  DLIList(const DLIList<X>& from);
   
+  //! Destructor: Free all resources used by this list.
+  /*! The list and its storage space are freed.  Note that if this is a list
+  of pointers, this destructor will \a NOT delete the objects whose pointers
+  are stored in the list.
+  */
   ~DLIList();
-    //- Destructor: Free all resources used by this list.
   
+  //! Move the pointer to the next element in the list.
+  /*! If pointer reaches the end of the list, wrap around to the beginning */
   void step();
-    //- Move the pointer to the next element in the list. If pointer reaches
-    //- the end of the list, wrap around to the beginning
   
+  //! Move the pointer \a n positions forward in the list.
+  /*! The pointer will wrap around to the beginning of the list if the end 
+  is reached.  If \a n is less than zero, move backward.
+  \param n The number of positions to move forward or backward.
+  */
   void step(int n);
-    //- Move the pointer {n} positions forward in the list wrapping 
-    //- around to the beginning of the list if the end is reached
-    //- If {n} is less than zero, move backward.
   
+  //! Move the pointer to the previous element in the list. 
+  /*! If it reaches the beginning of the list, wrap around to the end. */
   void back();
-    //- Move the pointer to the previous element in the list. If reaches
-    //- the beginning of the list, wrap around to the end
   
+  //! Move the pointer \a n positions backward in the list.
+  /*! The pointer will wrap around to the end of the list if the beginning
+  is reached. If \a n is less than zero, move forward.
+  */
   void back(int n);
-    //- Move the pointer {n} positions backward in the list wrapping 
-    //- around to the end of the list if the beginning is reached.
-    //- If {n} is less than zero, move forward.
   
-  void reset();     //- Set the pointer to the beginning of the list.   
-  void last();      //- Set the pointer to the end of the list.
+  //! Set the pointer to the beginning of the list.
+  void reset();
+  //! Set the pointer to the end of the list.
+  void last();
   
+  //! Delete all elements in the list.
+  /*! This function does not release memory already allocated for the list. This
+  call is more efficient than creating a new list repeatedly within a loop.
+  */
   void clean_out();
-    //- Delete all elements in the list, reset the pointer to zero.
-    //- Does not release memory already allocated for the list. This
-    //- call is more efficient than creating a new list repeatedly
-    //- within a loop.
   
+  //! Reduces the size of the list by \a k.
+  /*! No list storage is freed.  Items in the array are not changed.
+  If the current position is beyond the new end of the list, then the 
+  current position is moved to the new end of the list.
+  */
   void shrink(int k);
-    //- itemCount -= k;  Doesn't change array elements.
-    //- Sets the index to the new end of the list if the old_index >= 
-    //- new_itemCount
   
+  //! Returns CUBIT_TRUE if the current position is at the beginning of the list.
   CubitBoolean is_at_beginning() const;
-    //- returns CUBIT_TRUE if list is at beginning
   
+  //! Returns CUBIT_TRUE if the current position is at the end of the list.
   CubitBoolean is_at_end() const;
-    //- returns CUBIT_TRUE if list is at end
 
-  void remove_all_with_value(X val);
-    //- Remove all items with value 'val'. This is similar to the DLList
-    //- function pair nullify() and compress().  First, change the value
-    //- of any elements you want to remove to 'val'.  Then, call this
-    //- function to compress the list.
-  
+  //! Reverse the items in the list.
   void reverse();
-    //- Reverse the items in the list.
   
+  //! Create a copy of a list.
+  /*! This is the most efficient way to do this. 
+  \return A reference to this list.*/
   DLIList<X>& operator=(const DLIList<X>& from);
-  DLIList<X>& operator=(const DLIListIterator<X>&);
-    //- Create a copy of a list.  Most efficient way to do this.
+
+  //! Create a copy of the list an iterator was obtained from.
+  /*! If \a from_iterator is not associated with a list,
+  then this list becomes empty.
+  \param from_iterator An iterator to another list.
+  \return A reference to this list.
+  */
+  DLIList<X>& operator=(const DLIListIterator<X>& from_iterator);
   
+  //! Append one list to another list.
+  /*!  This is the most efficient way to append two lists together. 
+  \param from The list to be appended to this list.
+  \return A reference to this list.
+  */
   DLIList<X>& operator+=(const DLIList<X>& from);
-  DLIList<X>& operator+=(void* from);
-    //- Append one list to another list.  Most efficient way to do this.
 
+  //! Subtract one list from another list.
+  /*! Any element in \from which is also found in this list
+  will be removed from this list.  Element ordered is retained.
+  The \a from list is not modified.
+  \param from The list to be subtracted from this list.
+  \return A reference to this list.*/
   DLIList<X>& operator-=(const DLIList<X>& from);
-    //- Subtract one list from another list.  Retains order.
 
-    //Added by K. Walton 3/1/01
-    //Needed to make changes from DLList
+  //! Compare two lists for equality.
+  /*! Two lists are considered equal if they have the same contents.
+  The elements do not need to be in the same order.  If values are
+  repeated, they do have to appear an equal number of times in each list.
+  \param from The list to compare with this list.
+  \return True if the lists are equal, false otherwise.
+  */
   int operator==(const DLIList<X>& from);
+
+  //! Compare two lists for inequality.
+  /*! Two lists are considered equal if they have the same contents.
+  The elements do not need to be in the same order.  If values are
+  repeated, they do have to appear an equal number of times in each list.
+  \param from The list to compare with this list.
+  \return False if the lists are equal, true otherwise.
+  */
   int operator!=(const DLIList<X>& from);
 
+  //! Gets a reference to the element with the given index.
+  /*! The index is zero-based.
+  \param index The index to the desired element.
+  \return A reference to the indicated element.
+  */
   X & operator[](int index) const;
+
+  //! Gets a reference to the last element in the list.
+  X& last_item( void ) const;
+
+  //! Merges the contents of another list into this list.
+  /*! Each element in \a merge_list is added to this list, but only if
+  it does not already appear in this list.  The result is a list where
+  no value appears twice.
+  
+  This function runs faster if you know that no value is repeated in the
+  \a merge_list.  This is indicated with the \a merge_list_unique parameter.
+  If \a merge_list_unique is
+  \a true, then elements of \merge_list will be checked against the original
+  contents of this list, but not against the other elements of \a merge_list.
+  If \a merge_list_unique is \a false, then each element will also be checked
+  against the other elements of \merge_list.
+
+  \param merge_list The list whose elements will be incorporated into this list.
+  \param merge_list_unique A flag indicating whether to skip a check for 
+  uniqueness between elements of \a merge_list.
+  */
   void merge_unique(const DLIList<X>& merge_list, 
                     bool merge_list_unique = false);
-    //- Merges the contents of the list, merge_list, with those of "this"
-    //- list, ensuring that items that are being added do not already
-    //- exist in "this" list.  If the items are known to appear in the
-    //- merge_list only once, then it can be done faster.
 
+  //! Merges the contents of a list of a different type into this list.
+  /*! This function is like merge_unique(), except that the type of object
+  stored by \a merge_list is not the same as this list's type.  The type of 
+  object stored in the other list must be able to be static_cast<> to this 
+  list's type.  
+  \param merge_list The list whose elements will be incorporated into this list.
+  \param merge_list_unique A flag indicating whether to skip a check for 
+  uniqueness between elements of \a merge_list.
+  \sa merge_unique()
+  */
+  template<typename Y> inline void casting_merge_unique(const DLIList<Y>& merge_list,
+                                                        bool merge_list_unique = false)
+    {
+        // Save the current index of the merge_list
+      int old_size = size();   
+      int i, j, check_index;
+      
+      X new_item;
+
+      // The resulting list will be at least as large as the larger of the two lists.
+      // Reserve space so we don't have to reallocate so often.  Note that if
+      // this list is already bigger than merge_list, the reserve won't
+      // make the list shorter.
+      reserve(merge_list.size());
+
+      for ( i = 0; i < merge_list.size(); i++)
+      {
+          // Get the item from the merge_list and insert it into "this"
+          // list if it doesn't already exist there.
+        new_item = static_cast<X>(merge_list[i]);
+        check_index = merge_list_unique ? old_size : size();
+
+        // Append the new item and then remove it if necessary.
+        append(new_item);
+        for ( j = 0; j < check_index; j++ )
+        {
+          if ( listArray[j] == new_item )
+          {
+            itemCount--;
+            break;
+          }
+        }
+      }
+    }
+
+  //! Remove all elements that are not also in \a merge_list, preserving order.
+  /*! This version is O(n^2).  If the order of elements in the list does 
+  not matter, then consider using intersect_undordered(), which is O(n + sort_time).
+  \param merge_list The list containing values to keep.
+  \sa intersect_unordered(const DLIList<X>& merge_list)
+  */
   void intersect(const DLIList<X>& merge_list);
-  void intersect(void* merge_list);
+  //! Remove all elements that are not also in \a merge_list, not preserving order.
+  /*! This version is O(n + sort_time).  If the order of elements in the list 
+  is significant, then use intersect(), which is O(n^2) but preserves list order.
+  \param merge_list The list containing values to keep.
+  \sa intersect(const DLIList<X>& merge_list)
+  */
   void intersect_unordered(const DLIList<X>& merge_list);
-  //- The regular version is O(n^2)
-  //- The unordered version is O(n + sort_time).
 
+  //! Appends the new item to the list, but only if it isn't already in the list.
+  /*! In either case, the current position is not changed.
+  \return CUBIT_TRUE if the item was added, otherwise CUBIT_FALSE.
+  */
   CubitBoolean append_unique(X new_item);
-    //- Appends the new item to the list, if it doesn't already exist
-    //- in the list. In either case, index is not changed.
-    //- Return CUBIT_TRUE if the item was added, else CUBIT_FALSE.
   
+  //! Ensure each element of the list only appears once, not preserving order.
+  /*! The list is first sorted for speed, so the order of elements may change.
+  The current position is set to 0.
+  \sa uniquify_ordered()
+  */
   void uniquify_unordered();
-    //- Ensure each element only appears once.
-    //- Sorts first for speed, resets index to 0.
     
+  //! Ensure each element of the list only appears once, preserving order.
+  /*! The order of elements is preserved, but at a speed cost compared to 
+  uniquify_unordered().  The current position is set to 0.
+  \sa uniquify_unordered()
+  */
   void uniquify_ordered();
-    //- Ensures each element appears only once.
-    //- Preserves order.  Resets index to 0.
   
+  //! Removes the current item from the list.
+  /*! Remaining items with an index higher than the current item
+  are moved up in the list.  The current position is set to the next item
+  in the list (i.e., the index does not change) unless the removed item was
+  the last item in the list, in which case the current position is set to
+  the beginning of the list.
+  \return The removed item.
+  \sa remove(X val)
+  \sa remove_all_with_value(X val)
+  \sa omit(X val)
+  */
   X remove ();
-    //- Removes the current item from the list.
   
-  X remove (X item);
-    //- Removes item with value 'item' from the list.
+  //! Removes the next item with value \a val from the list.
+  /*! Only one element is removed from the list, even if the specified
+  value occurs multiple times in the list.  The list is searched from 
+  the current position to the end of the list, then from the beginning of 
+  the list to the current position.  The current position continues to 
+  point at the same element, unless it is the element which was removed,
+  in which case the behavior is identical to remove().
+  \param val The value of the item to remove.
+  \return The removed item, or X(0) if the item was not found.
+  \sa remove()
+  \sa remove_all_with_value(X val)
+  \sa omit(X val)
+  */
+  X remove (X val);
+
+  //! Remove all instances of a given value from the list.
+  /*! This function can be used to remove multiple items efficiently.
+  First, change the value of any elements you want to remove to \a val.
+  Next, call this function with that same value.  This is more efficient
+  than removing each element one at a time.  After this function call,
+  the current position is set to the start of the list.
+  \sa remove()
+  \sa remove(X val)
+  \sa omit(X val)
+  */
+  void remove_all_with_value(X val);
+
+  //! Removes all instances of a value from the list.
+  /*! The current position of the list is not changed, unless the 
+  current item is removed from the list.  If the current item is
+  removed, then the current position is moved back one item, looping
+  to the back of the list if necessary.
+  \param val The value to remove from the list.
+  \return CUBIT_TRUE if at least one instance the item was removed, CUBIT_FALSE if not.
+  \sa remove()
+  \sa remove(X val)
+  \sa remove_all_with_value(X val)
+  */
+  CubitBoolean omit (X val);
   
-  CubitBoolean omit (X old_val);
-    //- Finds instance of item by matching value and deleting next instance
-    //- of it from the list, wrapping if necessary. The current position of
-    //- the list is not changed.
-    //- Returns CUBIT_TRUE if the item was found, CUBIT_FALSE if not.
-  
+  //! Returns the value of the current item.
+  /*! \return The value of the current item. If the list is empty, X(0) is returned.
+  */
   X get () const;
-    //- Returns value of current item
   
+  //! Returns the value at next position in the list.
+  /*! The current position is not changed.  If the current position is at the
+  end of the list, the function wraps to the front of the list and returns the
+  value of the first item.
+  \return The value of the next item. If the list is empty, X(0) is returned.
+  */
   X next () const;
-    //- Returns value at next position in the list
   
+  //! Returns the value at \a n positions forward in list.
+  /*! The current position is not changed.  If \a n positions beyond the 
+  current position would move past the end of the list, the function wraps
+  around to the start of the list.
+  \param n The number of positions beyond the current position to return.
+  \return The value of the item \a n positions beyond the current position. 
+  If the list is empty, X(0) is returned.
+  */
   X next (int n) const;
-    //- Returns value at 'n' positions forward in list
   
+  //! Returns the value at the previous position in list.
+  /*! The current position is not changed.  If the current position is at the
+  beginning of the list, the function wraps to the end of the list and returns the
+  value of the last item.
+  \return The value of the previous item. If the list is empty, X(0) is returned.
+  */
   X prev () const;
-    //- Returns value at previous position in list
   
+  //! Returns the value at \a n positions back in list.
+  /*! The current position is not changed.  If \a n positions before the 
+  current position would move before the beginning of the list, the function wraps
+  around to the end of the list.
+  \param n The number of positions behind the current position to return.
+  \return The value of the item \a n positions before the current position. 
+  If the list is empty, X(0) is returned.
+  */
   X prev (int n) const;
-    //- Returns value 'n' positions back in list
   
+  //! Returns the current value, then advances the current position by one.
+  /*! If the current position is at the end of the list, the function will
+  wrap to the beginning of the list.
+  \return The value at the current position, before stepping.
+  */
   X get_and_step ();
-    //- Returns value, then steps
   
+  //! Returns the current value, then moves the current position back one.
+  /*! If the current position is at the beginning of the list, the function will
+  wrap to the end of the list.
+  \return The value at the current position, before stepping back.
+  If the list is empty, X(0) is returned.
+  */
   X get_and_back ();
-    //- Returns value, then goes back
   
+  //! Advances the current position by one, then returns the current value.
+  /*! If the current position is at the end of the list, the function will
+  wrap to the beginning of the list.
+  \return The value at the current position, after stepping.
+  */
   X step_and_get ();
-    //- Steps then returns value
   
-//  CubitBoolean move_between (X item1, X item2);
+  //! Moves to the next instance of this value, wrapping if necessary.
+  /*! \return Returns \a true if the item was found in the list, otherwise returns \a false.
+  */
   CubitBoolean move_to(X item);
-    //- Moves to the next instance of this value, wrapping if necessary
+
+  //! Return \a true if the item is in the list, \a false otherwise.
+  /*! \return Returns \a true if the item was found in the list, otherwise returns \a false.
+  */
   CubitBoolean is_in_list(X item) const;
-    //- Return True if item is in the list, false otherwise.
 
+  //! Returns and removes last value in list.
+  /*! \return Returns the last value in the list.  If the list is empty, returns X(0).
+  */
   X pop();
-    //- Returns and removes last value in list
-  X push(X value);
-    //- Moves to end of list and appends and returns value
-  void insert (X new_item);
-    //- put new item in list after current item and make it current
-    //- Inefficient due to bubbling.
-  void insert_first(X new_item);
-    //- Adds value at start of list.  Inefficient due to bubbling.
+
+  //! Puts a value on the end of the list.
+  /*! The current position is then set to the end of the list.
+  \param val The value to place at the end of the list.
+  \return The value placed on the end of the list.
+  \sa push_back(X val)
+  */
+  X push(X val);
+
+  //! Insert an item into the list, after current item.
+  /*! The newly inserted item becomes the current item.  This function is
+  inefficient due to bubbling.
+  \param val The item to insert.
+  */
+  void insert (X val);
+
+  //! Add a value at start of the list. 
+  /*! The current position is set to the beginning of the list.
+  Inefficient due to bubbling.
+  \param val The value to place at the start of the list.
+  */
+  void insert_first(X val);
+
+  //! Place an item at the end of the list.
+  /*! This is the most efficient way to insert an item to the list.
+  The current position is unchanged.
+  \param val The value to place at the end of the list.  
+  */
   void append(X new_item);
-    //- Adds value to end of list
+
+  //! Remove the current value and put last value in the list in its place.
+  /*!  If list order isn't important, this is much more efficient than remove().
+  \return The value removed from the list, or X(0) if the list was empty.
+  */
   X extract();
-    //- Removes current value and puts last value
-    //- in the list in its place.  If list order isn't important, this is
-    //- much more efficient than remove().
   
-  X change_to(X new_value);
-    //- Changes value of current Item.
+  //! Change the value of the current item.
+  /*! Because this function does not actually remove or insert an element,
+  it is quite efficient.  If the list is empty, the new value will not be
+  inserted into the list.
+  \return The former value of the current item, or X(0) if the list was empty.
+  */
+  X change_to(X val);
   
+  //! Orders the list elements from lowest to highest.
+  /*! The sort order is determined by operator>= for the
+  stored element type.  
+  
+  Use reverse after this call if you want to go the
+  other direction.
+  */
   void sort();
-    //- Orders the list elements from lowest to highest.
-    //- Use reverse after this call if you want to go the
-    //- other direction.
+
+  //! A function which determines the relative order of objects.
+  /*!
+  The SortFunction should return a negative number if \a a should
+  be before \a b, a positive number if \a b comes before \a a, and
+  zero if they are equal, or relative order doesn't matter.
+  \param a The first object in the comparison
+  \param b The second object in the comparison
+  \sa sort(SortFunction f)
+  */
+  typedef int (*SortFunction)(X& a, X& b);
+
+  //! Orders the list elements from lowest to highest, as defined by a function.
+  /*! The sort order is determined by the passed in SortFunction.
   
-  typedef int (*SortFunction)(X& a, X& b);
+  Use reverse after this call if you want to go the
+  other direction.
+  \param f The function which determines the sort order.
+  \sa SortFunction
+  */
   void sort(SortFunction f);
-    //- Sorts based on a function you pass in.
-    //- SortFunction should return a negative number if 'a' should
-    //- be before 'b', a positive number if 'b' comes before 'a', and
-    //- zero if they are equal, or relative order doesn't matter.
+
+  //! Allocate enough space for at least \a min_size elements.
+  /*! If there is already enough space allocated, the function does nothing; this
+  function will never reduce the amount of memory allocated to the list.
+  \param min_size The minimum number of elements to be prepared to store.
+  */
+  void reserve(int min_size);
   
+  //! Returns the number of items in the list
+  /*! \return The number of items current in the list. */
   int size() const
     { return itemCount; }
-    //- Returns the number of items in the list
 
+  //! Returns current index of the current position
+  /*! \return the current position */
   int get_index()
      { return index; }
-    //- Returns current index value
   
-  int where_is_item(X item) const;
-    //- Return index of item in list, or -1 if item is not in the list.
+  //! Return the index of an item in list, or -1 if the item is not in the list.
+  /*! The location of the first instance of \a val is returned as a zero-based
+  index from the start of the list.  The list is searched starting from the 
+  current position, wrapping to the front of the list if necessary.
+  \param val The value to search for.
+  \return The index of the first instance of \a val, or -1 if the value is not found.
+  */
+  int where_is_item(X val) const;
 
-   int memory_use(CubitBoolean verbose_boolean);
-   //- return memory allocated in bytes
+  //! Returns the number of bytes allocated for this list's storage space.
+  int memory_use(CubitBoolean verbose_boolean);
    
+  //! Copy this list's contents into an array.
+  /*! It is assumed that \a other_array is big enough to hold all of this
+  list's elements.  No check is made to verify this.
+  \param other_array The array into which this list's contents will be copied.
+  */
   void copy_to(X *other_array);
-    //- copy this list's listArray into other_array
 
+  //! Copy items from an array into this list.
+  /*! Any prior contents of this list are removed.  The list allocates additional storage if necessary to hold all of
+  \a other_array's contents.
+  \param other_array The array from which items will be copied.
+  \param other_size The number of items to be copied from \a other_array.
+  */
   void copy_from(X *other_array, const int other_size);
-    //- copy items from other_array to this list
 
-  CubitBoolean move_to_nearby(const X objPtr);
-    //- searches from the current item both forward and backward.
+  //! Moves to the nearest instance of \a val, searching both forward and backward.
+  /*! 
+  \return True if an item with the specified value was found, false otherwise.
+  */
+  CubitBoolean move_to_nearby(const X val);
 
-  int distance_to_nearby(const X objPtr);
-    //- Sets indes to the item in the list that matches {body}
+  //! Returns the distance to the nearest element with a given value.
+  /*! The returned value is always positive, regardless of whether the
+  closest element is before or after the current position.
+  \param val The value to search for.
+  \return The distance to the closest element with value \a val.
+  */
+  int distance_to_nearby(const X val);
 
-  CubitBoolean move_between(X objPtr1, X objPtr2);
-    //- Sets the index to the place matching one of the items,
-    //- where the previous item is the other item
+  //! Set the current position to point at one of the two items, where the previous item is the other item.
+  /*! This function looks for a place in the list where these two items are adjacent 
+  to each other, in either order.  The current position is then set to the later
+  of the two items.  The function acts in a wrapped manner, such that the last
+  item in the list is considered adjacent to the first item in the list.
+  \param val1 One of the values to look for.
+  \param val2 The other value to look for.
+  \return \a true if the two items are found adjacent to each other, \a false otherwise.
+  */
+  CubitBoolean move_between(X val1, X val2);
 
 private:
   void lengthen_list(int by_how_much = DLI_COUNT_INCREMENT,
@@ -270,6 +565,13 @@
     return listArray[index];
 }
 
+template <class X> inline
+X & DLIList<X>::last_item(void) const
+{
+    assert( itemCount > 0 );
+    return listArray[itemCount-1];
+}
+
 template <class X> inline void DLIList<X>::step()
 {
   if (itemCount)

Modified: cgm/branches/cubit/util/DLList.hpp
===================================================================
--- cgm/branches/cubit/util/DLList.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/DLList.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -31,8 +31,8 @@
 #include "ArrayBasedContainer.hpp"
 #include "CubitDefines.h"
 #include "CubitMessage.hpp"
-#include <string.h>
-#include <assert.h>
+#include <cstring>
+#include <cassert>
 #include "CubitUtilConfigure.h"
 
 class CUBIT_UTIL_EXPORT DLList : public ArrayBasedContainer

Modified: cgm/branches/cubit/util/DynamicArray.cpp
===================================================================
--- cgm/branches/cubit/util/DynamicArray.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/DynamicArray.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,7 +4,7 @@
 //- Version: $Id: 
 
 #include "DynamicArray.hpp"
-#include <string.h>
+#include <cstring>
 
 #if defined(NO_MEMMOVE)
 extern "C" void *CUBIT_memmove(void *s1, const void *s2, size_t n);

Modified: cgm/branches/cubit/util/DynamicArray.hpp
===================================================================
--- cgm/branches/cubit/util/DynamicArray.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/DynamicArray.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -23,7 +23,7 @@
 
 #include "MemoryManager.hpp"
 #include "ArrayBasedContainer.hpp"
-#include <string.h>
+#include <cstring>
 #include "CubitUtilConfigure.h"
 
 class CUBIT_UTIL_EXPORT DynamicArray : public ArrayBasedContainer

Modified: cgm/branches/cubit/util/ElementType.h
===================================================================
--- cgm/branches/cubit/util/ElementType.h	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ElementType.h	2010-01-06 19:22:14 UTC (rev 3423)
@@ -4,7 +4,7 @@
   syncronized correctly.  The invalid type MUST be 0
   if we have an unknown element type in the .cc file.
   DRW 10/20/97                                       */
-  
+
 enum ElementType { SPHERE_EXO=0,
                    BAR, BAR2, BAR3,
                    BEAM, BEAM2, BEAM3,
@@ -16,7 +16,10 @@
                    QUAD, QUAD4, QUAD5, QUAD8, QUAD9,
                    TETRA, TETRA4, TETRA8, TETRA10, TETRA14,
                    PYRAMID, PYRAMID5, PYRAMID8, PYRAMID13, PYRAMID18,
-                   HEX, HEX8, HEX9, HEX20, HEX27, HEXSHELL, 
+                   HEX, HEX8, HEX9, HEX20, HEX27, HEXSHELL,
+                   FLATQUAD, FLATWEDGE, FLATHEX,
+                   GAP, LUMPMASS, RIGID, CONSTRAINT,
+                   WEDGE,
                    INVALID_ELEMENT_TYPE};
 /*Invalid element type must be the last type...*/
 #endif

Added: cgm/branches/cubit/util/ExternalCoordinateSystem.hpp
===================================================================
--- cgm/branches/cubit/util/ExternalCoordinateSystem.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/ExternalCoordinateSystem.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,21 @@
+
+#ifndef EXTERNAL_COORDINATE_SYSTEM_HPP
+#define EXTERNAL_COORDINATE_SYSTEM_HPP
+
+class ExternalCoordinateSystem
+{
+  public:
+
+  virtual ~ExternalCoordinateSystem() {}
+
+	//given s,n return x,y,z
+	virtual bool GetXYZ( double i, double j, double k,
+   		    		 double &x, double &y, double &z ) = 0;
+   	
+  //given x,y,z , return an s,n
+  virtual bool GetIJK( double x, double y, double z,
+	      			double &i, double &j, double &k ) = 0;	  
+};
+
+#endif
+

Modified: cgm/branches/cubit/util/GMem.cpp
===================================================================
--- cgm/branches/cubit/util/GMem.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/GMem.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,5 +1,5 @@
 #include "GMem.hpp"
-#include <string.h> // To define NULL
+#include <cstring> // To define NULL
 #include "CubitVector.hpp"
 #include "DLIList.hpp"
 #include "OctTree.hpp"

Modified: cgm/branches/cubit/util/GeometryDefines.h
===================================================================
--- cgm/branches/cubit/util/GeometryDefines.h	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/GeometryDefines.h	2010-01-06 19:22:14 UTC (rev 3423)
@@ -23,8 +23,10 @@
 /* than GEOMETRY_RESABS the points are considered to be identical. */
 #ifdef __cplusplus
 const double GEOMETRY_RESABS = 1.0E-6;
+const double DEFAULT_GEOM_FACTOR = 500.0;
 #else
 #define GEOMETRY_RESABS 1.0E-6
+#define DEFAULT_GEOM_FACTOR 500.0
 #endif
 
 /* Types of solid modeler engines. */
@@ -36,6 +38,8 @@
    NOT_A_SOLID_MODELER,
    ACIS,
    PROE_GEOM,                  /* Normal Pro/E model */
+   PROE_PART,
+   PROE_ASSEMBLY,
    PROE_FEM_MESH_SOLID,        /* Pro/Mesh models... */
    PROE_FEM_MESH_SHELL,
    PROE_FEM_MESH_MIXED,
@@ -77,11 +81,42 @@
   TORUS_SURFACE_TYPE,
   BEST_FIT_SURFACE_TYPE,
   FACET_SURFACE_TYPE,
+  CYLINDER_SURFACE_TYPE, // only currently defined in ACIS Engine
   UNDEFINED_SURFACE_TYPE,
   
     /* Lump types */
   UNDEFINED_LUMP_TYPE
 };
 
+enum ImprintType
+{
+  NO_IMPRINT=0,
+  ONLY_INVOLVED_BODIES,
+  INCLUDE_NEIGHBORS,
+  TOL_IMPRINT,
+  TOL_IMPRINT_INCLUDE_NEIGHBORS
+};
+
+/* loops may be the following types */
+enum LoopType
+{
+  /* Unknown loop type */
+  LOOP_TYPE_UNKNOWN,
+  
+  /* The external loop of a surface */
+  LOOP_TYPE_EXTERNAL,
+  
+  /* The loop is a hole */
+  LOOP_TYPE_HOLE,
+  
+  /* The loop is a u or v periodic loop (only applies to periodic surfaces)
+   * An example of this is a cylindrical surface with only 2 loops with each
+   * loop defining a cap of the cylinder. 
+   * If its a u periodic loop, the face is periodic in u */
+  LOOP_TYPE_U_PERIODIC,
+  LOOP_TYPE_V_PERIODIC
+};
+
+
 #endif
 

Modified: cgm/branches/cubit/util/GetLongOpt.hpp
===================================================================
--- cgm/branches/cubit/util/GetLongOpt.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/GetLongOpt.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -24,7 +24,7 @@
 
 #include <iostream>
 
-#include <string.h>
+#include <cstring>
 #include "CubitUtilConfigure.h"
 
 class CUBIT_UTIL_EXPORT GetLongOpt {

Modified: cgm/branches/cubit/util/GfxDebug.cpp
===================================================================
--- cgm/branches/cubit/util/GfxDebug.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/GfxDebug.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -3,7 +3,8 @@
 #include "GfxDebug.hpp"
 #include "GMem.hpp"
 #include "CubitVector.hpp"
-#include <assert.h>
+#include "DLIList.hpp"
+#include <cassert>
 
 GfxDebug* GfxDebug::mInstance = 0;
 
@@ -491,6 +492,16 @@
   mInstance->p_draw_point(*vector, color);
 }
 
+void GfxDebug::draw_points( DLIList<CubitVector> &points, int color )
+{
+    if (!mInstance) return;
+    int i;
+    for ( i = 0; i < points.size(); i++ )
+    {
+        mInstance->p_draw_point( points[i], color );
+    }
+}
+
 // draw line of points {x,y,z}, {x,y,z} of color
 void GfxDebug::draw_line(float x1, float y1, float z1, float x2, float y2, float z2, int color)
 {

Modified: cgm/branches/cubit/util/GfxDebug.hpp
===================================================================
--- cgm/branches/cubit/util/GfxDebug.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/GfxDebug.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -185,6 +185,7 @@
     static void draw_point(float x, float y, float z, int color);
     static void draw_point(const CubitVector& vector, int color);
     static void draw_point(CubitVector* vector, int color);
+    static void draw_points( DLIList<CubitVector> &points, int color );
 
     // draw line of points {x,y,z}, {x,y,z} of color
     static void draw_line(float x1, float y1, float z1, 

Added: cgm/branches/cubit/util/GlobalCommandFeedback.cpp
===================================================================
--- cgm/branches/cubit/util/GlobalCommandFeedback.cpp	                        (rev 0)
+++ cgm/branches/cubit/util/GlobalCommandFeedback.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,18 @@
+#include "GlobalCommandFeedback.hpp"
+
+namespace GlobalCommandFeedback
+{
+  ManagedPtrVector<CommandFeedback>* instance_;
+  
+  void create()
+  { instance_ = new ManagedPtrVector<CommandFeedback>; }
+    
+  void destroy()
+  {
+    delete instance_;
+    instance_ = NULL;
+  }
+  
+  ManagedPtrVector<CommandFeedback>& instance()
+  { return *instance_; }
+}

Added: cgm/branches/cubit/util/GlobalCommandFeedback.hpp
===================================================================
--- cgm/branches/cubit/util/GlobalCommandFeedback.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/GlobalCommandFeedback.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,15 @@
+#ifndef GLOBAL_COMMAND_FEEDBACK_HPP
+#define GLOBAL_COMMAND_FEEDBACK_HPP
+
+#include "CommandFeedback.hpp"
+#include "ManagedPtrVector.hpp"
+#include "CubitUtilConfigure.h"
+
+namespace GlobalCommandFeedback
+{
+  CUBIT_UTIL_EXPORT void create();
+  CUBIT_UTIL_EXPORT void destroy();
+  CUBIT_UTIL_EXPORT ManagedPtrVector<CommandFeedback>& instance();
+};
+
+#endif

Modified: cgm/branches/cubit/util/IntersectionTool.cpp
===================================================================
--- cgm/branches/cubit/util/IntersectionTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/IntersectionTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -98,14 +98,19 @@
   return t;
 }
 
-int IntersectionTool::point_on_polyline(CubitVector& pt, DLIList<CubitVector*> &pt_list)
+int IntersectionTool::point_on_polyline(CubitVector& pt, DLIList<CubitVector*> &pt_list,
+                                        double *tol_in)
 {
   int i, ret;
   double t, distance;
   double pt_coords[3];
   double line_coords1[3];
   double line_coords2[3];
+  double tol = GEOMETRY_RESABS;
 
+  if(tol_in)
+    tol = *tol_in;
+
   ret = 0;
 
   pt_coords[0] = pt.x();
@@ -127,7 +132,7 @@
 
     distance = distance_point_line(pt_coords, line_coords1, line_coords2, t);
 
-    if(distance > -GEOMETRY_RESABS && distance < GEOMETRY_RESABS)
+    if(distance > -tol && distance < tol)
     {
       i = 1;
       ret = 1;
@@ -397,3 +402,182 @@
   point_2 = p2 + tc*v;
   return CUBIT_SUCCESS;
 }
+
+int IntersectionTool::intersect_triangle_with_ray( CubitVector &ray_origin, CubitVector &ray_direction,
+												  const CubitVector *p0, const CubitVector *p1, const CubitVector *p2,
+												  CubitVector* point, double &distance, int &edge_hit )
+{
+	// This algorithm can be found at http://geometryalgorithms.com/
+
+	CubitVector n;           // triangle vectors
+    CubitVector w0, w;       // ray vectors
+    double a, b;             // params to calc ray-plane intersect
+
+	double tol = GEOMETRY_RESABS;
+
+	// get triangle edge vectors and plane normal
+	CubitVector u(  p1->x() - p0->x(),
+					p1->y() - p0->y(),
+					p1->z() - p0->z()); //(*p1-*p0);
+	CubitVector v(  p2->x() - p0->x(),
+					p2->y() - p0->y(),
+					p2->z() - p0->z()); // = (*p2-*p0);
+
+    n = u * v; // cross product to get normal
+
+    if (n.length_squared() == 0)   // triangle is degenerate
+        return -1;                 // do not deal with this case
+
+    //dir = R.P1 - R.P0;             // ray direction vector
+    //w0 = R.P0 - T.V0;
+	w0 = CubitVector(ray_origin.x() - p0->x(),
+		ray_origin.y() - p0->y(),
+		ray_origin.z() - p0->z());
+
+    a = -(n%w0);
+    b = (n%ray_direction);
+    if (fabs(b) < tol) {     // ray is parallel to triangle plane
+        if (a == 0)                // ray lies in triangle plane
+            return 2;
+        else return 0;             // ray disjoint from plane
+    }
+
+    // get intersect point of ray with triangle plane
+    distance = a / b;
+    if (distance < 0.0)                   // ray goes away from triangle
+        return 0;                  // => no intersect
+    // for a segment, also test if (r > 1.0) => no intersect
+
+    point->set(ray_origin + distance * ray_direction);           // intersect point of ray and plane
+
+	// set distance to be absolute distance (if ray_direction was a unit vector)
+    distance = distance * ray_direction.length();
+
+    // is point inside facet?
+    double uu, uv, vv, wu, wv, D;
+    uu = u%u;
+    uv = u%v;
+    vv = v%v;
+    //w = *I - T.V0;
+	w = CubitVector(point->x() - p0->x(),
+					point->y() - p0->y(),
+					point->z() - p0->z());
+    wu = w%u;
+    wv = w%v;
+    D = uv * uv - uu * vv;
+
+    // get and test parametric coords
+    double s, t;
+    s = (uv * wv - vv * wu) / D;
+    if (s < 0.0 || s > 1.0)        // point is outside facet
+        return 0;
+    t = (uv * wu - uu * wv) / D;
+    if (t < 0.0 || (s + t) > 1.0)  // point is outside facet
+        return 0;
+
+	if (s==0)
+		edge_hit = 2; //lies along v, edge #2
+	if (t==0)
+		edge_hit = 1; //lies along u, edge #1
+	if (s+t==1)
+		edge_hit = 3; //lies along edge #3
+
+	// note:
+	// if s and t are both 0, hit the point p0
+	// if s=1 and t=0, hit point p1
+	// if s=0 and t=1, hit point p2
+
+    return 1; // point is in facet
+
+}
+
+int IntersectionTool::intersect_segment_with_ray( CubitVector &ray_origin, CubitVector &ray_direction,
+												 const CubitVector *p0, const CubitVector *p1,
+												 CubitVector* point, double &hit_distance, int &point_hit, double tol )
+{
+	// This algorithm can be found at http://geometryalgorithms.com/
+
+	if (tol == 0.0)
+		tol = GEOMETRY_RESABS;
+
+	CubitVector u = CubitVector(*p0, *p1);
+	CubitVector v = ray_direction;
+	v.normalize();
+
+	CubitVector w = CubitVector(ray_origin, *p0);
+
+	double sc, tc;         // sc is fraction along facet edge, tc is distance along ray
+	
+	double a = u%u;        // always >= 0
+    double b = u%v;
+    double c = v%v;        // always >= 0
+    double d = u%w;
+    double e = v%w;
+    double D = a*c - b*b;  // always >= 0
+
+    // compute the line parameters of the two closest points
+    if (D < tol)
+	{
+		// the lines are almost parallel
+        sc = 0.0;
+        tc = (b>c ? d/b : e/c);   // use the largest denominator
+    }
+    else
+	{
+        sc = (b*e - c*d) / D;
+        tc = (a*e - b*d) / D;
+    }
+
+    // get the difference of the two closest points
+    CubitVector dP = CubitVector(w + (sc * u) - (tc * v));  // = <0 0 0> if intersection
+
+    double distance = sqrt(dP % dP); // return the closest distance (0 if intersection)
+
+	point->set(*p0 + (sc * u));
+	hit_distance = tc; //distance from origin to intersection point
+
+	if (distance < tol)
+	{
+		//check if parallel (infinite intersection)
+		if (D < tol)
+			return 2;
+		//check if on edge
+		if (sc <= 1.0 && sc >= 0.0)
+		{
+			if (sc==0)
+				point_hit = 1; //hit point p0
+			if (sc==1)
+				point_hit = 2; //hit point p1
+
+			return 1;
+		}
+		else
+			return 0;
+	}
+
+	return 0;
+}
+
+int IntersectionTool::intersect_point_with_ray( CubitVector &ray_origin, CubitVector &ray_direction, 
+	  const CubitVector* point, double &distance, double tol)
+{
+	if (tol == 0.0)
+		tol = GEOMETRY_RESABS;
+
+	//Does the ray pass through the Point?
+	// Calc distance from ray origin to Point.
+	// Then compute coord's of point along ray that distance.
+	// Calc distance between Point and this ray-point. If less than tolerance, a hit.
+
+	CubitVector pointB;
+	double dist1 = point->distance_between(ray_origin);
+	ray_origin.next_point(ray_direction, dist1, pointB);
+
+	if ( pointB.distance_between_squared(*point) <= (tol*tol) )
+	{
+		distance = dist1;
+		return 1;
+	}
+	
+	return 0;
+}

Modified: cgm/branches/cubit/util/IntersectionTool.hpp
===================================================================
--- cgm/branches/cubit/util/IntersectionTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/IntersectionTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -30,7 +30,8 @@
 
   double distance_point_line(const double point[3], const double start[3], 
                              const double end[3], double &t);
-  int point_on_polyline(CubitVector& pt, DLIList<CubitVector*> &pt_list);
+  int point_on_polyline(CubitVector& pt, DLIList<CubitVector*> &pt_list,
+                         double *tol_in = NULL);
 
   double parametric_position(const double node[3],
                            const double pt1[3],
@@ -49,6 +50,41 @@
 
   virtual CubitStatus initialize(){return CUBIT_SUCCESS;}
 
+  // The following copyright applies to the following two functions...
+  //
+  // Copyright 2001, softSurfer (www.softsurfer.com)
+  //
+  // This code may be freely used and modified for any purpose
+  // providing that this copyright notice is included with it.
+  // SoftSurfer makes no warranty for this code, and cannot be held
+  // liable for any real or imagined damage resulting from its use.
+  // Users of this code must verify correctness for their application.
+
+  static int intersect_triangle_with_ray( CubitVector &ray_origin, CubitVector &ray_direction,
+	  const CubitVector *p0, const CubitVector *p1, const CubitVector *p2,
+	  CubitVector* point, double &distance, int &edge_hit );
+    //- Find intersection point of a ray and a triangle
+    //    Return: -1 = triangle is degenerate (a segment or point)
+    //             0 = disjoint (no intersect)
+    //             1 = intersect at unique point
+    //             2 = are in the same plane
+
+  static int intersect_segment_with_ray( CubitVector &ray_origin, CubitVector &ray_direction,
+	  const CubitVector *p0, const CubitVector *p1,
+	  CubitVector* point, double &distance, int &point_hit, double tol=0.0 );
+    //- Find intersection point of a ray and a facet edge
+    //    Return: -1 = edge is degenerate (a point)
+    //             0 = disjoint (no intersect)
+    //             1 = intersect at unique point
+    //             2 = are the same line (infinite points)
+
+  static int intersect_point_with_ray( CubitVector &ray_origin, CubitVector &ray_direction, 
+	  const CubitVector* point, double &distance, double tol=0.0);
+    //- Find intersection of a ray and a point
+    //	  Return: 0 = no intersection
+    //			  1 = intersection
+
+
 protected:
   double mTolerance;
   double mToleranceSquared;

Modified: cgm/branches/cubit/util/KDDTree.cpp
===================================================================
--- cgm/branches/cubit/util/KDDTree.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/KDDTree.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -23,8 +23,8 @@
 // Include Files
 //---------------------------------
 
-#include <stdlib.h>
-#include <stdio.h>
+#include <cstdlib>
+#include <cstdio>
 #include <time.h>
 
 #include "KDDTree.hpp"

Modified: cgm/branches/cubit/util/Makefile.am
===================================================================
--- cgm/branches/cubit/util/Makefile.am	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/Makefile.am	2010-01-06 19:22:14 UTC (rev 3423)
@@ -38,6 +38,7 @@
   CubitStack.cpp \
   CubitString.cpp \
   CubitTransformMatrix.cpp \
+  CubitUndo.cpp \
   CubitUtil.cpp \
   CubitVector.cpp \
   DIntArray.cpp \
@@ -46,6 +47,7 @@
   GMem.cpp \
   GetLongOpt.cpp \
   GfxDebug.cpp \
+  GlobalCommandFeedback.cpp \
   IntersectionTool.cpp \
   MemoryBlock.cpp \
   MemoryManager.cpp \
@@ -71,6 +73,7 @@
   AppUtil.hpp \
   ArrayBasedContainer.hpp \
   CastTo.hpp \
+  CommandFeedback.hpp \
   CpuTimer.hpp \
   Cubit2DPoint.hpp \
   CubitBox.hpp \
@@ -99,6 +102,7 @@
   CubitStack.hpp \
   CubitString.hpp \
   CubitTransformMatrix.hpp \
+  CubitUndo.hpp \
   CubitUtil.hpp \
   CubitUtilConfigure.h \
   CubitVector.hpp \
@@ -119,10 +123,12 @@
   DynamicDLIIterator.hpp \
   DynamicTreeIterator.hpp \
   ElementType.h \
+  ExternalCoordinateSystem.hpp \
   GMem.hpp \
   GeometryDefines.h \
   GetLongOpt.hpp \
   GfxDebug.hpp \
+  GlobalCommandFeedback.hpp \
   IGUIObservers.hpp \
   IdSetEvent.hpp \
   IndexedDouble.hpp \
@@ -131,11 +137,14 @@
   KDDTree.hpp \
   KDDTreeNode.hpp \
   LocalStart.h \
+  ManagedPtrVector.hpp \
   MemoryBlock.hpp \
   MemoryManager.hpp \
   MergeEvent.hpp \
   OctTree.hpp \
   OctTreeCell.hpp \
+  OrderedMap.hpp \
+  OrderedSet.hpp \
   ParamCubitPlane.hpp \
   ParamTool.hpp \
   PlanarParamTool.hpp \

Added: cgm/branches/cubit/util/ManagedPtrVector.hpp
===================================================================
--- cgm/branches/cubit/util/ManagedPtrVector.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/ManagedPtrVector.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,193 @@
+#ifndef MANAGED_PTR_VECTOR
+#define MANAGED_PTR_VECTOR
+
+#include <vector>
+#include <memory>
+
+//! A vector of pointers to objects that are automatically deleted when the container itself is deleted.
+/*! Loosely
+modeled after the boost ptr containers.
+*/
+template <typename X>
+class ManagedPtrVector
+{
+public:
+  typedef X value_type;
+  typedef X& reference_type;
+  typedef size_t size_type;
+  typedef std::vector<X*> container_type;
+  
+  class iterator
+  {
+  public:
+    typedef iterator this_type;
+    typedef X& reference;
+    typedef size_t size_type;
+    typedef size_t difference_type;
+    
+    iterator()
+      {}
+    iterator(const this_type& rhs)
+        :mIter(rhs.mIter)
+      {}
+    iterator(const typename ManagedPtrVector<X>::container_type::iterator& rhs)
+        : mIter(rhs)
+      {}
+    ~iterator()
+      {}
+    
+    X* operator->()
+      { return *mIter; }
+    reference operator*() const
+      { return **mIter; }
+    
+    bool operator==(const this_type& rhs) const
+      { return this->mIter == rhs.mIter; }
+    bool operator!=(const this_type& rhs) const
+      { return this->mIter != rhs.mIter; }
+    
+    this_type& operator++()
+      {
+        ++mIter;
+        return *this;
+      }
+    
+    this_type operator++(int)
+      {
+        this_type rv = *this;
+        ++mIter;
+        return rv;
+      }
+    
+    this_type& operator--()
+      {
+        --mIter;
+        return *this;
+      }
+    
+    this_type operator--(int)
+      {
+        this_type rv = *this;
+        --mIter;
+        return rv;
+      }
+
+    this_type operator+(difference_type n)
+    {
+      this_type rv = *this;
+      rv += n;
+      return rv;
+    }
+    
+    this_type& operator+=(difference_type n)
+      {
+        mIter += n;
+        return *this;
+      }
+    
+    this_type& operator-=(difference_type n)
+      {
+        mIter -= n;
+        return *this;
+      }
+    
+    reference operator[](difference_type i) const
+      {
+        return reference(*(mIter+i));
+      }
+    
+  private:
+    typename ManagedPtrVector<X>::container_type::iterator mIter;
+  };
+  
+  
+  ManagedPtrVector()
+  {}
+  ~ManagedPtrVector()
+  { clear(); }
+  
+  // Add an object to the container.
+  // The container becomes "owned" by the container.
+  void push_back(X* obj)
+  { mContainer.push_back(obj); }
+
+  iterator begin()
+  { return iterator(mContainer.begin()); }
+  iterator end()
+  { return iterator(mContainer.end()); }
+
+  //! Refer by index
+  reference_type operator[](size_type i)
+  { return *(mContainer[i]); }
+
+  //! Remove an item from the list without deleting it.
+  /*! The returned auto_ptr now owns the pointer.*/
+  std::auto_ptr<X> release(iterator to_release)
+  {
+    // save a raw pointer.
+    X* rv = to_release.operator->();
+    // find the iterator in the container.  We don't have access
+    // to the internal iterator, so we have to loop through to find it.
+    // This could probably be optimized.
+    typename container_type::iterator i = mContainer.begin();
+    for (;
+      i != mContainer.end() && iterator(i) != to_release;
+      ++i)
+    {}
+    // we either found the iterator, or the end.  erase it.
+    mContainer.erase(i);
+    return std::auto_ptr<X>(rv);
+  }
+
+  //! Replace one object with another.
+  /*! The returned auto_ptr now owns the pointer removed from
+      the container, and the container owns the object pointed to
+      by \a new_val.
+  */
+  std::auto_ptr<X> replace(iterator to_replace, std::auto_ptr<X> new_val)
+  {
+    // save a raw pointer.
+    X* rv = to_replace.operator->();
+    // find the iterator in the container.  We don't have access
+    // to the internal iterator, so we have to loop through to find it.
+    // This could probably be optimized.
+    typename container_type::iterator i = mContainer.begin();
+    for (;
+      i != mContainer.end();
+      ++i)
+    {
+      if (iterator(i) == to_replace)
+      {
+        *i = new_val;
+      }
+    }
+    return std::auto_ptr<X>(NULL);
+  }
+
+  // Delete all objects contained in this container.
+  void clear()
+  {
+    // delete all the pointers
+    for (typename container_type::iterator i = mContainer.begin();
+      i != mContainer.end();
+      i++)
+    {
+      delete *i;
+    }
+    mContainer.clear();
+  }
+
+  size_type size() const
+  { return mContainer.size(); }
+
+private:
+  // Make both of these illegal
+  ManagedPtrVector(const ManagedPtrVector<X>&);
+  ManagedPtrVector& operator=(const ManagedPtrVector<X>&);
+
+  container_type mContainer;
+};
+
+
+
+#endif

Modified: cgm/branches/cubit/util/MemoryBlock.hpp
===================================================================
--- cgm/branches/cubit/util/MemoryBlock.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/MemoryBlock.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -9,7 +9,7 @@
 #ifndef MEMORY_BLOCK_HPP
 #define MEMORY_BLOCK_HPP
 
-#include <stdlib.h>
+#include <cstdlib>
 #include "CubitUtilConfigure.h"
 
 class CUBIT_UTIL_EXPORT MemoryBlock

Modified: cgm/branches/cubit/util/MemoryManager.cpp
===================================================================
--- cgm/branches/cubit/util/MemoryManager.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/MemoryManager.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -15,8 +15,8 @@
 #include "CubitMessage.hpp"
 #include "ArrayBasedContainer.hpp"
 #include "AppUtil.hpp"
-#include <assert.h>
-#include <string.h>
+#include <cassert>
+#include <cstring>
 #ifndef NT
 #include <unistd.h>
 #endif
@@ -447,38 +447,51 @@
 #endif
 
   // send requests of "wrong" size to ::new
-
-  if (size != objectSize) return ::new char[size];
-
+  
+  try
+  {
+    if (size != objectSize) return ::new char[size];
+  }
+  catch(...)
+  {
+    return (void*) NULL;
+  }
   // get new element from head of free list
 
   char* p = headOfFreeList;
 
-  if(!p)
-    {
-    // allocate new block
+  try
+  {
+    if(!p)
+        {
+        // allocate new block
 
-    int block_size  = memAllocatnSize * size;
-    char* new_block = ::new char[block_size];
-    if (!new_block) return (void*) NULL;
+        int block_size  = memAllocatnSize * size;
+        char* new_block = ::new char[block_size];
+        if (!new_block) return (void*) NULL;
 
-    // link new elements to form the free list
+        // link new elements to form the free list
 
-    int fill_limit = (memAllocatnSize - 1) * size;
-    for (int j = 0; j < fill_limit; j += size)
-    {
-      *((char**) &new_block[j]) = &new_block[j + size];
-    }
-    *((char**) &new_block[fill_limit]) = (char*) NULL;
+        int fill_limit = (memAllocatnSize - 1) * size;
+        for (int j = 0; j < fill_limit; j += size)
+        {
+          *((char**) &new_block[j]) = &new_block[j + size];
+        }
+        *((char**) &new_block[fill_limit]) = (char*) NULL;
 
-    // assign new element
+        // assign new element
 
-    p = new_block;
+        p = new_block;
 
-    // save new block to memory block stack
+        // save new block to memory block stack
 
-    memBlockStack = new MemoryBlock(memBlockStack, new_block, block_size);
+        memBlockStack = new MemoryBlock(memBlockStack, new_block, block_size);
+      }
   }
+  catch(...)
+  {
+    return (void*) NULL;
+  }
   //assign head of free list and return p
 
   headOfFreeList = *((char**) p);

Modified: cgm/branches/cubit/util/MemoryManager.hpp
===================================================================
--- cgm/branches/cubit/util/MemoryManager.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/MemoryManager.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -20,8 +20,8 @@
 const  int STATIC_MEMORY_MANAGER = 1;
 //- Static Memory Manager definition argument
 
-#include <stdlib.h>
-#include <assert.h>
+#include <cstdlib>
+#include <cassert>
 #include "CubitUtilConfigure.h"
 
 class MemoryBlock;

Modified: cgm/branches/cubit/util/OctTree.cpp
===================================================================
--- cgm/branches/cubit/util/OctTree.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/OctTree.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -110,9 +110,9 @@
     // other nodes were allocated from our internal memory bool by
     // the allocate_8() method.  We just release the whole pool.
   delete root_;
-  delete node_memory_;
+  delete [] node_memory_;
   while( mem_pages_.size() )
-    delete mem_pages_.pop();
+    delete [] mem_pages_.pop();
     
     // Reinitialize to catch stale pointer to this object.
   

Added: cgm/branches/cubit/util/OrderedMap.hpp
===================================================================
--- cgm/branches/cubit/util/OrderedMap.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/OrderedMap.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,121 @@
+//-------------------------------------------------------------------------
+// Filename      : OrderedMap.hpp
+//
+// Purpose       : An std::map that keeps order that things were inserted
+//                 into it.
+//
+// Creator       : Matt Staten
+//
+// Creation Date : 01/27/2006
+//
+// Owner         : Matt Staten
+//-------------------------------------------------------------------------
+
+#ifndef OrderedMap_HPP
+#define OrderedMap_HPP
+
+#include <map>
+#include "DLIList.hpp"
+
+template<class X, class Y> class OrderedMap
+{
+private:
+    DLIList<X> mList1;
+    std::map<X,Y> mMap;
+
+public:
+
+    OrderedMap( void ) {};
+
+    bool find( X key, Y *data = NULL ) const
+    {
+        typename std::map<X,Y>::const_iterator iter = mMap.find( key );
+        if ( iter == mMap.end() )
+        {
+            return CUBIT_FALSE;
+        }
+        if ( data )
+        {
+            *data = iter->second;
+        }
+        return CUBIT_TRUE;
+    };
+
+    // Return true if the new pair was inserted.
+    // Return false if this key is already being used.
+    bool insert( X new_key, Y new_data )
+    {
+        if ( !find( new_key ) )
+        {
+            mList1.append( new_key );
+            mMap.insert( std::map<X,Y>::value_type( new_key, new_data ) );
+            return CUBIT_TRUE;
+        }
+        return CUBIT_FALSE;
+    };
+
+    // This can be inefficient
+    void erase( X key_to_erase )
+    {
+        typename std::map<X,Y>::iterator iter = mMap.find( key_to_erase );
+        if ( iter != mMap.end() )
+        {
+            mMap.erase( iter );
+            mList1.remove_all_with_value( key_to_erase );
+        }
+    };
+
+    void erase_iter( int iter_to_erase )
+    {
+        X key_to_erase = mList1[iter_to_erase];
+        typename std::map<X,Y>::iterator iter = mMap.find( key_to_erase );
+        if ( iter != mMap.end() )
+        {
+            mMap.erase( iter );
+            mList1.remove_all_with_value( key_to_erase );
+        }
+    };
+
+    X first( int iter ) const
+    {
+        return mList1[iter];
+    }
+    Y second( int iter ) const
+    {
+        Y data;
+        bool stat = find( mList1[iter], &data );
+        assert(stat);
+        return data;
+    }
+
+    bool empty( void ) const { return ( mList1.size() == 0 ? CUBIT_TRUE : CUBIT_FALSE ); };
+    int size( void ) const { return mList1.size(); };
+
+    void clean_out( void )
+    {
+        mList1.clean_out();
+        mMap.clear();
+    };
+
+    OrderedMap<X,Y>& operator=(const OrderedMap<X,Y>&from)
+    {
+    	clean_out();
+    	for ( int i = 0; i < from.size(); i++ )
+    	{
+    		X key = from.first( i );
+    		Y data = from.second( i );
+    		this->insert( key, data );
+    	}
+    	return *this;
+    };
+
+    Y operator[]( X key ) const
+    {
+        Y data;
+        bool stat = find( key, &data );
+        assert(stat);
+        return data;
+    };
+};
+
+#endif // OrderedMap_HPP

Added: cgm/branches/cubit/util/OrderedSet.hpp
===================================================================
--- cgm/branches/cubit/util/OrderedSet.hpp	                        (rev 0)
+++ cgm/branches/cubit/util/OrderedSet.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -0,0 +1,330 @@
+//-------------------------------------------------------------------------
+// Filename      : OrderedSet.hpp
+//
+// Purpose       : A DLIList that does not allow duplicates and is faster
+//                 at inserting uniquely than DLIList.
+//
+// Creator       : Matt Staten
+//
+// Creation Date : 09/22/2005
+//
+// Owner         : Matt Staten
+//-------------------------------------------------------------------------
+
+#ifndef OrderedSet_HPP
+#define OrderedSet_HPP
+
+#include <set>
+#include "DLIList.hpp"
+
+template<class X> class OrderedSet
+{
+private:
+    DLIList<X> mList;
+    std::set<X> mSet;
+
+public:
+
+    OrderedSet( void ) {};
+    OrderedSet( const DLIList<X> list )
+    {
+        int i;
+        for ( i = 0; i < list.size(); i++ )
+        {
+            append( list[i] );
+        }
+    };
+
+    CubitBoolean is_in_list( X item ) const
+    {
+        if ( mSet.find( item ) == mSet.end() )
+        {
+            return CUBIT_FALSE;
+        }
+        return CUBIT_TRUE;
+    };
+
+    int where_is_item( X item ) const
+    {
+        CubitBoolean stat = is_in_list( item );
+        if ( stat == CUBIT_TRUE )
+        {
+            return mList.where_is_item( item );
+        }
+        return -1;
+    };
+
+    // true if it could be replaced.  false if old_item is not in the list
+    bool replace_item( X old_item, X new_item )
+    {
+        if ( is_in_list( old_item ) )
+        {
+            for ( int i = 0; i < mList.size(); i++ )
+            {
+                if ( mList[i] == old_item )
+                {
+                    mList[i] = new_item;
+                    mSet.erase( old_item );
+                    mSet.insert( new_item );
+                    return true;
+                }
+            }
+        }
+        return false;
+    };
+
+    CubitBoolean insert( X new_item )
+    {
+        if ( !is_in_list( new_item ) )
+        {
+            force_insert( new_item );
+            return CUBIT_TRUE;
+        }
+        return CUBIT_FALSE;
+    }
+
+    // Append to the end of this list.
+    CubitBoolean append( X new_item )
+    {
+        return insert( new_item );
+    }
+
+    // insert at the beginning of the list.
+    CubitBoolean prepend( X new_item )
+    {
+        if ( !is_in_list( new_item ) )
+        {
+            mList.insert_first( new_item );
+            mSet.insert( new_item );
+            return CUBIT_TRUE;
+        }
+        return CUBIT_FALSE;
+    }
+
+    void force_insert( X new_item )
+    {
+        mList.append( new_item );
+        mSet.insert( new_item );
+    };
+
+    void reverse( void )
+    {
+        mList.reverse();
+    };
+
+    void reset( void )
+    {
+        mList.reset();
+    };
+
+    void reserve( int min_size )
+    {
+      mList.reserve(min_size);
+    };
+  
+    X get_and_step( int n = 1 ) 
+    {
+        X temp = get();
+        step( n );
+        return temp;
+    };
+
+    void step( int n = 1 )
+    {
+        mList.step( n );
+    };
+
+    X get() const
+    {
+        return mList.get();
+    };
+
+    X & operator[](int index) const;
+    OrderedSet<X>& operator=(const OrderedSet<X>& from);
+    OrderedSet<X>& operator=(const DLIList<X>& from);
+    OrderedSet<X>& operator+=(const DLIList<X>& from);
+    OrderedSet<X>& operator+=(const OrderedSet<X>& from);
+    OrderedSet<X>& operator+=( X from );
+    OrderedSet<X>& operator-=(const DLIList<X>& from);
+    OrderedSet<X>& operator-=(const OrderedSet<X> &from);
+    OrderedSet<X>& operator-=(const OrderedSet<X> *from);
+    OrderedSet<X>& operator-=( X from );
+    OrderedSet<X> operator&( const OrderedSet<X> other_set ) const;
+    OrderedSet<X> operator|( const OrderedSet<X> other_set ) const;
+
+    CubitBoolean empty( void ) const { return ( mList.size() == 0 ? CUBIT_TRUE : CUBIT_FALSE ); };
+    int size( void ) const { return mList.size(); };
+    X pop( void )
+    {
+        X item = mList.pop();
+        mSet.erase( item );
+        return item;
+    };
+    void remove( X item )
+    {
+        if ( !is_in_list( item ) )
+            return;
+        mList.remove_all_with_value( item );
+        mSet.erase( item );
+    };
+
+    void clean_out( void )
+    {
+        mList.clean_out();
+        mSet.clear();
+    };
+
+    void list( DLIList<X> &list ) const
+    {
+        list = mList;
+    }
+    const DLIList<X> * list( void ) const
+    {
+        return &mList;
+    }
+
+    X & last( void ) const;
+    X & first( void ) const;
+};
+
+template <class X> inline
+X & OrderedSet<X>::last(void) const
+{
+    assert( mList.size() > 0 );
+    int index = mList.size()-1;
+    return mList[index];
+}
+
+template <class X> inline
+X & OrderedSet<X>::first(void) const
+{
+    assert( mList.size() > 0 );
+    return mList[0];
+}
+
+template <class X> inline
+X & OrderedSet<X>::operator[](int index) const
+{
+    return mList[index];
+}
+
+template <class X> inline
+OrderedSet<X>& OrderedSet<X>::operator=(const OrderedSet<X>& from)
+{
+    mList.clean_out();
+    mSet.clear();
+    int i;
+    int from_size = from.mList.size();
+    for ( i = 0; i < from_size; i++ )
+    {
+        force_insert( from.mList[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline 
+OrderedSet<X>& OrderedSet<X>::operator=(const DLIList<X>& list)
+{ 
+    mList.clean_out();
+    mSet.clear();
+    int i;
+    int list_size = list.size();
+    for ( i = 0; i < list_size; i++ )
+    {
+        this->insert( list[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline
+OrderedSet<X>& OrderedSet<X>::operator+=( X from )
+{
+    this->insert( from );
+    return *this;
+}
+
+template <class X> inline
+OrderedSet<X>& OrderedSet<X>::operator-=( X from )
+{
+    this->remove( from );
+    return *this;
+}
+
+template <class X> inline 
+OrderedSet<X>& OrderedSet<X>::operator+=(const DLIList<X>& list)
+{ 
+    int i;
+    for ( i = 0; i < list.size(); i++ )
+    {
+        this->insert( list[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline 
+OrderedSet<X>& OrderedSet<X>::operator+=(const OrderedSet<X>& list)
+{ 
+    int i;
+    for ( i = 0; i < list.size(); i++ )
+    {
+        this->insert( list[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline 
+OrderedSet<X>& OrderedSet<X>::operator-=(const DLIList<X>& list)
+{ 
+    int i;
+    for ( i = 0; i < list.size(); i++ )
+    {
+        this->remove( list[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline 
+OrderedSet<X>& OrderedSet<X>::operator-=(const OrderedSet<X>& list)
+{ 
+    int i;
+    for ( i = 0; i < list.size(); i++ )
+    {
+        this->remove( list[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline 
+OrderedSet<X>& OrderedSet<X>::operator-=(const OrderedSet<X> *list)
+{ 
+    int i;
+    for ( i = 0; i < list->size(); i++ )
+    {
+        this->remove( (*list)[i] );
+    }
+    return *this; 
+}
+
+template <class X> inline 
+OrderedSet<X> OrderedSet<X>::operator&( const OrderedSet<X> other_set ) const
+{
+    OrderedSet<X> tmp;
+    for ( int i = 0; i < other_set.size(); i++ )
+    {
+        if ( this->is_in_list( other_set[i] ) )
+        {
+            tmp.append( other_set[i] );
+        }
+    }
+    return tmp;
+}
+
+template <class X> inline 
+OrderedSet<X> OrderedSet<X>::operator|( const OrderedSet<X> other_set ) const
+{
+    OrderedSet<X> tmp = *this;
+    tmp += other_set;
+    return tmp;
+}
+
+#endif // OrderedSet_HPP

Modified: cgm/branches/cubit/util/OtherFiles/make.client
===================================================================
--- cgm/branches/cubit/util/OtherFiles/make.client	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/OtherFiles/make.client	2010-01-06 19:22:14 UTC (rev 3423)
@@ -68,7 +68,7 @@
 
 SHELL = /bin/sh
 
-CUBIT_VERSION = 10.2
+CUBIT_VERSION = 12.0b
 
 include ${CUBIT_BASE_DIR}/util/OtherFiles/cubiti.version
 

Modified: cgm/branches/cubit/util/ParamTool.hpp
===================================================================
--- cgm/branches/cubit/util/ParamTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ParamTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -29,10 +29,13 @@
     ParamTool() {}
     virtual ~ParamTool() {}
 
-    virtual CubitStatus transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location) = 0;
+    virtual CubitStatus transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location) = 0;
 
-    virtual CubitStatus transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location) = 0;
+    virtual CubitStatus transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location) = 0;
 
+	virtual CubitStatus uv_derivitives( double u_param, double v_param, 
+		CubitVector &du, CubitVector &dv ) {return CUBIT_FAILURE;}
+
 };
 
 #endif // PARAM_TOOL_HPP

Modified: cgm/branches/cubit/util/PlanarParamTool.cpp
===================================================================
--- cgm/branches/cubit/util/PlanarParamTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/PlanarParamTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -55,7 +55,7 @@
 // Author: chynes
 // Date: 7/10/02
 //===================================================================================
-CubitStatus PlanarParamTool::transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location) 
+CubitStatus PlanarParamTool::transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location) 
 {
   // Translate to local origin at center
 
@@ -65,7 +65,7 @@
 
   uv_location.x( vect % Du );
   uv_location.y( vect % Dv );
-  uv_location.z( 1.0 );
+  uv_location.z( 0.0 );
 
   return CUBIT_SUCCESS;
 }
@@ -76,7 +76,7 @@
 // Author: chynes
 // Date: 7/10/02
 //===================================================================================
-CubitStatus PlanarParamTool::transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location) 
+CubitStatus PlanarParamTool::transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location) 
 {
 // Multiply by transformation matrix
 
@@ -95,6 +95,12 @@
   return CUBIT_SUCCESS;
 }
 
+CubitStatus PlanarParamTool::uv_derivitives( double u_param, double v_param, 
+                        		                 CubitVector &du, CubitVector &dv )
+{
+  du = Du;
+  dv = Dv;
+  return CUBIT_SUCCESS;
+}
 
-
 //EOF

Modified: cgm/branches/cubit/util/PlanarParamTool.hpp
===================================================================
--- cgm/branches/cubit/util/PlanarParamTool.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/PlanarParamTool.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -29,10 +29,12 @@
 	
 	CubitStatus set_up_space(CubitVector& du, CubitVector& dv, CubitVector& uv_center);
 
-	CubitStatus transform_to_uv(CubitVector &xyz_location, CubitVector &uv_location);
+	CubitStatus transform_to_uv(const CubitVector &xyz_location, CubitVector &uv_location);
 
-	CubitStatus transform_to_xyz(CubitVector &xyz_location, CubitVector &uv_location);
+	CubitStatus transform_to_xyz(CubitVector &xyz_location, const CubitVector &uv_location);
 
+  virtual CubitStatus uv_derivitives( double u_param, double v_param, 
+		CubitVector &du, CubitVector &dv );
 
 private:
 	

Modified: cgm/branches/cubit/util/PriorityQueue.cpp
===================================================================
--- cgm/branches/cubit/util/PriorityQueue.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/PriorityQueue.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,4 +1,4 @@
-#include "assert.h"
+#include "cassert"
 #include "PriorityQueue.hpp"
 #include "CubitMessage.hpp"
 

Modified: cgm/branches/cubit/util/RTree.cpp
===================================================================
--- cgm/branches/cubit/util/RTree.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/RTree.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -292,5 +292,63 @@
   return CUBIT_FAILURE;
 }
 
-    
-    
+template <class Z> MY_INLINE
+CubitStatus RTree<Z>::find( const CubitVector &ray_origin, const CubitVector &ray_direction,
+      DLIList <Z> &range_members)
+{
+    //Find all of the members of the RTree that intersect this ray.
+  if ( myRoot == NULL )
+  {
+      // Nothing has been added to this Tree yet, so we are not going to find this
+      // object in it.
+      return CUBIT_SUCCESS;
+  }
+  CubitStatus stat = recursive_find(myRoot, ray_origin, ray_direction, range_members);
+  if ( stat != CUBIT_SUCCESS )
+    return CUBIT_FAILURE;
+  else
+    return CUBIT_SUCCESS;
+}
+
+template <class Z> MY_INLINE
+CubitStatus RTree<Z>::recursive_find(RTreeNode<Z> *rect_tree,
+                             const CubitVector &ray_origin,
+                             const CubitVector &ray_direction,
+                             DLIList <Z> &range_members)
+{
+  CubitBox rect_box = rect_tree->bounding_box();
+  //if ( !range_box.overlap(myTolerance, rect_box ) )
+  if ( !rect_box.intersect(&ray_origin, &ray_direction) )
+    return CUBIT_SUCCESS;
+
+    //Now see if this is a data member.  If it is, append the data to the
+    //list.
+  if (rect_tree->is_data() )
+  {
+    range_members.append(rect_tree->get_data());
+    return CUBIT_SUCCESS;
+  }
+    //Now if this is anything else we need to keep iterating...
+  int loop_size = rect_tree->num_children();
+    //We are doing a depth-first search of the tree.  Not
+    //all branches will need to be followed since they won't
+    //all overlap...
+  int ii;
+  RTreeNode<Z> *curr_node;
+  CubitStatus stat;
+  for ( ii = 0; ii < loop_size; ii++ )
+  {
+    curr_node = rect_tree->get_child(ii);
+    if ( curr_node == NULL )
+    {
+      PRINT_ERROR("Problems finding boxes in range.\n");
+      assert(curr_node != NULL);
+      return CUBIT_FAILURE;
+    }
+    stat = recursive_find(curr_node, ray_origin, ray_direction, range_members);
+    if ( stat != CUBIT_SUCCESS )
+      return stat;
+  }
+  
+  return CUBIT_SUCCESS;
+}

Modified: cgm/branches/cubit/util/RTree.hpp
===================================================================
--- cgm/branches/cubit/util/RTree.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/RTree.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -34,6 +34,13 @@
     //- recurses down the rtree to find all all the data members
     //- that fall in the range of the range_box.
 
+  CubitStatus recursive_find(RTreeNode<Z> *rect_tree,
+                             const CubitVector &ray_origin,
+                             const CubitVector &ray_direction,
+                             DLIList <Z> &range_members);
+    //- recurses down the rtree to find all all the data members
+    //- that fall in the range of the ray.
+
   void to_list(DLIList <RTreeNode<Z>*> &member_list,
                RTreeNode<Z> *top);
     //- converts the tree under top to a list.  Note, top is NOT in the list
@@ -69,6 +76,11 @@
     //- searches the range tree for members that intersect this range box
     //- within the tolerance.
 
+  CubitStatus find( const CubitVector &ray_origin, const CubitVector &ray_direction,
+      DLIList <Z> &range_members);
+    //- searches the range tree for members that intersect this ray
+    //- within the tolerance.
+
   CubitBoolean remove(Z data );
     //- Remove the data member's entry in the rectangle tree.
     //- Returns CUBIT_TRUE if item removed.  FALSE if item not

Modified: cgm/branches/cubit/util/RandomMersenne.cpp
===================================================================
--- cgm/branches/cubit/util/RandomMersenne.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/RandomMersenne.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -133,7 +133,7 @@
 
 #ifdef TEST_RANDOM
 
-#include <stdio.h>
+#include <cstdio>
 
 int main(void)
 {

Modified: cgm/branches/cubit/util/SDLList.cpp
===================================================================
--- cgm/branches/cubit/util/SDLList.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/SDLList.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -180,15 +180,12 @@
 
 // move_to_item_sorted finds the index of the given value, then sets the 
 // current index there
-int SDLList::move_to_item_sorted(void* value)
+CubitBoolean SDLList::move_to_item_sorted(void* value)
 {
   int item_index;
   CubitBoolean item_exists = where_is_item_sorted( value, item_index );
   index = item_index; // always
-  if ( item_exists ) {
-    return CUBIT_TRUE;
-  }
-  return CUBIT_FALSE;
+  return item_exists;
 }
 
 

Modified: cgm/branches/cubit/util/SDLList.hpp
===================================================================
--- cgm/branches/cubit/util/SDLList.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/SDLList.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -31,8 +31,8 @@
 #include "DLList.hpp"
 #include "CubitDefines.h"
 #include "CubitMessage.hpp"
-#include <string.h>
-#include <assert.h>
+#include <cstring>
+#include <cassert>
 #include "CubitUtilConfigure.h"
 
 const int ORDER_ASCENDING  = 0;
@@ -119,7 +119,7 @@
   //- (depending on the assignment of compare_order function pointer).  The
   //- list is sorted using a standard Heap Sort algorithm.
   
-  int move_to_item_sorted(void* value);
+  CubitBoolean move_to_item_sorted(void* value);
   //- move_to_item_sorted performs a binary search on the list to locate
   //- the item (object) that has functionType functionName() = value
   //- (see SSDLListdeclare macro for description of functionType and
@@ -318,7 +318,7 @@
     {                                                                        \
       return (typePtr) move_to_and_remove_item_sorted((void*) &value);       \
     }                                                                        \
-    int move_to(typePtr objPtr)                                              \
+    CubitBoolean move_to(typePtr objPtr)                                     \
     {                                                                        \
       if (nullItem && ((typePtr) nullItem == objPtr))                        \
         return CUBIT_FALSE;                                                  \
@@ -329,7 +329,7 @@
         return move_to_item_sorted((void*) &value);                          \
       }                                                                      \
     }                                                                        \
-    int move_to(functionType value)                                          \
+    CubitBoolean move_to(functionType value)                                 \
     {                                                                        \
       return move_to_item_sorted((void*) &value);                            \
     }                                                                        \

Modified: cgm/branches/cubit/util/SettingHandler.cpp
===================================================================
--- cgm/branches/cubit/util/SettingHandler.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/SettingHandler.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -2,9 +2,9 @@
 #pragma warning(disable : 4786)
 #endif
 
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
+#include <cassert>
+#include <cstdio>
+#include <cstring>
 
 #include <iostream>
 
@@ -57,7 +57,7 @@
   mSettingsList.clear();
 }
 
-void SettingHandler::add_setting(char* name, void (*setFn) (int), 
+void SettingHandler::add_setting(const char* name, void (*setFn) (int), 
 				int (*getFn)())
 {
   CubitString cs = name;
@@ -72,7 +72,7 @@
 }
 
 
-void SettingHandler::add_setting(char* name, void (*setFn) (double), 
+void SettingHandler::add_setting(const char* name, void (*setFn) (double), 
 				double (*getFn)())
 {
   CubitString cs = name;
@@ -88,7 +88,7 @@
 }
 
 
-void SettingHandler::add_setting(char* name, void (*setFn) (CubitBoolean), 
+void SettingHandler::add_setting(const char* name, void (*setFn) (CubitBoolean), 
 				CubitBoolean (*getFn)())
 {
    CubitString cs = name;
@@ -104,7 +104,7 @@
 }
 
 
-void SettingHandler::add_setting(char* name, void (*setFn) (CubitString), 
+void SettingHandler::add_setting(const char* name, void (*setFn) (CubitString), 
 				CubitString (*getFn)())
 {
    CubitString cs = name;
@@ -219,7 +219,7 @@
 void SettingHandler::save_settings()
 {
   
-  char* default_filename = "cubit.settings";
+  const char* default_filename = "cubit.settings";
 
   FILE* file = fopen(default_filename, "w");
   
@@ -374,10 +374,19 @@
 	return (*(mSettingsList.find(name))).second;
 }
 
-void SettingHandler::get_settings_list(std::map<CubitString, SettingHolder*> &list)
+void SettingHandler::get_settings_list(std::vector< std::pair<CubitString, SettingHolder*> > &list)
 {
-  // return a copy of the settings list
-  list = mSettingsList;
+  // return a list of the settings
+  std::map<CubitString, SettingHolder*>::iterator iter = mSettingsList.begin();
+  while(iter != mSettingsList.end())
+  {
+    std::pair<CubitString, SettingHolder*>  tmp_pair;
+    CubitString key = (*iter).first;
+    tmp_pair.first = key;
+    tmp_pair.second = (*iter).second;
+    list.push_back( (tmp_pair) );
+    iter++;
+  }
 }
 
 

Modified: cgm/branches/cubit/util/SettingHandler.hpp
===================================================================
--- cgm/branches/cubit/util/SettingHandler.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/SettingHandler.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -11,6 +11,7 @@
 #include "CubitDefines.h"
 #include "SettingHolder.hpp"
 #include <map>
+#include <vector>
 #include "CubitUtilConfigure.h"
 
 
@@ -23,15 +24,15 @@
 
   static void delete_instance(); //deletes instance if it exists 
 
-  void add_setting(char* name, void (*setFn) (int), int (*getFn)());
-  void add_setting(char* name, void (*setFn) (double), double (*getFn)());
-  void add_setting(char* name, void (*setFn) (CubitBoolean), CubitBoolean (*getFn)());
-  void add_setting(char* name, void (*setFn) (CubitString), CubitString (*getFn)());
+  void add_setting(const char* name, void (*setFn) (int), int (*getFn)());
+  void add_setting(const char* name, void (*setFn) (double), double (*getFn)());
+  void add_setting(const char* name, void (*setFn) (CubitBoolean), CubitBoolean (*getFn)());
+  void add_setting(const char* name, void (*setFn) (CubitString), CubitString (*getFn)());
 
 #ifdef BOYD15
   int num_settings();
 #endif
-  void get_settings_list(std::map<CubitString, SettingHolder*> &list);
+  void get_settings_list( std::vector< std::pair<CubitString, SettingHolder*> > &list);
 
   void print_settings(); // Output all settings using PRINT_INFO
   void save_settings(const char *filename); //Save settings into a file specified by the user

Modified: cgm/branches/cubit/util/TextProgressTool.cpp
===================================================================
--- cgm/branches/cubit/util/TextProgressTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/TextProgressTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,4 +1,4 @@
-//#include "string.h"
+//#include "cstring"
 #include "TextProgressTool.hpp"
 #include "CubitMessage.hpp"
 

Modified: cgm/branches/cubit/util/ToolData.cpp
===================================================================
--- cgm/branches/cubit/util/ToolData.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ToolData.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -10,4 +10,12 @@
 // functions aren't inlined in a lot of cases where their address is
 // taken.
 
+ToolData* ToolData::propogate(ToolDataUser* new_td_user)
+{
+  return NULL;
+}
 
+ToolData* ToolData::merge(ToolDataUser* other_td_user)
+{
+  return NULL;
+}

Modified: cgm/branches/cubit/util/ToolData.hpp
===================================================================
--- cgm/branches/cubit/util/ToolData.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ToolData.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -11,8 +11,10 @@
 
 #include "CubitDefines.h"
 #include "CubitUtilConfigure.h"
-#include <assert.h>
+#include <cassert>
 
+class ToolDataUser;
+
 class CUBIT_UTIL_EXPORT ToolData
 {
   private:
@@ -37,6 +39,19 @@
     //- access to next tooldata in chain
   
     // handy for ToolDataUser::delete_TD, see e.g. DoubletPillower.cc
+
+        
+    virtual ToolData* propogate(ToolDataUser* new_td_user);
+    //- propogate() receives the ToolData User that has been copied or split off from the 
+    //- ToolDataUser this TD is on and returns the ToolData that should be put on the new 
+    //- ToolDataUser.  If no new TD should be created, it returns NULL.
+
+    virtual ToolData* merge(ToolDataUser* other_td_user);
+    //- merge() receives a ToolDataUser that is about to be merged with the ToolDataUser that this
+    //- TD is on.  It should process what should happen to this and any similar tooldata on the
+    //- other ToolDataUser and return the TD that should be assigned to the merged entity.
+    //- Note: ToolDataUser deletes any TD that is on it when itself is deleted.  The calling function
+    //- should probably remove any TD returned by this function from the entities before deleting them.
   
 };
 // ********** BEGIN INLINE FUNCTIONS       **********

Modified: cgm/branches/cubit/util/ToolDataUser.cpp
===================================================================
--- cgm/branches/cubit/util/ToolDataUser.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ToolDataUser.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -1,6 +1,6 @@
 // Class: ToolDataUser
 
-#include <assert.h>
+#include <cassert>
 #include "ToolDataUser.hpp"
 #include "ToolData.hpp"
 #include "DLIList.hpp"
@@ -106,6 +106,15 @@
   }  
 }
 
+void ToolDataUser::get_all_TDs(DLIList <ToolData *> *all_tds) const
+{
+  ToolData *td = tool_data();
+  while (td) 
+  {
+    all_tds->append(td);
+    td = td->next_tool_data();
+  }  
+}
 
 ToolDataUser::~ToolDataUser()
 {

Modified: cgm/branches/cubit/util/ToolDataUser.hpp
===================================================================
--- cgm/branches/cubit/util/ToolDataUser.hpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/ToolDataUser.hpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -44,29 +44,31 @@
   virtual ~ToolDataUser();
   //- automatically deletes all the chained ToolDatas
   
-  CubitBoolean delete_TD(IdentityFn specified_type);
+  virtual CubitBoolean delete_TD(IdentityFn specified_type);
   //- delete the specific type of tool data from the chain.
   //- return true if something was actually found and deleted.
 
-  CubitBoolean delete_TD(ToolData *td);
+  virtual CubitBoolean delete_TD(ToolData *td);
   //- delete the specific tool data from the chain.
   //- return true if something was actually found and deleted.
   
-  ToolData *remove_TD(IdentityFn specified_type);
+  virtual ToolData *remove_TD(IdentityFn specified_type);
   //- remove the specific type of tool data from the chain, and
   //- return it.
 
-  ToolData *remove_TD(ToolData *td);
+  virtual ToolData *remove_TD(ToolData *td);
   //- remove the specific tool data from the chain, and
   //- return it.
   
-  void add_TD(ToolData *new_td);
+  virtual void add_TD(ToolData *new_td);
   //- add the new_td to the beginning of the tool_data chain
   
   virtual ToolData *get_TD(IdentityFn specified_type);
   virtual ToolData const *get_TD(IdentityFn specified_type) const;
   virtual void get_all_TDs(IdentityFn specified_type, 
                            DLIList <ToolData *> *all_tds) const;
+  
+  virtual void get_all_TDs(DLIList <ToolData *> *all_tds) const;
   //- get the specific type of ToolData in the chain.
   //- returns null if not found.
   

Modified: cgm/branches/cubit/util/TtyProgressTool.cpp
===================================================================
--- cgm/branches/cubit/util/TtyProgressTool.cpp	2009-12-22 20:36:06 UTC (rev 3422)
+++ cgm/branches/cubit/util/TtyProgressTool.cpp	2010-01-06 19:22:14 UTC (rev 3423)
@@ -12,7 +12,7 @@
 #ifndef NT
 #  include <unistd.h>
 #endif
-#include <string.h>
+#include <cstring>
 #include "AppUtil.hpp"
 #include "TtyProgressTool.hpp"
 #include "CubitUtil.hpp"



More information about the cgma-dev mailing list