Index: /cgm/README.CGM
===================================================================
--- /cgm/README.CGM (revision 1040)
+++ /cgm/README.CGM (revision 1040)
@@ -0,0 +1,94 @@
+=====================================
+The Common Geometry Module (CGM)
+Read Me
+
+Version 10.0
+=====================================
+
+The Common Geometry Module (CGM) is a code library which provides
+geometry functionality used for mesh generation and other
+applications.  This functionality includes that commonly found in
+solid modeling engines, like geometry creation, query and
+modification; CGM also includes capabilities not commonly found in
+solid modeling engines, like geometry decomposition tools and support
+for shared material interfaces.  CGM is built upon the ACIS solid
+modeling engine, but also includes geometry capability developed
+beside and on top of ACIS.  CGM can be used as-is to provide geometry
+functionality for codes needing this capability.  However, CGM can
+also be extended using derived classes in C++, allowing the geometric
+model to serve as the basis for other applications, for example mesh
+generation.  CGM is supported on Sun Solaris, SGI, HP, Linux
+and Windows NT platforms.  CGM also includes support for loading ACIS
+models on parallel computers, using MPI-based communication.  Future
+plans for CGM are to port it to different solid modeling engines,
+including Pro/Engineer or SolidWorks.  CGM is being released into the
+public domain under an LGPL license; the ACIS-based engine is
+available to ACIS licensees on request.  
+
+=====================================
+Dependencies
+=====================================
+
+CGM can be built using the CMake utility, which is "an extensible,
+open-source system that manages the build process in an operating
+system and compiler independent manner", or (on *NIX) using a
+configure-make system.  Cmake is available under an open source
+license, and can be downloaded in binary or source formats; see
+http://www.cmake.org for details.
+
+CGM can be built without using any external solid modeling engines; in
+this form, facet-based geometry can be constructed, queried and
+modified.  Specific engines relying on third-party, commercial
+modelers are also available, to those licensed to use those modelers.
+Contact the CUBIT team at cubit-dev_at_sandia.gov for details and to
+obtain source code for these engines.
+
+=====================================
+Compiling
+=====================================
+
+1. Unpack the source code in some directory CGM_DIR, and change
+directory into CGM_DIR.
+2a. Run cmake in that directory, using either the non-interactive
+("cmake .") or interactive ("ccmake .") version, OR
+2b. Run "./configure" in that directory, optionally specifying where
+ACIS libraries are located and other options (run "./configure -h" for
+a list of options).
+3. Make the CGM libraries by typing "make".
+4. Install the CGM libraries by typing "make install" (this installs
+the libraries to the location specified by the --prefix option to
+configure, or to /usr/local by default).
+5. Test the installation using "make test".
+
+=====================================
+Documentation, Testing, Example Applications
+=====================================
+
+Documentation for CGM is available from the CGM web page,
+http://cubit.sandia.gov/CGM.
+
+Example applications are included with the CGM distribution in the
+cgm_apps subdirectory.  Examples include importing and querying solid
+model-based geometry, and constructing facet-based geometry.  If you
+are interested in contributing examples to be included with CGM, we
+would welcome submissions; please send them to the email address
+below.
+
+The best example for how to build applications is to look in the
+cgm_apps/examples/facetdriver (without ACIS) and
+cgm_apps/examples/driverc++ (with ACIS) subdirectories.
+
+=====================================
+Bugs, Correspondence, Contributing
+=====================================
+
+CGM is LGPL code, and we encourage users to submit bug reports (and,
+if desired, fixes) to cubit-dev_at_sandia.gov.  Users are encouraged to check
+http://cubit.sandia.gov/CGM often for news and updates.
+
+=====================================
+Updates
+=====================================
+
+10.0 (4/05): Initial public CGM release
+
Index: /cgm/configure.in
===================================================================
--- /cgm/configure.in (revision 1040)
+++ /cgm/configure.in (revision 1040)
@@ -0,0 +1,124 @@
+################################################################################
+#                           Standard Stuff
+################################################################################
+AC_INIT(CGM, 10.0b)
+AC_CONFIG_AUX_DIR(./config_aux)
+AC_CANONICAL_SYSTEM
+AM_INIT_AUTOMAKE(CGM,10.0b)
+AC_DISABLE_SHARED
+
+SNL_CHECK_COMPILERS
+AM_CONDITIONAL(build_parallel, [test "x$WITH_MPI" != "xno"])
+AC_PROG_LIBTOOL
+LIBS="-lm"
+AC_PROG_LIBTOOL
+AC_C_BIGENDIAN( [LITTLE_ENDIAN=], [LITTLE_ENDIAN="-DLITTLE_ENDIAN=BYTE_ORDER"] )
+AC_SUBST(LITTLE_ENDIAN)
+
+
+
+################################################################################
+#                              MPI OPTIONS
+################################################################################
+
+if test "x$WITH_MPI" != "xno"; then
+  CXXFLAGS="$CXXFLAGS -DUSE_MPI"
+  CGM_PARALLEL_INCLUDE='-I${CGM_DIR}/geom/parallel'
+  CGM_PARALLEL_LIB='-L${CGM_DIR}/geom/parallel -lcubit_parallel'
+  CGM_PARALLEL_LIB_FILE='${CGM_LIBDIR}/libcubit_parallel.a'
+fi
+AM_CONDITIONAL(USE_MPI, [test "xno" != "x$WITH_MPI"])
+AC_SUBST(CGM_PARALLEL_INCLUDE)
+AC_SUBST(CGM_PARALLEL_LIB)
+AC_SUBST(CGM_PARALLEL_LIB_FILE)
+
+################################################################################
+#                           CGM-specific Checks
+################################################################################
+
+SNL_CANT_USE_STD
+SNL_TEMPLATE_DEFS_INCLUDED
+AC_SUBST(CANT_USE_STD)
+AC_SUBST(CANT_USE_STD_IO)
+AC_SUBST(TEMPLATE_DEFS_INCLUDED)
+AM_CONDITIONAL(INCLUDE_TEMPLATE_DEFS, test x$TEMPLATE_DEFS_INCLUDED != x)
+
+
+
+################################################################################
+#                           ACIS OPTIONS
+################################################################################
+ACIS_BASE_LIBS='-lSpaAVis -lSpaAWarp -lSpaASurf -lSpaALops -lSpaABlend -lSpaACIS -lSpaBase'
+ACIS_STEP_LIBS='-lacisstep -lxstep'
+ACIS_IGES_LIBS='-lacisiges -lxiges'
+CGM_ACIS_LIBS='-lcubit_ACIS'
+
+AC_ARG_WITH( ACIS, 
+             AC_HELP_STRING([--with-ACIS=DIR],[Build with ACIS support, specify directory where ACIS is installed.]),
+             [ACIS_DIR=$withval],[ACIS_DIR=no] )
+AC_ARG_WITH( ACIS-system, AC_HELP_STRING([--with-ACIS-system=SYS], 
+          [Specify ACIS system name (e.g. linux_so), default is to autodetect.]),
+             [ACIS_SYSTEM=$withval],[ACIS_SYSTEM=] )
+AC_ARG_WITH( ACIS-version, AC_HELP_STRING([--with-ACIS-version=INT],
+[Specify ACIS version as an integer value (100*major+10*minor+point), default is to autodetect.]),
+[if ! test "$withval" -gt "600"; then
+  AC_MSG_ERROR("ACIS-version must be an integer greater than 600.")
+ fi
+ ACIS_VERSION=$withval],
+[ACIS_VERSION=0])
+if test "x$ACIS_DIR" == "x"; then 
+  ACIS_DIR=no; 
+fi          
+if test "$ACIS_DIR" == "no"; then
+  ACIS_LIB_DIR=".";
+fi
+if test "$ACIS_DIR" != "no"; then
+  if test "$ACIS_DIR" == "yes"; then ACIS_DIR=.; fi
+  SNL_ACIS_ENV
+  
+  SNL_ACIS_TRANSLATOR
+  if test x$ACIS_STEP_TRANSLATOR != x; then
+    ACIS_LIBS="$ACIS_LIBS $ACIS_STEP_LIBS"
+    ACIS_XLIBS="$ACIS_XLATE_LIBS"
+  fi
+  if test x$ACIS_IGES_TRANSLATOR != x; then
+    ACIS_LIBS="$ACIS_LIBS $ACIS_IGES_LIBS"
+    ACIS_XLIBS="$ACIS_XLATE_LIBS"
+  fi
+  ACIS_LIBS="$CGM_ACIS_LIBS $ACIS_LIBS $ACIS_XLIBS $ACIS_BASE_LIBS"
+  ACIS_HEALER="-DACIS_HEALER"
+  ACIS_INCLUDES="-I$ACIS_DIR/include"
+  ACIS_DEFS='$(ACIS_STEP_TRANSLATOR) $(ACIS_IGES_TRANSLATOR) -DCUBIT_ACIS_VERSION=$(ACIS_VERSION) -DACIS_VERSION=$(ACIS_VERSION) -D$(ACIS_PLATFORM) -DACIS_LOCAL_OPS'
+fi
+AC_SUBST(ACIS_DEFS)
+AC_SUBST(ACIS_DIR)
+AC_SUBST(ACIS_LIB_DIR)
+AC_SUBST(ACIS_INCLUDES)
+AC_SUBST(ACIS_LIBS)
+AC_SUBST(ACIS_HEALER)
+AC_SUBST(ACIS_VERSION)
+AC_SUBST(ACIS_PLATFORM)
+AC_SUBST(ACIS_STEP_TRANSLATOR)
+AC_SUBST(ACIS_IGES_TRANSLATOR)
+AM_CONDITIONAL(build_ACIS, test x$ACIS_DIR != xno)
+
+
+
+################################################################################
+#                           Output Files
+################################################################################
+AC_MSG_RESULT([CXXFLAGS = $CXXFLAGS])
+AC_OUTPUT_COMMANDS( [if test -f util/CubitUtilConfigure.h; then true; else echo "#define CUBIT_UTIL_EXPORT" > util/CubitUtilConfigure.h; fi],
+                    [if test -f geom/CubitGeomConfigure.h; then true; else echo "#define CUBIT_GEOM_EXPORT" > geom/CubitGeomConfigure.h; fi] )
+AC_CONFIG_FILES(Makefile 
+           util/Makefile
+           geom/Makefile
+           geom/ACIS/Makefile
+           geom/Cholla/Makefile
+           geom/facet/Makefile
+           geom/facetbool/Makefile
+           geom/parallel/Makefile
+           geom/virtual/Makefile 
+           cgm.make)
+
+AC_OUTPUT
Index: /cgm/LICENSE.CGM
===================================================================
--- /cgm/LICENSE.CGM (revision 1040)
+++ /cgm/LICENSE.CGM (revision 1040)
@@ -0,0 +1,21 @@
+CGM, the Common Geometry Module, is a code library which provides
+geometry functionality used for mesh generation and other applications.
+
+Copyright 2005 Sandia Corporation.  Under the terms of Contract
+DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
+retains certain rights in this software.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.  A copy of the full
+GNU Lesser General Public License can be found at
+http://www.gnu.org/copyleft/lesser.html.
+
+For more information, contact the authors of this software at
+cubit-dev@sandia.gov.
Index: /cgm/acsite.m4
===================================================================
--- /cgm/acsite.m4 (revision 1040)
+++ /cgm/acsite.m4 (revision 1040)
@@ -0,0 +1,881 @@
+#######################################################################################
+# Implement checks for C and C++ compilers, with all corresponding options
+#
+# Sets the following variables:
+#  CPP      - The C preprocessor
+#  CC       - The C compiler
+#  CXX      - The C++ compiler
+#  CFLAGS   - C compiler flags
+#  CXXFLAGS - C++ compiler flags
+#  WITH_MPI - 'yes' if parallel support, 'no' otherwise
+#
+#######################################################################################
+AC_DEFUN([SNL_CHECK_COMPILERS], [
+
+  # Save these before calling AC_PROG_CC or AC_PROG_CXX
+  # because those macros will modify them, and we want
+  # the original user values, not the autoconf defaults.
+USER_CXXFLAGS="$CXXFLAGS"
+USER_CCFLAGS="$CFLAGS"
+
+  # Check for Parallel
+  # Need to check this early so we can look for the correct compiler
+AC_ARG_WITH( [mpi], AC_HELP_STRING([[--with-mpi(=DIR)]], [Enable parallel support]),
+             [WITH_MPI=$withval],[WITH_MPI=no] )
+case "x$WITH_MPI" in
+  xno)
+    CC_LIST="cc gcc cl egcs"
+    CXX_LIST="CC aCC cxx xlC_r xlC pgCC c++ g++ gpp cc++ cl FCC KCC RCC"
+    ;;
+  xyes)
+    CC_LIST="mpicc mpcc"
+    CXX_LIST="mpiCC mpCC mpicxx"
+    ;;
+  x*)
+    if test -z "$CC";then
+      for prog in mpicc mpcc; do
+        if test -x ${WITH_MPI}/bin/$prog; then
+          CC="${WITH_MPI}/bin/$prog"
+          CC_LIST="$prog"
+        fi
+      done
+    else
+      CC_LIST="$CC"
+    fi
+    if test -z "$CXX";then
+      for prog in mpicxx mpiCC mpCC; do
+        if test -x ${WITH_MPI}/bin/$prog; then
+          CXX="${WITH_MPI}/bin/$prog"
+          CXX_LIST="$prog"
+        fi
+      done
+    else
+      CXX_LIST="$CXX"
+    fi
+    WITH_MPI=yes
+    ;;
+esac
+AC_PROG_CC( [$CC_LIST] )
+AC_PROG_CPP
+AC_PROG_CXX( [$CXX_LIST] )
+AC_PROG_CXXCPP
+
+# Try to determine compiler-specific flags.  This must be done
+# before setting up libtool so that it can override libtool settings.
+SNL_CC_FLAGS
+SNL_CXX_FLAGS
+CFLAGS="$USER_CFLAGS $SNL_CC_SPECIAL"
+CXXFLAGS="$USER_CXXFLAGS $SNL_CXX_SPECIAL"
+
+# On IBM/AIX, the check for OBJEXT fails for the mpcc compiler.
+# (Comment out this hack, it should be fixed correctly now)
+#if test "x$OBJEXT" = "x"; then
+#  OBJEXT=o
+#fi
+
+  # Check for debug flags
+AC_ARG_ENABLE( debug, AC_HELP_STRING([--enable-debug],[Debug symbols (-g)]),
+               [enable_debug=$enableval], [enable_debug=] )  
+AC_ARG_ENABLE( optimize, AC_HELP_STRING([--enable-optimize],[Compile optimized (-O2)]),
+               [enable_cxx_optimize=$enableval
+                enable_cc_optimize=$enableval], 
+               [enable_cxx_optimize=
+                enable_cc_optimize=] )
+
+# Do enable_optimize by default, unless user has specified
+# custom CXXFLAGS or CFLAGS
+if test "x$enable_debug" = "x"; then
+  if test "x$enable_cxx_optimize" = "x"; then
+    if test "x$USER_CXXFLAGS" = "x"; then
+      enable_cxx_optimize=yes
+    fi
+  fi
+  if test "x$enable_cc_optimize" = "x"; then
+    if test "x$USER_CFLAGS" = "x"; then
+      enable_cc_optimize=yes
+    fi
+  fi
+fi
+
+# Choose compiler flags from CLI args
+if test "xyes" = "x$enable_debug"; then
+  CXXFLAGS="$CXXFLAGS -g"
+  CFLAGS="$CLFAGS -g"
+fi
+if test "xyes" = "x$enable_cxx_optimize"; then
+  CXXFLAGS="$CXXFLAGS -O2 -DNDEBUG"
+fi
+if test "xyes" = "x$enable_cc_optimize"; then
+  CFLAGS="$CFLAGS -O2 -DNDEBUG"
+fi
+
+  # Check for 32/64 bit.
+  # This requires SNL_CXX_FLAGS and SNL_CC_FLAGS to have been called first
+AC_ARG_ENABLE( 32bit, AC_HELP_STRING([--enable-32bit],[Force 32-bit objects]),
+[
+  if test "xyes" != "x$enableval"; then
+    AC_MSG_ERROR([Unknown argument --enable-32bit=$enableval])
+  elif test "x" = "x$SNL_CXX_32BIT"; then
+    AC_MSG_ERROR([Don't know how to force 32-bit C++ on this platform.  Try setting CXXFLAGS manually])
+  elif test "x" = "x$SNL_CC_32BIT"; then
+    AC_MSG_ERROR([Don't know how to force 32-bit C on this platform.  Try setting CFLAGS manually])
+  fi
+  CXXFLAGS="$CXXFLAGS $SNL_CXX_32BIT"
+  CFLAGS="$CFLAGS $SNL_CC_32BIT"
+  enable_32bit=yes
+])
+# This requires SNL_CXX_FLAGS and SNL_CC_FLAGS to have been called first
+AC_ARG_ENABLE( 64bit, AC_HELP_STRING([--enable-64bit],[Force 64-bit objects]),
+[
+  if test "xyes" != "x$enableval"; then
+    AC_MSG_ERROR([Unknown argument --enable-64bit=$enableval])
+  elif test "x" = "x$SNL_CXX_64BIT"; then
+    AC_MSG_ERROR([Don't know how to force 64-bit C++ on this platform.  Try setting CXXFLAGS manually])
+  elif test "x" = "x$SNL_CC_64BIT"; then
+    AC_MSG_ERROR([Don't know how to force 64-bit C on this platform.  Try setting CFLAGS manually])
+  elif test "xyes" = "x$enable_32bit"; then
+    AC_MSG_ERROR([Cannot do both --enable-32bit and --enable-64bit])
+  fi
+  CXXFLAGS="$CXXFLAGS $SNL_CXX_64BIT"
+  CFLAGS="$CFLAGS $SNL_CC_64BIT"
+])
+
+]) # SNL_CHECK_COMPILERS
+
+
+
+#######################################################################################
+# Extract the value of a variable from a makefile fragment.
+# Arguments:
+#   - The path of the makefile fragment
+#   - The name of the makefile variable
+#   - Action on success (the shell variable "make_val" will contain the value
+#         of the variable)
+#   - Action on failure
+#######################################################################################
+AC_DEFUN([SNL_MAKE_INC_VAR], [
+make_val=
+snl_makefile="snl_check.mak"
+rm -f $snl_makefile
+
+if test ! -f $1 ; then
+  AC_MSG_WARN([File not found: $1])
+  $4
+else
+cat >$snl_makefile <<SNL_END_OF_MAKEFILE
+default:
+	@echo "\$($2)"
+
+include $1
+SNL_END_OF_MAKEFILE
+if make -f $snl_makefile > /dev/null 2>&1; then
+  make_val=`make -f $snl_makefile`
+  rm -f $snl_makefile
+  $3
+else
+  rm -f $snl_makefile
+  $4
+fi
+fi
+])
+
+
+#######################################################################################
+# Check for existance of new no-file-extension C++ headers.
+# Conditinionally sets the following preprocessor macros:
+#   CANT_USE_STD
+#    - The new no-extension versions of the c++ headers do not
+#      exist or do not define symbols to be in the "std" namespace.
+#      For example: if this is defined #include <map.h> rather than <map>.
+#   CANT_USE_STD_IO
+#    - The new no-extension versions of the c++ IO headers do not
+#      exist or do not define symbols to be in the "std" namespace.
+#      For example: if this is defined, #include <iostrea.h> rather than <iostream>
+#######################################################################################
+AC_DEFUN([SNL_CANT_USE_STD], [
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+
+AC_MSG_CHECKING([for C++-standard header files])
+AC_TRY_COMPILE([#include <vector>
+                #include <string>
+                #include <map>
+                #include <algorithm>
+               ],
+               [std::vector<std::string> v;
+                std::map<std::string,std::string> m;
+               ],
+               [AC_MSG_RESULT(yes)],
+               [AC_MSG_RESULT(no); CANT_USE_STD=-DCANT_USE_STD])
+
+AC_MSG_CHECKING([for C++-standard I/O header files])
+AC_TRY_COMPILE([#include <iosfwd>
+                #include <iostream>
+                #include <ostream>
+                #include <sstream>
+               ],
+               [std::cout << std::endl;],
+               [AC_MSG_RESULT(yes)],
+               [AC_MSG_RESULT(no); CANT_USE_STD_IO=-DCANT_USE_STD_IO])
+
+AC_LANG_RESTORE
+]) # SNL_CANT_USE_STD
+
+
+
+
+#######################################################################################
+# Check if template definitions (.cpp files) must be
+# included (in the .hpp files).
+# Sets TEMPLATE_DEFS_INCLUDED=1
+#######################################################################################
+AC_DEFUN([SNL_TEMPLATE_DEFS_INCLUDED], [
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+
+AC_MSG_CHECKING([if template definitions should be included])
+
+src=conftest.cc
+templ=conftemp.cc
+exe=conftest
+
+echo "template <typename T> class MyTempl { public: T get() const; };" >$templ
+echo "template <typename T> T MyTempl<T>::get() const { return 0; }"  >>$templ
+echo "template <typename T> class MyTempl { public: T get() const; };" >$src
+echo "int main( ) { MyTempl<int> c; return c.get(); }"                >>$src
+if $CXX $CXXFLAGS $LDFLAGS $src $templ -o $exe >/dev/null 2>/dev/null; then
+  TEMPLATE_DEFS_INCLUDED=
+  AC_MSG_RESULT(no)
+else
+  TEMPLATE_DEFS_INCLUDED=-DTEMPLATE_DEFS_INCLUDED
+  AC_MSG_RESULT(yes)
+fi
+
+rm -f $src $templ $exe
+AC_LANG_RESTORE
+]) # SNL_TEMPLATE_DEFS_INCLUDED
+
+
+
+
+#######################################################################################
+# Check for HDF5 library and related stuff
+# Sets HAVE_HDF5 to 'yes' or 'no'
+# If HAVE_HDF5 == yes, then updates INCLUDES and LIBS accordingly.
+#######################################################################################
+AC_DEFUN([SNL_CHECK_HDF5],[
+
+  # CLI option for linking zlib
+AC_ARG_WITH(zlib,
+  [AC_HELP_STRING([--with-zlib=DIR],[HDF5 requires zlib, and zlib can be found at...])],
+  [WITH_ZLIB=$withval],[WITH_ZLIB=])
+case "x$WITH_ZLIB" in
+  xyes|xno|x)
+    ;;
+  *)
+    if ! test -d  ${WITH_ZLIB}/lib; then
+      AC_MSG_ERROR([Not a directory: ${WITH_ZLIB}/lib])
+    fi
+    LIBS="$LIBS -L${WITH_ZLIB}/lib"
+    ;;
+esac
+HAVE_ZLIB=no
+if test "x$WITH_ZLIB" != "xno"; then
+  AC_CHECK_LIB([z],[deflate],[HAVE_ZLIB=yes],
+    [if test "x$WITH_ZLIB" != "x"; then AC_MSG_ERROR([Could not find zlib]); fi])
+fi
+
+  # CLI option for linking szip
+AC_ARG_WITH(szip,
+  [AC_HELP_STRING([--with-szip=DIR],[HDF5 requires szip, and szip an be found at...])],
+  [WITH_SZIP=$withval],[WITH_SZIP=])
+case "x$WITH_SZIP" in
+  xyes|xno|x)
+    ;;
+  *)
+    if ! test -d  ${WITH_SZIP}/lib; then
+      AC_MSG_ERROR([Not a directory: ${WITH_SZIP}/lib])
+    fi
+    LIBS="$LIBS -L${WITH_SZIP}/lib"
+    ;;
+esac
+HAVE_SZIP=no
+if test "x$WITH_SZIP" != "xno"; then
+  AC_CHECK_LIB([sz],[SZ_Decompress],[HAVE_SZIP=yes],
+    [if test "x$WITH_SZIP" != "x"; then AC_MSG_ERROR([Could not find libsz]); fi])
+fi
+
+  # CLI option for extra HDF5 link flags
+AC_ARG_WITH([--with-hdf5-ldflags],[AC_HELP_STRING([--with-hdf5-ldflags=...],
+ [Extra LDFLAGS required for HDF5 library (e.g. parallel IO lib)])],
+ [HDF5_LDFLAGS="$withval"],[HDF5_LDFLAGS=])
+case "x$HDF5_LDFLAGS" in
+  xno)
+    AC_MSG_ERROR("Invalid argument: --without-hdf5-ldflags")
+    ;;
+  xyes)
+    AC_MSG_ERROR("Nonsensical argument:  --with-hdf5-ldflags without any specified flags")
+    ;;
+esac
+
+
+  # CLI option for HDF5
+AC_MSG_CHECKING([if HDF5 support is enabled])
+AC_ARG_WITH(hdf5, 
+[AC_HELP_STRING([--with-hdf5=DIR], [Specify HDF5 library to use for native file format])
+AC_HELP_STRING([--without-hdf5], [Disable support for native HDF5 file format])],
+[HDF5_ARG=$withval], [HDF5_ARG=yes])
+if test "xno" = "x$HDF5_ARG"; then
+  AC_MSG_RESULT([no])
+else
+  AC_MSG_RESULT([yes])
+fi
+
+ # if HDF5 support is not disabled, check to make sure we have HDF5
+if test "xno" != "x$HDF5_ARG"; then
+    # Check for IBM parallel IO library
+  if test "x$WITH_MPI" != "xno"; then
+    AC_CHECK_LIB([gpfs],[gpfs_stat],[LIBS="-lgpfs $LIBS"])
+  fi
+
+    # Add flag to defines
+  LIBS="$HDF5_LDFLAGS $LIBS"
+
+    # if a path is specified, update LIBS and INCLUDES accordingly
+  if test "xyes" != "x$HDF5_ARG"; then
+    if test -d "${HDF5_ARG}/lib"; then
+      LIBS="$LIBS -L${HDF5_ARG}/lib"
+    elif test -d "${HDF5_ARG}"; then
+      LIBS="$LIBS -L${HDF5_ARG}"
+    else
+      AC_MSG_ERROR("$HDF5_ARG is not a directory.")
+    fi
+    if test -d "${HDF5_ARG}/include"; then
+      INCLUDES="$INCLUDES -I${HDF5_ARG}/include"
+    else
+      INCLUDES="$INCLUDES -I${HDF5_ARG}"
+    fi
+  fi
+  
+    # check for libraries and headers
+  old_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $INCLUDES"
+  AC_CHECK_HEADERS( [hdf5.h], [], [AC_MSG_ERROR("HDF5 header not found")] )
+  CPPFLAGS="$old_CPPFLAGSS"
+  
+  HAVE_LIB_HDF5=no
+  AC_CHECK_LIB( [hdf5], [H5Fopen], [HAVE_LIB_HDF5=yes] )
+  if test $HAVE_LIB_HDF5 = no; then
+    if test $HAVE_ZLIB = yes; then
+      unset ac_cv_lib_hdf5_H5Fopen
+      AC_CHECK_LIB( [hdf5], [H5Fopen], [HAVE_LIB_HDF5=yes; LIBS="-lz $LIBS"], [], [-lz] )
+    fi
+  fi
+  if test $HAVE_LIB_HDF5 = no; then
+    if test $HAVE_SZIP = yes; then
+      unset ac_cv_lib_hdf5_H5Fopen
+      AC_CHECK_LIB( [hdf5], [H5Fopen], [HAVE_LIB_HDF5=yes; LIBS="-lsz $LIBS"], [], [-lsz] )
+    fi
+  fi
+  if test $HAVE_LIB_HDF5 = no; then
+    if test $HAVE_SZIP = yes; then
+      if test $HAVE_ZLIB = yes; then
+        unset ac_cv_lib_hdf5_H5Fopen
+        AC_CHECK_LIB( [hdf5], [H5Fopen], [HAVE_LIB_HDF5=yes; LIBS="-lsz -lz $LIBS"], [], [-lz -lsz] )
+      fi
+    fi
+  fi
+  if test HAVE_LIB_HDF5 = no; then
+    AC_MSG_ERROR([Could not find HDF5 library (-lhdf5)])
+  fi
+  LIBS="-lhdf5 $LIBS"
+  HAVE_HDF5=yes
+else
+  HAVE_HDF5=no
+fi
+
+
+]) # SNL_CHECK_HDF5
+
+
+
+
+#######################################################################################
+# Check for NetCDF library ((C++)
+# Sets HAVE_NETCDF to 'yes' or 'no'
+# If HAVE_NETCDF == yes, then updates INCLUDES and LIBS accordingly.
+#######################################################################################
+AC_DEFUN([SNL_CHECK_NETCDF],[
+
+AC_MSG_CHECKING([if NetCDF support is enabled])
+AC_ARG_WITH(netcdf, 
+[AC_HELP_STRING([--with-netcdf=DIR], [Specify NetCDF library to use for ExodusII file format])
+AC_HELP_STRING([--without-netcdf], [Disable support for ExodusII file format])],
+[NETCDF_ARG=$withval], [NETCDF_ARG=yes])
+if test "xno" = "x$NETCDF_ARG"; then
+  AC_MSG_RESULT([no])
+else
+  AC_MSG_RESULT([yes])
+fi
+
+ # if NetCDF support is not disabled
+if test "xno" != "x$NETCDF_ARG"; then
+    # Add flag to defines
+  DEFINES="$DEFINES -DNETCDF_FILE"
+
+    # Check for stream headers and set STRSTREAM_H_SPEC accordingly
+  AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  AC_CHECK_HEADER( [strstream.h], [NETCDF_DEF="<strstream.h>"], [
+    AC_CHECK_HEADER( [sstream.h], [NETCDF_DEF="<sstream.h>"], [
+      AC_CHECK_HEADER( [strstream], [NETCDF_DEF="<strstream>"], [
+        AC_CHECK_HEADER( [sstream], [NETCDF_DEF="<sstream>"] )
+  ] ) ] ) ] )
+  AC_LANG_RESTORE
+
+    # if a path is specified, update LIBS and INCLUDES accordingly
+  if test "xyes" != "x$NETCDF_ARG"; then
+    if test -d "${NETCDF_ARG}/lib"; then
+      LIBS="$LIBS -L${NETCDF_ARG}/lib"
+    elif test -d "${NETCDF_ARG}"; then
+      LIBS="$LIBS -L${NETCDF_ARG}"
+    else
+      AC_MSG_ERROR("$NETCDF_ARG is not a directory.")
+    fi
+    if test -d "${NETCDF_ARG}/include"; then
+      INCLUDES="$INCLUDES -I${NETCDF_ARG}/include"
+    elif test -d "${NETCDF_ARG}/inc"; then
+      INCLUDES="$INCLUDES -I${NETCDF_ARG}/inc"
+    else
+      INCLUDES="$INCLUDES -I${NETCDF_ARG}"
+    fi
+  fi
+  
+  old_CPPFLAGS="$CPPFLAGS"
+  CPPFLAGS="$CPPFLAGS $INCLUDES"
+  old_CXXFLAGS="$CXXFLAGS"
+  CXXFLAGS="$CXXFLAGS $INCLUDES"
+   # Check for C library
+  AC_CHECK_HEADERS( [netcdf.h], [], [AC_MSG_ERROR([[NetCDF header not found.]])] )
+  AC_MSG_CHECKING([for netcdf.hh])
+  AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  HAVE_NETCDF_HH=no
+  AC_TRY_COMPILE( 
+[#include "netcdf.hh"], [], [HAVE_NETCDF_HH=yes; NETCDF_DEF=], [
+    AC_TRY_COMPILE( 
+[#define STRSTREAM_H_SPEC $NETCDF_DEF
+ #include "netcdf.hh"], [], [HAVE_NETCDF_HH=yes], [NAVE_NETCDF_HH=no])])
+  AC_MSG_RESULT([$HAVE_NETCDF_HH])
+  if test $HAVE_NETCDF_HH != yes; then
+    AC_MSG_ERROR([NetCDF C++ header not found])
+  fi
+  if test "x$NETCDF_DEF" != "x"; then
+  CPPFLAGS="$CPPFLAGS -DSTRSTREAM_H_SPEC=$NETCDF_DEF"
+  CXXFLAGS="$CXXFLAGS -DSTRSTREAM_H_SPEC=$NETCDF_DEF"
+  fi
+  AC_MSG_CHECKING([[for netcdf_c++ library]])
+  LIBS="$LIBS -lnetcdf_c++ -lnetcdf"
+  AC_TRY_LINK(
+    [#include <netcdf.hh>], [NcFile ncf("foo",NcFile::ReadOnly);],
+    [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); AC_MSG_ERROR([NetCDF C++ API not found])] )
+  AC_LANG_RESTORE
+  CPPFLAGS="$old_CPPFLAGS"
+  CXXFLAGS="$old_CXXFLAGS"
+  if test "x$NETCDF_DEF" != "x"; then
+    DEFINES="$DEFINES '-DSTRSTREAM_H_SPEC=$NETCDF_DEF'"
+  fi
+  
+  HAVE_NETCDF=yes
+else
+  HAVE_NETCDF=no
+fi
+
+]) # SNL_HAVE_NETCDF
+
+
+
+
+#######################################################################################
+# Macro to set the following variables:
+# ACIS_VERSION
+# ACIS_LIB_DIR
+# ACIS_DEBUG_LIB_DIR
+# ACIS_PLATFORM
+# This macro expects ACIS_DIR to be set.
+# If ACIS_SYSTEM is set, ACIS_LIB_DIR will
+# be constructed using that value rather than
+# via a trial-and-error search.
+# If ACIS_VERSION is set, the corresponding test
+# will be skipped.
+#######################################################################################
+AC_DEFUN([SNL_ACIS_ENV], [
+
+AC_CHECK_FILE([$ACIS_DIR/include/acis.hxx], [], [AC_MSG_ERROR("Invalid ACIS path")])
+ 
+if test "x" == "x$ACIS_SYSTEM"; then
+  dir_list="$ACIS_DIR/bin/*"
+else
+  dir_list="$ACIS_DIR/bin/$ACIS_SYSTEM"
+fi
+
+for dir in $dir_list; do
+    # first try non-debug libraries
+  case "$dir" in
+    *_debug)
+      ;;
+    *)
+      if ! test "$ACIS_VERSION" -gt "600"; then
+        SNL_ACIS_VERSION( [$dir] )
+        ACIS_LIB_DIR="$dir"
+      fi
+      ;;
+  esac
+    # next try debug libraries
+  case "$dir" in
+    *_debug)
+      if ! test "$ACIS_VERSION" -gt "600"; then
+        SNL_ACIS_VERSION( [$dir] )
+        ACIS_DEBUG_LIB_DIR="$dir"
+      fi
+      ;;
+  esac
+done
+
+if ! test "$ACIS_VERSION" -gt "600"; then
+  AC_MSG_ERROR([ACIS configuration failed.  Verify ACIS directory.  Try specifying ACIS system and version])
+fi
+
+# If either ACIS_LIB_DIR or ACIS_DEBUG_LIB_DIR is not defined,
+# make both the same
+if test "x" = "x$ACIS_LIB_DIR"; then
+  ACIS_LIB_DIR="$ACIS_DEBUG_LIB_DIR"
+elif test "x" = "x$ACIS_DEBUG_LIB_DIR"; then
+  ACIS_DEBUG_LIB_DIR="$ACIS_LIB_DIR"
+fi
+
+# Determine the ACIS platform name from the lib dir
+AC_MSG_CHECKING([ACIS platform name])
+case "$ACIS_LIB_DIR" in
+  $ACIS_DIR/bin/aix*)  
+    ACIS_PLATFORM=aix
+    ;;
+  $ACIS_DIR/bin/hp700*)
+    ACIS_PLATFORM=hp700
+    ;;
+  $ACIS_DIR/bin/linux*)
+    ACIS_PLATFORM=linux
+    ;;
+  $ACIS_DIR/bin/mac*)
+    ACIS_PLATFORM=mac
+    ;;
+  $ACIS_DIR/bin/osf1*)
+    ACIS_PLATFORM=osf1
+    ;;
+  $ACIS_DIR/bin/sgi*)
+    ACIS_PLATFORM=sgi
+    ;;
+  $ACIS_DIR/bin/solaris*)
+    ACIS_PLATFORM=solaris
+    ;;
+  *)
+    AC_MSG_ERROR([Cannot determine ACIS platform name.])
+    ;;
+esac
+AC_MSG_RESULT([$ACIS_PLATFORM])
+])
+
+
+
+#######################################################################################
+# Macro to check for ACIS translators.
+#######################################################################################
+AC_DEFUN([SNL_ACIS_TRANSLATOR], [
+AC_REQUIRE([SNL_ACIS_ENV])
+case "$ACIS_VERSION" in
+  11??)
+    ACIS_XLATE_LIBS='-lxacis2k -lxcore2k -lxutil'
+    ;;
+  1[23]??)
+    ACIS_XLATE_LIBS='-lSPAXAssemblyRep -lSPAXInterop -lSPAXBase -lxacis2k -lxcore2k -lxutil'
+    ;;
+  14??)
+    ACIS_XLATE_LIBS='-lSPAXAssemblyRep -lSPAXInterop -lSPAXAcisBase -lSPAXDefaultGeometryRep -lSPAXGeometryRepresentation -lSPAXPropertiesBRepImporter -lSPAXPropertiesBase -lSPAXBase -lxacis2k -lxcore2k'
+    ;;
+  *)
+    ACIS_XLATE_LIBS='-lSPAXEBOMBase -lSPAXEBOMNewAssemblyExporter -lSPAXEBOMNewAssemblyImporter -lSPAXXMLTk -lpthread -lSPAXPropertiesNewAssemblyImporter -lSPAXAssemblyRep -lSPAXInterop -lSPAXAcisBase -lSPAXDefaultGeometryRep -lSPAXGeometryRepresentation -lSPAXPropertiesBRepImporter -lSPAXPropertiesBase -lSPAXBase -lxacis2k -lxcore2k'
+    ;;
+esac
+old_LIBS="$LIBS"
+LIBS="$LIBS -L$ACIS_LIB_DIR $ACIS_XLATE_LIBS $ACIS_BASE_LIBS"
+AC_CHECK_LIB([xstep],[main],[ACIS_STEP_TRANSLATOR=-DACIS_STEP_TRANSLATOR])
+AC_CHECK_LIB([xiges],[main],[ACIS_IGES_TRANSLATOR=-DACIS_IGES_TRANSLATOR])
+LIBS="$old_LIBS"
+])
+
+
+#######################################################################################
+# *******************************************************************************
+# **************************** INTERNAL STUFF ***********************************
+# *******************************************************************************
+#######################################################################################
+
+#################################################################################
+# Check if the compiler defines a specific preprocessor macro
+# Arguments:
+#  - preprocessor define to check for
+#  - action upon success
+#  - action upon failure
+#################################################################################
+AC_DEFUN([SNL_TRY_COMPILER_DEFINE], [
+AC_COMPILE_IFELSE([
+AC_LANG_PROGRAM( [[#ifndef $1
+  choke me
+#endif]], []) ],
+[$2],[$3])
+])
+
+
+#######################################################################################
+# Check for compiler-specific flags.
+# Sets the following environmental variables:
+#   SNL_CXX_SPECIAL : Any compiler-specific flags which must be specified
+#   SNL_CXX_32BIT   : Flag to force compilation of 32-bit code
+#   SNL_CXX_64BIT   : Flag to force compilation of 64-bit code
+#######################################################################################
+AC_DEFUN([SNL_CXX_FLAGS], [
+AC_REQUIRE([AC_PROG_CXX])
+
+# Detect compiler 
+AC_MSG_CHECKING([for known c++ compilers])
+# Autoconf does G++ for us
+if test x$GXX = xyes; then
+  cxx_compiler=GNU
+# Search for other compiler types
+# For efficiency, limit checks to relevant OSs
+else
+  cxx_compiler=unknown
+  AC_LANG_SAVE
+  AC_LANG_CPLUSPLUS
+  case "$target_os" in
+    aix*)
+      SNL_TRY_COMPILER_DEFINE([__IBMCPP__],[cxx_compiler=VisualAge])
+      ;;
+    solaris*|sunos*)
+      SNL_TRY_COMPILER_DEFINE([__SUNPRO_CC],[cxx_compiler=SunWorkshop])
+      ;;
+    irix*)
+      SNL_TRY_COMPILER_DEFINE([__sgi],[cxx_compiler=MIPSpro])
+      ;;
+    linux*)
+      SNL_TRY_COMPILER_DEFINE([__INTEL_COMPILER],[cxx_compiler=Intel])
+      SNL_TRY_COMPILER_DEFINE([__IBMCPP__],[cxx_compiler=VisualAge])
+      SNL_TRY_COMPILER_DEFINE([__DECCXX_VER],[cxx_compiler=Compaq])
+      ;;
+    hpux*)
+      SNL_TRY_COMPILER_DEFINE([__HP_aCC],[cxx_compiler=HP])
+      ;;
+    windows*)
+      SNL_TRY_COMPILER_DEFINE([__MSC_VER],[cxx_compiler=VisualStudio])
+      SNL_TRY_COMPILER_DEFINE([__INTEL_COMPILER],[cxx_compiler=Intel])
+      SNL_TRY_COMPILER_DEFINE([__DECCXX_VER],[cxx_compiler=Compaq])
+      SNL_TRY_COMPILER_DEFINE([__BORLANDC__],[cxx_compiler=Borland])
+      SNL_TRY_COMPILER_DEFINE([__CYGWIN__],[cxx_compiler=Cygwin])
+      SNL_TRY_COMPILER_DEFINE([__MINGW32__],[cxx_compiler=MinGW])
+      ;;
+  esac
+  AC_LANG_RESTORE
+fi
+AC_MSG_RESULT([$cxx_compiler])
+if test "x$cxx_compiler" = "xunknown"; then
+  AC_MSG_WARN([Unrecognized C++ compiler: $CXX])
+fi
+
+# Now decide special compiler flags using compiler/cpu combination
+AC_MSG_CHECKING([for known compiler/OS combinations])
+case "$cxx_compiler:$host_cpu" in
+  GNU:sparc*)
+    SNL_CXX_32BIT=-m32
+    SNL_CXX_64BIT=-m64
+    SNL_CXX_SPECIAL="-Wall -pipe"
+    ;;
+  GNU:powerpc*)
+    SNL_CXX_32BIT=-m32
+    SNL_CXX_64BIT=-m64
+    SNL_CXX_SPECIAL="-Wall -pipe"
+    ;;
+  GNU:i?86|GNU:x86_64)
+    SNL_CXX_32BIT=-m32
+    SNL_CXX_64BIT=-m64
+    SNL_CXX_SPECIAL="-Wall -pipe"
+    ;;
+  GNU:mips*)
+    SNL_CXX_32BIT="-mips32 -mabi=32"
+    SNL_CXX_64BIT="-mips64 -mabi=64"
+    SNL_CXX_SPECIAL="-Wall -pipe"
+    ;;
+  VisualAge:*)
+    SNL_CXX_32BIT=-q32
+    SNL_CXX_64BIT=-q64
+    # Do V5.0 namemangling for compatibility with ACIS, and enable RTTI
+    SNL_CXX_SPECIAL="-qrtti=all -qnamemangling=v5"
+    AR="ar -X 32_64"
+    NM="nm -B -X 32_64"
+    ;;
+  MIPSpro:mips)
+    SNL_CXX_32BIT=-n32
+    SNL_CXX_64BIT=-64
+    SNL_CXX_SPECIAL=-LANG:std
+    ;;
+  MIPSpro:*)
+    SNL_CXX_SPECIAL=-LANG:std
+    ;;
+  SunWorkshop:sparc*)
+    SNL_CXX_32BIT=-xarch=generic
+    SNL_CXX_64BIT=-xarch=generic64
+    ;;
+  *)
+    ;;
+esac
+AC_MSG_RESULT([$cxx_compiler:$host_cpu])
+]) # end SNL_CXX_FLAGS
+
+#######################################################################################
+# Check for compiler-specific flags.
+# Sets the following environmental variables:
+#   SNL_CC_SPECIAL : Any compiler-specific flags which must be specified
+#   SNL_CC_32BIT   : Flag to force compilation of 32-bit code
+#   SNL_CC_64BIT   : Flag to force compilation of 64-bit code
+#######################################################################################
+AC_DEFUN([SNL_CC_FLAGS], [
+AC_REQUIRE([AC_PROG_CC])
+
+# Detect compiler 
+
+AC_MSG_CHECKING([for known C compilers])
+# Autoconf does gcc for us
+if test x$GCC = xyes; then
+  cc_compiler=GNU
+# Search for other compiler types
+# For efficiency, limit checks to relevant OSs
+else
+  cc_compiler=unknown
+  case "$target_os" in
+    aix*)
+      SNL_TRY_COMPILER_DEFINE([__IBMC__],[cc_compiler=VisualAge])
+      ;;
+    solaris*|sunos*)
+      SNL_TRY_COMPILER_DEFINE([__SUNPRO_C],[cc_compiler=SunWorkshop])
+      ;;
+    irix*)
+      SNL_TRY_COMPILER_DEFINE([__sgi],[cc_compiler=MIPSpro])
+      ;;
+    linux*)
+      SNL_TRY_COMPILER_DEFINE([__INTEL_COMPILER],[cc_compiler=Intel])
+      SNL_TRY_COMPILER_DEFINE([__IBMC__],[cc_compiler=VisualAge])
+      SNL_TRY_COMPILER_DEFINE([__DECC_VER],[cc_compiler=Compaq])
+      ;;
+    hpux*)
+      SNL_TRY_COMPILER_DEFINE([__HP_cc],[cc_compiler=HP])
+      ;;
+    windows*)
+      SNL_TRY_COMPILER_DEFINE([__MSC_VER],[cc_compiler=VisualStudio])
+      SNL_TRY_COMPILER_DEFINE([__INTEL_COMPILER],[cc_compiler=Intel])
+      SNL_TRY_COMPILER_DEFINE([__DECC_VER],[cc_compiler=Compaq])
+      SNL_TRY_COMPILER_DEFINE([__BORLANDC__],[cc_compiler=Borland])
+      SNL_TRY_COMPILER_DEFINE([__TURBOC__],[cc_compiler=TurboC])
+      SNL_TRY_COMPILER_DEFINE([__CYGWIN__],[cc_compiler=Cygwin])
+      SNL_TRY_COMPILER_DEFINE([__MINGW32__],[cc_compiler=MinGW])
+      ;;
+  esac
+fi
+AC_MSG_RESULT([$cc_compiler])
+if test "x$cc_compiler" = "xunknown"; then
+  AC_MSG_WARN([Unrecognized C compiler: $CXX])
+fi
+
+# Now decide special compiler flags using compiler/cpu combination
+AC_MSG_CHECKING([for known compiler/OS combinations])
+case "$cc_compiler:$host_cpu" in
+  GNU:sparc*)
+    SNL_CC_32BIT=-m32
+    SNL_CC_64BIT=-m64
+    SNL_CC_SPECIAL="-Wall -pipe"
+    ;;
+  GNU:powerpc*)
+    SNL_CC_32BIT=-m32
+    SNL_CC_64BIT=-m64
+    SNL_CC_SPECIAL="-Wall -pipe"
+    ;;
+  GNU:i?86|GNU:x86_64)
+    SNL_CC_32BIT=-m32
+    SNL_CC_64BIT=-m64
+    SNL_CC_SPECIAL="-Wall -pipe"
+    ;;
+  GNU:mips*)
+    SNL_CC_32BIT="-mips32 -mabi=32"
+    SNL_CC_64BIT="-mips64 -mabi=64"
+    SNL_CC_SPECIAL="-Wall -pipe"
+    ;;
+  VisualAge:*)
+    SNL_CC_32BIT=-q32
+    SNL_CC_64BIT=-q64
+    AR="ar -X 32_64"
+    NM="nm -B -X 32_64"
+    ;;
+  MIPSpro:mips)
+    SNL_CC_32BIT=-n32
+    SNL_CC_64BIT=-64
+    SNL_CC_SPECIAL=-LANG:std
+    ;;
+  MIPSpro:*)
+    SNL_CC_SPECIAL=-LANG:std
+    ;;
+  SunWorkshop:sparc*)
+    SNL_CC_32BIT=-xarch=generic
+    SNL_CC_64BIT=-xarch=generic64
+    ;;
+  *)
+    ;;
+esac
+AC_MSG_RESULT([$cc_compiler:$host_cpu])
+]) # end SNL_CC_FLAGS
+
+
+#######################################################################################
+# Macro to get ACIS_VERSION
+# Expected arguments: ACIS library path
+#######################################################################################
+AC_DEFUN([SNL_ACIS_VERSION], [
+AC_REQUIRE([AC_PROG_LIBTOOL])
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_MSG_CHECKING([ACIS version of $1])
+src=conftest.cc
+exe=conftest
+
+cat <<END_SNL_ACIS_VERSION_SRC  >$src
+#include <stdio.h>
+int get_major_version();
+int get_minor_version();
+int get_point_version();
+int main(int,char**) { printf("%d\n", 
+100*get_major_version() +
+ 10*get_minor_version() +
+    get_point_version()); 
+return 0;}
+
+END_SNL_ACIS_VERSION_SRC
+
+FLAGS="$CXXFLAGS $LDFLAGS -L$1 -R$1"
+if ./libtool --mode=link $CXX $FLAGS $src -lSpaBase -o $exe >/dev/null 2>/dev/null; then
+  ACIS_VERSION=`./$exe || echo 0`
+  AC_MSG_RESULT($ACIS_VERSION)
+else
+  ACIS_VERSION=0
+  AC_MSG_RESULT(failed)
+fi
+
+#rm -f $src $exe
+AC_LANG_RESTORE
+]) # SNL_ACIS_VERSION
Index: /cgm/cgm.make.in
===================================================================
--- /cgm/cgm.make.in (revision 1040)
+++ /cgm/cgm.make.in (revision 1040)
@@ -0,0 +1,60 @@
+#==================================================================
+#
+# To build CGM applications, do the following:
+#
+# 0. include this file in your makefile (using 'include config.make')
+# 1. Insert '${CGM_INCLUDES}' (w/o quotes) in your compile command, e.g.
+#      ${CXX} ${CGM_INCLUDES} -c mysource.cpp
+# 2. Insert '${CGM_LIBS_LINK}' (w/o quotes) on your link line
+#
+# That's it! No need to look at the code below, unless you're curious.
+#
+#==================================================================
+
+CANT_USE_STD           = @CANT_USE_STD@
+CANT_USE_STD_IO        = @CANT_USE_STD_IO@
+TEMPLATE_DEFS_INCLUDED = @TEMPLATE_DEFS_INCLUDED@
+
+ACIS_DEFS            = @ACIS_DEFS@
+ACIS_DIR             = @ACIS_DIR@
+ACIS_LIB_DIR         = @ACIS_LIB_DIR@
+ACIS_VERSION         = @ACIS_VERSION@
+ACIS_HEALER          = @ACIS_HEALER@
+ACIS_PLATFORM        = @ACIS_PLATFORM@
+ACIS_STEP_TRANSLATOR = @ACIS_STEP_TRANSLATOR@
+ACIS_IGES_TRANSLATOR = @ACIS_IGES_TRANSLATOR@
+ACIS_LIBS            = @ACIS_LIBS@
+ACIS_INCLUDES        = @ACIS_INCLUDES@
+
+CGM_PARALLEL_INCLUDE = @CGM_PARALLEL_INCLUDE@
+CGM_PARALLEL_LIB = @CGM_PARALLEL_LIB@
+CGM_PARALLEL_LIB_FILE = @CGM_PARALLEL_LIB_FILE@
+# These get redefined by a makefile target during *install*
+# by appending correct values to the end of the file.
+CGM_LIBDIR = @abs_builddir@/.libs
+CGM_INCLUDEDIR = @abs_srcdir@
+
+CGM_CXX = @CXX@
+CGM_CC = @CC@
+CGM_CXXFLAGS = @CXXFLAGS@ @CANT_USE_STD@ @CANT_USE_STD_IO@ @TEMPLATE_DEFS_INCLUDED@ ${ACIS_DEFS}
+CGM_CFLAGS = @CFLAGS@
+CGM_LDFLAGS = @LDFLAGS@
+
+CGM_INCLUDES = -I$(CGM_DIR)/util -I$(CGM_DIR)/geom -I$(CGM_DIR)/geom/ACIS $(CGM_PARALLEL_INCLUDE) -I$(CGM_INCLUDEDIR) ${ACIS_INCLUDES}
+
+CGM_LIBS_LINK = ${LDFLAGS} \
+	-L$(CGM_DIR)/geom/virtual -L$(CGM_DIR)/geom/facetbool -L$(CGM_DIR)/geom/facet \
+	-L$(CGM_DIR)/geom/Cholla -L$(CGM_DIR)/geom/ACIS -L$(CGM_DIR)/geom -L$(CGM_DIR)/util \
+	-L${ACIS_LIB_DIR} \
+	-L$(CGM_LIBDIR) \
+	${ACIS_LIBS} -lcubit_virtual -lcubit_facet -lcubit_facetbool -lcholla ${ACIS_LIBS} -lcubit_geom -lcubit_util \
+	${CGM_PARALLEL_LIB}
+
+CGM_LIBS_FILES = \
+       $(CGM_LIBDIR)/libcubit_virtual.a \
+       $(CGM_LIBDIR)/libcubit_facetbool.a \
+       $(CGM_LIBDIR)/libcubit_facet.a \
+       $(CGM_LIBDIR)/libcholla.a \
+       $(CGM_LIBDIR)/libcubit_geom.a \
+       $(CGM_LIBDIR)/libcubit_util.a \
+       ${CGM_PARALLEL_LIB_FILE}
Index: /cgm/geom/TopologyBridge.hpp
===================================================================
--- /cgm/geom/TopologyBridge.hpp (revision 1040)
+++ /cgm/geom/TopologyBridge.hpp (revision 1040)
@@ -0,0 +1,240 @@
+//-------------------------------------------------------------------------
+// Filename      : TopologyBridge.hpp
+//
+// Purpose       : This file contains the declarations of the base class 
+//                 TopologyBridge.  Sub-classes of TopologyBridge
+//                 represent the link between the Cubit representation
+//                 of an entity (such as RefVertex) and the GME representation
+//                 of an entity (such as an acis VERTEX).
+//
+// Creator       : Darryl Melander
+//
+// Creation Date : 01/10/99
+//
+// Owner         : Darryl Melander
+//-------------------------------------------------------------------------
+
+#ifndef MODEL_ENTITY_BRIDGE_HPP
+#define MODEL_ENTITY_BRIDGE_HPP
+
+
+#include <typeinfo>
+#if !defined(NT)
+using std::type_info;
+#endif
+
+// ********** BEGIN CUBIT INCLUDES         **********
+#include "CubitDefines.h"
+#include "CubitGeomConfigure.h"
+// ********** END CUBIT INCLUDES           **********
+
+// ********** BEGIN FORWARD DECLARATIONS   **********
+class TopologyEntity;
+class RefVolume;
+class GeometryQueryEngine;
+class CubitSimpleAttrib;
+class CubitSimpleAttrib;
+class CubitString;
+class BridgeManager;
+class TBOwner;
+template <class X> class DLIList;
+class Lump;
+class ShellSM;
+class Surface;
+class LoopSM;
+class Curve;
+class CoEdgeSM;
+class Point;
+class TopologyBridge;
+class TopologyEntity;
+class BodySM;
+class Lump;
+class ShellSM;
+class Surface;
+class LoopSM;
+class Curve;
+class CoEdgeSM;
+class Point;
+
+// ********** END FORWARD DECLARATIONS     **********
+
+class CUBIT_GEOM_EXPORT TopologyBridge 
+{
+public:
+  TopologyBridge() 
+      : bridgeOwner(0),
+        bridgeSense(CUBIT_FORWARD)
+    {}
+
+  virtual ~TopologyBridge();
+  
+  const type_info& generic_entity_type_info();
+  
+  virtual const type_info& topology_entity_type_info() const = 0;
+  
+  virtual void append_simple_attribute_virt(CubitSimpleAttrib*) = 0;
+    //R void
+    //I name
+    //I- A reference to a constant CubitString object which is the name
+    //I- that is to be appended to the TopologyBridge object.
+    //- The purpose of this function is to append a string
+    //- attribute to the TB. The name is attached to each 
+    //- of the underlying solid model entities.
+  
+  virtual void remove_simple_attribute_virt(CubitSimpleAttrib*) = 0;
+    //R void
+    //I CubitSimpleAttrib*
+    //I- A reference to a CubitSimpleAttrib object which is the object
+    //I- that is to be removed to this TB object.
+    //- The purpose of this function is to remove a simple
+    //- attribute from the TB. The attribute is attached to each of the
+    //- underlying solid model entities this one points to.
+  
+  virtual void remove_all_simple_attribute_virt() = 0;
+    //R void
+    //I-
+    //- The purpose of this function is to remove all simple
+    //- attributes from the TB. 
+  
+  virtual CubitStatus get_simple_attribute(DLIList<CubitSimpleAttrib*>&) = 0;
+    //R CubitSimpleAttrib*
+    //R- the returned cubit simple attribute.
+    //- The purpose of this function is to get the attributes
+    //- of the geometry entity. The name is attached to the underlying solid
+    //- model entity(ies) this one points to.
+    //- The default implementation returns a NULL.
+    //- MJP Note:
+    //- This is the code that implements the requirement that names
+    //- of VGI Entities propagate across solid model boolean
+    //- operations.  The success of this relies, of course, on the underlying
+    //- solid modeler being able to propagate attributes across
+    //- such operations on its entities. If it cannot, then "names"
+    //- of VGI entities will not propagate.
+    
+  virtual CubitStatus get_simple_attribute(const CubitString& name,
+                                    DLIList<CubitSimpleAttrib*>& ) = 0;
+
+  TopologyEntity* topology_entity() const;
+    //R TopologyEntity*
+    //R- Pointer to the TopologyEntity using this TopologyBridge.
+    //- This (pure virtual) function returns a pointer to the
+    //- TopologyEntity that is using this object, i.e. owner of this
+    //- TopologyBridge. It is implied that a TopologyBridge is not
+    //- used by more than one TopologyEntity.
+
+  TBOwner* owner() const
+    { return bridgeOwner; }
+  
+  void owner( TBOwner* new_owner )
+    { bridgeOwner = new_owner; }
+    
+  BridgeManager* bridge_manager() const;
+  void bridge_manager(BridgeManager* manager);
+  
+  CubitSense bridge_sense() 
+    { return bridgeSense; }
+  void reverse_bridge_sense() 
+    { bridgeSense = bridgeSense == CUBIT_UNKNOWN ? CUBIT_UNKNOWN  :
+                    bridgeSense == CUBIT_FORWARD ? CUBIT_REVERSED :
+                                                   CUBIT_FORWARD; }
+    //- Get or switch the bridge sense.
+    //-
+    //- The bridge sense is the sense of the TopologyBridge with
+    //- respect to it's owning TopologyEntity.  The results of
+    //- geometric evaluation functions on the ownging TopologyEntity
+    //- may be affected by this value.  
+    //-
+    //- Currently, this is only set for Surfaces and Curves, as the
+    //- sense of either may be opposite that of its owning RefFace
+    //- or RefEdge when merging occurs.  It is not set/used on Loops
+    //- or CoEdges because a) there are no geometric evaluations on
+    //- the underlying LoopSMs or CoEdgeSMs and b) the relative sense
+    //- can be inferred from that of the corresponding Surface and
+    //- Curve.
+    //-
+    //- This value is saved in the MergePartner attribute.
+    
+  virtual GeometryQueryEngine* get_geometry_query_engine() const = 0;
+    //- This function returns a pointer to the geometry query engine
+    //- associated with the object.
+  
+  virtual int validate(const CubitString&,
+                       DLIList <TopologyEntity*>&)
+    { return 0; }
+    //- Check that entity is valid. Returns number of problems detected.
+    //- For sub-classes that don't implement this, just assume there are
+    //- no problems and return 0.
+
+  
+  enum { MAX_TB_LAYER = 255 };
+  virtual int layer() const { return 0; }
+    //- Bridge layer at which this bridge occurs.
+    //- 0   - real geometry
+    //- 126 - sub-composite partition layer
+    //- 127 - composite layer
+    //- 128 - super-composite partition layer
+
+  void get_parents(DLIList<TopologyBridge*> &parents);
+    //- get parent topology bridges
+
+  void get_children(DLIList<TopologyBridge*> &children,
+                    bool return_hidden_entities = false,
+                    int layer = MAX_TB_LAYER );
+    //- get child topology bridges
+  
+  void get_related(const type_info& other_type,
+                   DLIList<TopologyBridge*> &related);
+    //- get the related entities of type other_type
+  
+#ifdef BOYD14
+  CubitBoolean is_related(TopologyBridge *other_entity);
+    //- returns CUBIT_TRUE if this and other_entity are directly related
+#endif
+  void bodysms(DLIList<BodySM*> &bodies,bool unique = true);
+  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 loopsms(DLIList<LoopSM*> &loopsms,bool unique = true);
+  void curves(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
+    //- functions in the modeler
+  
+  BodySM *bodysm();
+  Lump *lump();
+#ifdef BOYD14
+  ShellSM *shellsm();
+  Surface *vgi_surface();
+  Curve *vgi_curve();
+  CoEdgeSM *coedgesm();
+  Point *point();
+    //- topology traversal of TB's; implemented based on native traversal
+    //- functions in the modeler
+#endif
+  LoopSM *loopsm();
+  
+  virtual void get_parents_virt(DLIList<TopologyBridge*> &parents ) = 0;
+    //- Get parent topology bridges as returned by solid modeler.
+    //- Derived classes must provide this method for use in the
+    //- implementation of get_parents(..).  You probably want to 
+    //- be using get_parents(..) rather than this method.
+
+  virtual void get_children_virt(DLIList<TopologyBridge*> &children ) = 0;
+    //- Get child topology bridges as returned by solid modeler.
+    //- Derived classes must provide this method for use in the
+    //- implementation of get_children(..).  You probably want to 
+    //- be using get_children(..) rather than this method.
+  
+private:
+
+  
+  TBOwner* bridgeOwner;
+  
+  CubitSense bridgeSense;
+    //- (See comments for bridge_sense() method.)
+  
+};
+
+#endif
+
Index: /cgm/geom/CAGroup.cpp
===================================================================
--- /cgm/geom/CAGroup.cpp (revision 1040)
+++ /cgm/geom/CAGroup.cpp (revision 1040)
@@ -0,0 +1,662 @@
+//- Class:          CAGroup
+//- Owner:          Greg Nielson
+//- Description:    Cubit Attribute for groups.
+//- Checked By:
+//- Version:
+
+#include "CAGroup.hpp"
+#include "RefEntity.hpp"
+#include "RefEntityFactory.hpp"
+#include "RefGroup.hpp"
+#include "CubitObserver.hpp"
+#include "DLIList.hpp"
+#include "CastTo.hpp"
+#include "TDCAGE.hpp"
+#include "GeometryQueryTool.hpp"
+
+#include <stdlib.h>
+#include <time.h>
+
+// initialize this CA's static members
+CubitBoolean CAGroup::initialize_rand = CUBIT_TRUE;
+
+CubitAttrib* CAGroup_creator(RefEntity* entity, CubitSimpleAttrib *p_csa)
+{
+  CAGroup *new_attrib = NULL;
+  if (NULL == p_csa)
+  {
+    new_attrib = new CAGroup(entity);
+  }
+  else
+  {
+    new_attrib = new CAGroup(entity, p_csa);
+  }
+
+  return new_attrib;
+}
+
+CAGroup::CAGroup(RefEntity* new_attrib_owner)
+        : CubitAttrib(new_attrib_owner)
+{
+  initialize();
+}
+
+CAGroup::CAGroup(RefEntity* new_attrib_owner,
+                 CubitSimpleAttrib *csa_ptr)
+        : CubitAttrib(new_attrib_owner)
+{
+
+  initialize();
+  
+  DLIList<int*> *i_list = csa_ptr->int_data_list();
+  DLIList<CubitString*> *cs_list = csa_ptr->string_data_list();
+
+    // first, the ints
+  i_list->reset();
+  
+  int num_groups = *(i_list->get_and_step());
+  
+    // groupID
+  int i;
+  for (i = num_groups; i > 0; i--)
+    groupID.append(*(i_list->get_and_step()));
+
+      // uniqueID
+  for (i = num_groups; i > 0; i--)
+    uniqueID.append(*(i_list->get_and_step()));
+
+      // sequenceNumbers
+  for (i = num_groups; i > 0; i--)
+    sequenceNumbers.append(*(i_list->get_and_step()));
+
+    // numOwningGroups
+  for (i = num_groups; i > 0; i--)
+    numOwningGroups.append(*(i_list->get_and_step()));
+
+    // total number of owning groups
+  int total_owning_groups = *(i_list->get_and_step());
+  
+    // owningGroupID
+  for (i = total_owning_groups; i > 0; i--)
+    owningGroupID.append(*(i_list->get_and_step()));
+    
+    // owningUniqueID
+  for (i = total_owning_groups; i > 0; i--)
+    owningUniqueID.append(*(i_list->get_and_step()));
+
+    // owningSequenceNumbers
+  for (i = total_owning_groups; i > 0; i--)
+    owningSequenceNumbers.append(*(i_list->get_and_step()));
+
+    // ancestor groups added after first implementation of CAGroup,
+    // therefore not all attributes may have ancestor groups
+    // setting total_ancestor_groups to zero first will short-circuit
+    // loops below if there aren't any ancestor groups, so no need for
+    // an 'if' statement
+
+    // total number of ancestor groups
+  int total_ancestor_groups = 0;
+
+  if (i_list->size() > (4*num_groups + 3*total_owning_groups + 2))
+    total_ancestor_groups = *(i_list->get_and_step());
+  
+    // ancestorGroupID
+  for (i = total_ancestor_groups; i > 0; i--)
+    ancestorGroupID.append(*(i_list->get_and_step()));
+    
+    // ancestorUniqueID
+  for (i = total_ancestor_groups; i > 0; i--)
+    ancestorUniqueID.append(*(i_list->get_and_step()));
+    
+    // ancestorOwnedGroupUid
+  for (i = total_ancestor_groups; i > 0; i--)
+    ancestorOwnedGroupUid.append(*(i_list->get_and_step()));
+    
+     // ancestorSequenceNumbers
+  for (i = total_ancestor_groups; i > 0; i--)
+    ancestorSequenceNumbers.append(*(i_list->get_and_step()));
+    
+    // now, doubles (none)
+
+    // now, strings
+  cs_list->reset();
+
+    // attribute internal name (just pop the list)
+  cs_list->step();
+
+    // groupNames
+  for (i = num_groups; i > 0; i--)
+    groupNames.append(new CubitString(*(cs_list->get_and_step())));
+
+    // owningGroupNames
+  for (i = total_owning_groups; i > 0; i--)
+    owningGroupNames.append(new CubitString(*(cs_list->get_and_step())));
+
+    // ancestorGroupName
+  for (i = total_ancestor_groups; i > 0; i--)
+    ancestorGroupName.append(new CubitString(*(cs_list->get_and_step())));
+
+    // ok, we're done
+}
+
+CAGroup::~CAGroup()
+{
+  int i;
+  for ( i = groupNames.size(); i > 0; i--)
+    delete groupNames.get_and_step();
+  
+  for (i = owningGroupNames.size(); i > 0; i--)
+    delete owningGroupNames.get_and_step();
+}
+
+void CAGroup::initialize()
+{
+  if(initialize_rand == CUBIT_TRUE)
+  {
+#if defined NT || defined _NT || defined CUBIT_LINUX
+    srand((unsigned)time(NULL));
+#else
+    srand48(time(NULL));
+#endif
+    initialize_rand = CUBIT_FALSE;
+  }
+}
+
+
+
+CubitStatus CAGroup::actuate()
+{
+  if (hasActuated == CUBIT_TRUE) return CUBIT_SUCCESS;
+  
+    // need to reset all the lists to keep them in sync
+  groupID.reset();
+  uniqueID.reset();
+  groupNames.reset();
+  sequenceNumbers.reset();
+  owningGroupID.reset();
+  owningUniqueID.reset();
+  owningGroupNames.reset();
+  owningSequenceNumbers.reset();
+  numOwningGroups.reset();
+  
+    // go through all the groups on this CA
+  int i;
+  for (i = groupID.size(); i > 0; i--) {
+      // pop the data for this group off the lists
+    int group_id = groupID.get_and_step();
+    int unique_id = uniqueID.get_and_step();
+    CubitString *group_name = groupNames.get_and_step();
+    int seq_num = sequenceNumbers.get_and_step();
+
+    RefGroup *ref_group =
+        assign_group(attribOwnerEntity, group_id, unique_id, 
+                     group_name, seq_num);
+    
+    
+      // check for groups owning this group
+    int owning_groups = numOwningGroups.get_and_step();
+  
+    for (int j = owning_groups; j > 0; j--)
+    {
+      int owning_group_id = owningGroupID.get_and_step();
+      int owning_unique_id = owningUniqueID.get_and_step();
+      CubitString *owning_group_name = owningGroupNames.get_and_step();
+      seq_num = owningSequenceNumbers.get_and_step();
+
+      assign_group(ref_group, owning_group_id, owning_unique_id,
+                   owning_group_name, seq_num);
+    }
+
+  } // loop over all groups in this CAGroup
+
+    // now do ancestors
+  ancestorGroupID.reset();
+  ancestorUniqueID.reset();
+  ancestorOwnedGroupUid.reset();
+  ancestorGroupName.reset();
+  ancestorSequenceNumbers.reset();
+  
+  for (i = ancestorGroupID.size(); i > 0; i--) {
+    /*RefGroup *ancestor_group = */
+      assign_ancestor_group(ancestorGroupID.get_and_step(), 
+                            ancestorUniqueID.get_and_step(),
+                            ancestorGroupName.get_and_step(),
+                            ancestorOwnedGroupUid.get_and_step(),
+                            ancestorSequenceNumbers.get_and_step());
+  }
+  
+  deleteAttrib = CUBIT_TRUE;
+  hasActuated = CUBIT_TRUE;
+  
+  return CUBIT_SUCCESS;
+}
+
+RefGroup *CAGroup::assign_group(RefEntity *owned_entity,
+                                const int group_id, const int unique_id,
+                                CubitString *group_name,
+                                const int seq_num)
+{
+  RefGroup* parent_group = NULL;
+  CubitBoolean group_id_exists = CUBIT_FALSE;
+
+    // search for the group corresponding to this id and unique id
+  RefGroup *ref_group = GeometryQueryTool::instance()->get_last_ref_group();
+  for(int i = GeometryQueryTool::instance()->num_ref_groups(); i > 0 && !parent_group; i--)
+  {
+    ref_group = GeometryQueryTool::instance()->get_next_ref_group();
+    if(ref_group->id() == group_id)
+    {
+      group_id_exists = CUBIT_TRUE;
+    }
+
+    ToolData *td_temp = ref_group->get_TD(&TDCAGE::is_cage);
+    TDCAGE *td_cagroup = (td_temp ? CAST_TO(td_temp, TDCAGE) : NULL);
+    if (td_cagroup != NULL && td_cagroup->unique_id() == unique_id)
+      parent_group = ref_group;
+  }
+  
+  if(!parent_group)
+  {
+      // else make a new group, and assign id and unique id
+      // also assign group name
+    parent_group = RefEntityFactory::instance()->construct_RefGroup();
+    if(!group_id_exists) {
+      parent_group->set_id(0);
+      parent_group->set_id(group_id);
+    }
+    else
+      PRINT_INFO("Creating group %d to hold attribute group %d\n",
+                 parent_group->id(), group_id);
+
+      // put a td on this new group with the right unique_id
+    TDCAGE *td_cagroup = new TDCAGE(unique_id);
+    parent_group->add_TD(td_cagroup);
+
+      // add the attribOwnerEntity to the group and name the group
+    parent_group->entity_name(*group_name);
+  }
+
+    // add the entity to the group with the proper sequence number
+  TDCAGE::insert_entity(owned_entity, seq_num, parent_group);
+  
+  return parent_group;
+}
+  
+RefGroup *CAGroup::assign_ancestor_group(const int ancestor_id,
+                                         const int ancestor_uid,
+                                         const CubitString *ancestor_name,
+                                         const int owned_group_uid,
+                                         const int seq_num)
+{
+    // for each call of this function, we:
+    // - get an ancestor group with ancestor_id, ancestor_uid and
+    //   ancestor_name (make one if it doesn't exist)
+    // - add group with owned_group_uid to that ancestor group
+    //   (owned_group_uid should exist, error if not)
+    // search for the group corresponding to this id and unique id
+  RefGroup* ancestor_group = NULL;
+  RefGroup *owned_group = NULL;
+  CubitBoolean ancestor_id_exists = CUBIT_FALSE;
+
+  RefGroup *ref_group = GeometryQueryTool::instance()->get_last_ref_group();
+  
+  for(int i = GeometryQueryTool::instance()->num_ref_groups(); i > 0 && 
+        (!ancestor_group || !owned_group); i--)
+  {
+    ref_group = GeometryQueryTool::instance()->get_next_ref_group();
+  
+    if(ref_group->id() == ancestor_id)
+    {
+      ancestor_id_exists = CUBIT_TRUE;
+    }
+    
+    ToolData *td_temp = ref_group->get_TD(&TDCAGE::is_cage);
+    TDCAGE *td_cagroup = (td_temp ? CAST_TO(td_temp, TDCAGE) : NULL);
+    if (td_cagroup != NULL && td_cagroup->unique_id() == ancestor_uid) {
+      ancestor_group = ref_group;
+    }
+        
+    if (td_cagroup != NULL && td_cagroup->unique_id() == owned_group_uid) {
+      owned_group = ref_group;
+    }
+  }
+
+  assert(owned_group != 0);
+  
+  if (!ancestor_group)
+  {
+      // make a new group, and assign id and unique id
+      // also assign group name
+    ancestor_group = RefEntityFactory::instance()->construct_RefGroup();
+;
+    if(!ancestor_id_exists) {
+      ancestor_group->set_id(0);
+      ancestor_group->set_id(ancestor_id);
+    }
+    else
+      PRINT_INFO("Creating group %d to hold attribute group %d\n",
+                 ancestor_group->id(), ancestor_id);
+
+      // put a td on this new group with the right unique_id
+    TDCAGE *td_cagroup = new TDCAGE(ancestor_uid);
+    ancestor_group->add_TD(td_cagroup);
+
+      // add the owned group to the group and name the group
+    ancestor_group->entity_name(*ancestor_name);
+  }
+
+    // add the entity to the group with the proper sequence number
+  TDCAGE::insert_entity(owned_group, seq_num, ancestor_group);
+
+  return ancestor_group;
+}
+  
+CubitStatus CAGroup::update()
+{
+  if (hasUpdated) return CUBIT_SUCCESS;
+  
+    // set the updated flag
+  hasUpdated = CUBIT_TRUE;
+
+    // get the groups containing attribOwnerEntity
+  RefGroup* ref_group;
+  DLIList<RefGroup*> ref_group_list;
+  int i;
+
+  RefGroup::get_groups_within(attribOwnerEntity, ref_group_list, CUBIT_FALSE);
+
+  if( ref_group_list.size() == 0)
+  {
+    delete_attrib(CUBIT_TRUE);
+    return CUBIT_SUCCESS;
+  }
+
+    // else, this entity is owned by groups
+  RefGroup* parent_ref_group;
+
+    // get a td_cage onto the attribOwnerEntity, to keep sequence numbers
+    // for the owning groups
+  TDCAGE *td_entity = (TDCAGE *) attribOwnerEntity->get_TD(&TDCAGE::is_cage);
+  if (!td_entity) {
+    td_entity = new TDCAGE(-1);
+    attribOwnerEntity->add_TD(td_entity);
+  }
+
+    // now, initialize that tdcage
+  td_entity->initialize_group_sequence_list(attribOwnerEntity);
+  
+    // ok, now write the data for the groups to this attribute
+  for(i = ref_group_list.size(); i > 0; i--)
+  {
+      // get the refgroup which gets assigned to this CAGroup
+    ref_group = ref_group_list.get_and_step();
+
+      // First, make sure there's a TDCAGE on the RefGroup
+    ToolData *td_temp = ref_group->get_TD(&TDCAGE::is_cage);
+    TDCAGE *td_cagroup = (td_temp ? CAST_TO(td_temp, TDCAGE) : NULL);
+    if (td_cagroup == NULL) {
+#if defined NT || defined _NT || defined CUBIT_LINUX
+      td_cagroup = new TDCAGE(rand());
+#else
+      td_cagroup = new TDCAGE((int)lrand48());
+#endif
+      ref_group->add_TD(td_cagroup);
+      td_cagroup->initialize_group_sequence_list(ref_group);
+    }
+    
+      // append to this CAGroup the id and the unique id of the group;
+      // also append the group name
+    groupID.append(ref_group->id());
+    uniqueID.append(td_cagroup->unique_id());
+    groupNames.append(new CubitString(ref_group->entity_name()));
+
+      // get and append the sequence number of the attribOwnerEntity
+      // in this group
+    int seq_number = td_entity->td_sequence_number(ref_group);
+    assert(seq_number != -1);
+    sequenceNumbers.append(seq_number);
+
+      // check this group for containing (parent) groups
+    DLIList<RefGroup*> parent_ref_group_list;
+    RefGroup::get_groups_within(ref_group, parent_ref_group_list, CUBIT_FALSE);
+
+      // append the number of parent groups to the right list
+    numOwningGroups.append(parent_ref_group_list.size());
+    
+      // for each parent group, do essentially the same thing, adding the
+      // data to the owningGroup lists
+    for(int j = parent_ref_group_list.size(); j>0; j--)
+    {
+      parent_ref_group = parent_ref_group_list.get_and_step();
+      td_temp = parent_ref_group->get_TD(&TDCAGE::is_cage);
+      TDCAGE *td_parent = (td_temp ? CAST_TO(td_temp, TDCAGE) : NULL);
+      if (td_parent == NULL) {
+#if defined NT || defined _NT || defined CUBIT_LINUX
+        td_parent = new TDCAGE(rand());
+#else
+        td_parent = new TDCAGE((int)lrand48());
+#endif
+        parent_ref_group->add_TD(td_parent);
+        td_parent->initialize_group_sequence_list(parent_ref_group);
+      }
+
+        // append to this CAGroup the id and the unique id of the group;
+        // also append the group name
+      owningGroupID.append(parent_ref_group->id());
+      owningUniqueID.append(td_parent->unique_id());
+      owningGroupNames.append(new CubitString(parent_ref_group->entity_name()));
+
+        // get and append the sequence number of the group in the parent
+        // group
+      seq_number = td_cagroup->td_sequence_number(parent_ref_group);
+      assert(seq_number != -1);
+      owningSequenceNumbers.append(seq_number);
+
+        // finally, build a list of distant ancestors, in case there are
+        // groups more than twice removed from any real entities; make
+        // it a recursive function, so that it goes all the way up the chain
+        // of ancestors
+      build_ancestor_list(parent_ref_group);
+
+    } // loop over parent groups
+  } // loop over groups containing attribOwnerEntity
+
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus CAGroup::reset()
+{
+  groupID.clean_out();
+    //- group ids containing attribOwnerEntity
+  
+  uniqueID.clean_out();
+    //- unique ids of groups containing attribOwnerEntity
+
+  int i;
+  for (i = groupNames.size(); i > 0; i--)
+    delete groupNames.get_and_step();
+  groupNames.clean_out();
+    //- names of groups containing attribOwnerEntity
+
+  sequenceNumbers.clean_out();
+    //- sequence numbers of this entity in the groups
+
+  numOwningGroups.clean_out();
+    //- for each group in groupID, number of groups owning those groups
+
+  owningGroupID.clean_out();
+    //- group ids containing groups containing attribOwnerEntity
+  
+  owningUniqueID.clean_out();
+    //- unique ids of groups containing groups containing attribOwnerEntity
+
+  for (i = owningGroupNames.size(); i > 0; i--)
+    delete owningGroupNames.get_and_step();
+  owningGroupNames.clean_out();
+    //- names of groups containing groups containing attribOwnerEntity
+
+  owningSequenceNumbers.clean_out();
+    //- sequence numbers of groups in owning groups
+  
+    //- for each ancestor (a group which owns only other groups, with those
+    //- those groups owning only other groups), we store the group id, uid,
+    //- name, and the uid of the owned group to which this is an ancestor
+  ancestorGroupID.clean_out();
+  ancestorUniqueID.clean_out();
+  for (i = ancestorGroupName.size(); i > 0; i--)
+    delete ancestorGroupName.get_and_step();
+  ancestorGroupName.clean_out();
+  ancestorOwnedGroupUid.clean_out();
+  ancestorSequenceNumbers.clean_out();
+  
+  return CUBIT_SUCCESS;
+}
+
+void CAGroup::build_ancestor_list(RefGroup *parent_ref_group)
+{
+  DLIList<RefGroup*> ancestor_ref_group_list;
+  RefGroup::get_groups_within(parent_ref_group, ancestor_ref_group_list, CUBIT_FALSE);
+
+    // now, recursively work on ancestor list, adding owning group id,
+    // uid and name, and owned group uid, to lists
+  ToolData *td_temp = parent_ref_group->get_TD(&TDCAGE::is_cage);
+  TDCAGE *td_parent = (td_temp ? CAST_TO(td_temp, TDCAGE) : NULL);
+
+  for (int j = ancestor_ref_group_list.size(); j > 0; j--) {
+    RefGroup *ancestor = ancestor_ref_group_list.get_and_step();
+    td_temp = ancestor->get_TD(&TDCAGE::is_cage);
+    TDCAGE *td_cagroup = (td_temp ? CAST_TO(td_temp, TDCAGE) : NULL);
+    if (td_cagroup == NULL) {
+#if defined NT || defined _NT || defined CUBIT_LINUX
+      td_cagroup = new TDCAGE(rand());
+#else
+      td_cagroup = new TDCAGE((int)lrand48());
+#endif
+      ancestor->add_TD(td_cagroup);
+      td_cagroup->initialize_group_sequence_list(ancestor);
+    }
+
+    ancestorGroupID.append(ancestor->id());
+    ancestorUniqueID.append(td_cagroup->unique_id());
+    ancestorGroupName.append(new CubitString(ancestor->entity_name()));
+    ancestorOwnedGroupUid.append(td_parent->unique_id());
+    
+      // get and append the sequence number of the group in the parent
+      // group
+    int seq_number = td_parent->td_sequence_number(ancestor);
+    assert(seq_number != -1);
+    ancestorSequenceNumbers.append(seq_number);
+
+    build_ancestor_list(ancestor);
+  }
+}
+      
+CubitSimpleAttrib* CAGroup::cubit_simple_attrib()
+{
+  DLIList<CubitString*> cs_list;
+  DLIList<double> d_list;
+  DLIList<int> i_list;
+
+    // first, the ints
+    // groupID
+  groupID.reset();
+  i_list.append(groupID.size());
+  int i;
+  for (i = groupID.size(); i > 0; i--)
+    i_list.append(groupID.get_and_step());
+    
+    // uniqueID
+  uniqueID.reset();
+  for (i = uniqueID.size(); i > 0; i--)
+    i_list.append(uniqueID.get_and_step());
+    
+    // sequenceNumbers
+  sequenceNumbers.reset();
+  for (i = sequenceNumbers.size(); i > 0; i--)
+    i_list.append(sequenceNumbers.get_and_step());
+    
+    // numOwningGroups
+  numOwningGroups.reset();
+  for (i = numOwningGroups.size(); i > 0; i--)
+    i_list.append(numOwningGroups.get_and_step());
+
+    // size of owningGroupID
+  i_list.append(owningGroupID.size());
+  
+    // owningGroupID
+  owningGroupID.reset();
+  for (i = owningGroupID.size(); i > 0; i--)
+    i_list.append(owningGroupID.get_and_step());
+    
+    // owningUniqueID
+  owningUniqueID.reset();
+  for (i = owningUniqueID.size(); i > 0; i--)
+    i_list.append(owningUniqueID.get_and_step());
+    
+    // owningSequenceNumbers
+  owningSequenceNumbers.reset();
+  for (i = owningSequenceNumbers.size(); i > 0; i--)
+    i_list.append(owningSequenceNumbers.get_and_step());
+    
+    // size of ancestorGroupID
+  i_list.append(ancestorGroupID.size());
+  
+    // ancestorGroupID
+  ancestorGroupID.reset();
+  for (i = ancestorGroupID.size(); i > 0; i--)
+    i_list.append(ancestorGroupID.get_and_step());
+
+    // ancestorUniqueID
+  ancestorUniqueID.reset();
+  for (i = ancestorUniqueID.size(); i > 0; i--)
+    i_list.append(ancestorUniqueID.get_and_step());
+
+    // ancestorOwnedGroupUid
+  ancestorOwnedGroupUid.reset();
+  for (i = ancestorOwnedGroupUid.size(); i > 0; i--)
+    i_list.append(ancestorOwnedGroupUid.get_and_step());
+
+    // ancestorSequenceNumbers
+  ancestorSequenceNumbers.reset();
+  for (i = ancestorSequenceNumbers.size(); i > 0; i--)
+    i_list.append(ancestorSequenceNumbers.get_and_step());
+
+    // now, doubles (none)
+
+    // now, strings
+    // attribute internal name
+  cs_list.append(new CubitString(att_internal_name()));
+
+    // groupNames
+  groupNames.reset();
+  for (i = groupID.size(); i > 0; i--)
+    cs_list.append(new CubitString(*(groupNames.get_and_step())));
+
+    // owningGroupNames
+  owningGroupNames.reset();
+  for (i = owningGroupNames.size(); i > 0; i--)
+    cs_list.append(new CubitString(*(owningGroupNames.get_and_step())));
+
+    // ancestorGroupName
+  ancestorGroupName.reset();
+  for (i = ancestorGroupName.size(); i > 0; i--)
+    cs_list.append(new CubitString(*(ancestorGroupName.get_and_step())));
+
+  CubitSimpleAttrib* csattrib_ptr = new CubitSimpleAttrib(&cs_list,
+                                                          &d_list,
+                                                          &i_list);
+
+  for (i = cs_list.size(); i--; ) delete cs_list.get_and_step();
+  
+  return csattrib_ptr;
+}
+
+void CAGroup::has_written(CubitBoolean has_written)
+{
+    //- overloaded has_written function, resets td_cage on owner
+  if (has_written == CUBIT_TRUE && hasWritten == CUBIT_FALSE)
+      // reset the td_cage on the owner
+    attribOwnerEntity->delete_TD(&TDCAGE::is_cage);
+    
+  hasWritten = has_written;
+}
Index: /cgm/geom/RefEntityFactory.cpp
===================================================================
--- /cgm/geom/RefEntityFactory.cpp (revision 1040)
+++ /cgm/geom/RefEntityFactory.cpp (revision 1040)
@@ -0,0 +1,883 @@
+#include "RefEntityFactory.hpp"
+#include "RefVertex.hpp"
+#include "RefEdge.hpp"
+#include "RefFace.hpp"
+#include "RefVolume.hpp"
+#include "Body.hpp"
+#include "RefGroup.hpp"
+#include "GeometryQueryTool.hpp"
+#include "DLIList.hpp"
+
+RefEntityFactory *RefEntityFactory::instance_ = NULL;
+
+RefEntityFactory::RefEntityFactory(RefEntityFactory *factory) 
+{
+  instance_ = factory;
+
+  if (factory == NULL) {
+    refVertexList = new DLIList<RefVertex*>();
+    refEdgeList = new DLIList<RefEdge*>();
+    refFaceList = new DLIList<RefFace*>();
+    refGroupList = new DLIList<RefGroup*>();
+    refVolumeList = new DLIList<RefVolume*>();
+    bodyList = new DLIList<Body*>();
+    register_static_observer(this);
+  }
+  else {
+    refVertexList = NULL;
+    refEdgeList = NULL;
+    refFaceList = NULL;
+    refGroupList = NULL;
+    refVolumeList = NULL;
+    bodyList = NULL;
+  }
+  
+  reset_ids();
+}
+
+RefEntityFactory::~RefEntityFactory()
+{
+  if (refVertexList != NULL) delete refVertexList;
+  if (refEdgeList != NULL) delete refEdgeList;
+  if (refFaceList != NULL) delete refFaceList;
+  if (refGroupList != NULL) delete refGroupList;
+  if (refVolumeList != NULL) delete refVolumeList;
+  if (bodyList != NULL) delete bodyList;
+  unregister_static_observer(this);
+  instance_ = NULL;
+}
+
+RefVertex *RefEntityFactory::construct_RefVertex(Point *point)
+{
+  RefVertex *temp = new RefVertex(point);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+RefEdge *RefEntityFactory::construct_RefEdge(Curve *curve)
+{
+  RefEdge *temp = new RefEdge(curve);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+RefFace *RefEntityFactory::construct_RefFace(Surface *surface)
+{
+  RefFace *temp = new RefFace(surface);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+RefVolume *RefEntityFactory::construct_RefVolume(Lump *lump)
+{
+  RefVolume *temp = new RefVolume(lump);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+Body *RefEntityFactory::construct_Body(BodySM *body_sm)
+{
+  Body *temp = new Body(body_sm);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+RefGroup *RefEntityFactory::construct_RefGroup(const char* name)
+{
+  RefGroup *temp = new RefGroup(name);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+RefGroup *RefEntityFactory::construct_RefGroup (DLIList<RefEntity*>& entity_list)
+{
+  RefGroup *temp = new RefGroup(entity_list);
+  CubitObserver::notify_static_observers( temp, MODEL_ENTITY_CONSTRUCTED );
+  return temp;
+}
+
+CubitStatus RefEntityFactory::ref_entity_list( char const* keyword,
+                                               DLIList<RefEntity*> &entity_list,
+                                               const CubitBoolean print_errors )
+{
+   if ( !strcmp( keyword, "body" ) || !strcmp( keyword, "Body" )) {
+     CAST_LIST_TO_PARENT((*bodyList), entity_list) ;
+   }
+   else if ( !strcmp( keyword, "curve" ) || !strcmp( keyword, "Curve" ) ) {
+     CAST_LIST_TO_PARENT((*refEdgeList), entity_list) ;
+   }
+   else if ( !strcmp( keyword, "volume" ) || !strcmp( keyword, "Volume" ) ) {
+     CAST_LIST_TO_PARENT((*refVolumeList), entity_list) ; 
+   }
+   else if ( !strcmp( keyword, "vertex" ) || !strcmp( keyword, "Vertex" ) ) {
+     CAST_LIST_TO_PARENT((*refVertexList), entity_list) ;
+   }
+   else if ( !strcmp( keyword, "surface" ) || !strcmp( keyword, "Surface" ) ) {
+     CAST_LIST_TO_PARENT((*refFaceList), entity_list) ; 
+   }
+   else if ( !strcmp( keyword, "group" ) || !strcmp( keyword, "Group" ) ) {
+     CAST_LIST_TO_PARENT((*refGroupList), entity_list) ;
+   }
+   else 
+   {
+     if (print_errors)
+       PRINT_ERROR("Invalid list type for the ref_entity_list "
+                   "function: %s\n", keyword);
+     return CUBIT_FAILURE;
+   }
+
+   return CUBIT_SUCCESS;
+}
+
+void RefEntityFactory::add(RefEntity* ref_entity)
+{
+  assert(ref_entity != 0);
+  
+  RefGroup *group;
+  RefVolume *volume;
+  RefFace *face;
+  RefEdge *edge;
+  RefVertex *vertex;
+  Body *body;
+
+  if ( (group = CAST_TO(ref_entity, RefGroup)) != NULL ) {
+    add(group);
+  }
+  else if ( (volume = CAST_TO(ref_entity, RefVolume)) != NULL ) {
+    add(volume);
+  }
+  else if ( (face = CAST_TO(ref_entity, RefFace)) != NULL ) {
+    add(face);
+  }
+  else if ( (edge = CAST_TO(ref_entity, RefEdge)) != NULL ) {
+    add(edge);
+  }
+  else if ( (vertex = CAST_TO(ref_entity, RefVertex)) != NULL ) {
+    add(vertex);
+  }
+  else if ( (body = CAST_TO(ref_entity, Body)) != NULL ) {
+    add(body);
+  }
+}
+
+void RefEntityFactory::add(RefGroup* refGPtr)
+{
+   assert(!refGroupList->is_in_list(refGPtr));
+   refGroupList->append(refGPtr);
+   if (refGPtr->id() > maxRefGroupId) maxRefGroupId = refGPtr->id();
+}
+
+void RefEntityFactory::add(Body* bodyPtr)
+{
+   assert(!bodyList->is_in_list(bodyPtr));
+   bodyList->append(bodyPtr);
+   if (bodyPtr->id() > maxBodyId) maxBodyId = bodyPtr->id();
+}
+
+void RefEntityFactory::add(RefVolume* refVPtr)
+{
+   assert(!refVolumeList->is_in_list(refVPtr));
+   refVolumeList->append(refVPtr);
+   if (refVPtr->id() > maxRefVolumeId)
+       maxRefVolumeId = refVPtr->id();
+}
+
+void RefEntityFactory::add(RefFace* refFPtr)
+{
+   assert(!refFaceList->is_in_list(refFPtr));
+   refFaceList->append(refFPtr);
+   if (refFPtr->entityId > maxRefFaceId)
+       maxRefFaceId = refFPtr->entityId;
+}
+
+void RefEntityFactory::add(RefEdge* refEPtr)
+{
+   assert(!refEdgeList->is_in_list(refEPtr));
+   refEdgeList->append(refEPtr);
+   if (refEPtr->id() > maxRefEdgeId)
+       maxRefEdgeId = refEPtr->id();
+}
+
+void RefEntityFactory::add(RefVertex* refVPtr)
+{
+   assert(!refVertexList->is_in_list(refVPtr));
+   refVertexList->append(refVPtr);
+   if (refVPtr->id() > maxRefVertexId)
+       maxRefVertexId = refVPtr->id();
+}
+
+
+void RefEntityFactory::remove(RefEntity* ref_entity)
+{
+  assert(ref_entity != 0);
+  
+  RefGroup *group;
+  RefVolume *volume;
+  RefFace *face;
+  RefEdge *edge;
+  RefVertex *vertex;
+  Body *body;
+
+  if ( (group = CAST_TO(ref_entity, RefGroup)) != NULL ) {
+    remove(group);
+  }
+  else if ( (volume = CAST_TO(ref_entity, RefVolume)) != NULL ) {
+    remove(volume);
+  }
+  else if ( (face = CAST_TO(ref_entity, RefFace)) != NULL ) {
+    remove(face);
+  }
+  else if ( (edge = CAST_TO(ref_entity, RefEdge)) != NULL ) {
+    remove(edge);
+  }
+  else if ( (vertex = CAST_TO(ref_entity, RefVertex)) != NULL ) {
+    remove(vertex);
+  }
+  else if ( (body = CAST_TO(ref_entity, Body)) != NULL ) {
+    remove(body);
+  }
+}
+
+void RefEntityFactory::remove (RefVertex *ref_vertex_ptr)
+{
+  if (!refVertexList) return;
+  
+   if (ref_vertex_ptr != NULL)
+   {
+      if (refVertexList->move_to ( ref_vertex_ptr )) 
+          refVertexList->remove ();
+      else assert(0);
+   }
+}
+
+void RefEntityFactory::remove (RefEdge *ref_edge_ptr)
+{
+  if (!refEdgeList) return;
+
+   if (ref_edge_ptr != NULL)
+   {
+      if (refEdgeList->move_to ( ref_edge_ptr ))
+          refEdgeList->remove ();
+      else assert(0);
+   }
+}
+
+void RefEntityFactory::remove (RefFace *ref_face_ptr)
+{
+  if (!refFaceList) return;
+
+   if (ref_face_ptr != NULL)
+   {
+      if (refFaceList->move_to ( ref_face_ptr ))
+          refFaceList->remove ();
+      else assert(0);
+   }
+}
+
+void RefEntityFactory::remove (RefVolume *ref_volume_ptr)
+{
+  if (!refVolumeList) return;
+
+  if (ref_volume_ptr != NULL)
+   {
+      if (refVolumeList->move_to ( ref_volume_ptr ))
+          refVolumeList->remove ();
+      else assert(0);
+   }
+}
+
+void RefEntityFactory::remove (RefGroup *ref_group_ptr)
+{
+  if (!refGroupList) return;
+
+  if (ref_group_ptr != NULL)
+  {
+    if (refGroupList->move_to ( ref_group_ptr ))
+      refGroupList->remove ();
+    else assert(0);
+  }
+}
+
+void RefEntityFactory::remove (Body *body_ptr)
+{
+  if (!bodyList) return;
+
+  if (body_ptr != NULL)
+  {
+    if (bodyList->move_to ( body_ptr ))
+      bodyList->remove ();
+    else assert(0);
+  }
+}
+
+void RefEntityFactory::bodies(DLIList<Body*> &bodies) 
+{
+  bodies = *bodyList;
+}
+
+void RefEntityFactory::ref_volumes(DLIList<RefVolume*> &ref_volumes)
+{
+  ref_volumes = *refVolumeList;
+}
+
+void RefEntityFactory::ref_groups(DLIList<RefGroup*> &ref_groups)
+{
+  ref_groups = *refGroupList;
+}
+
+void RefEntityFactory::ref_faces(DLIList<RefFace*> &ref_faces)
+{
+  ref_faces = *refFaceList;
+}
+
+void RefEntityFactory::ref_edges(DLIList<RefEdge*> &ref_edges)
+{
+  ref_edges = *refEdgeList;
+}
+
+void RefEntityFactory::ref_vertices(DLIList<RefVertex*> &ref_vertices)
+{
+  ref_vertices = *refVertexList;
+}
+
+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();}
+int RefEntityFactory::num_ref_faces() const {return refFaceList->size();}
+int RefEntityFactory::num_ref_edges() const {return refEdgeList->size();}
+int RefEntityFactory::num_ref_vertices() const {return refVertexList->size();}
+
+RefEntity* RefEntityFactory::get_ref_entity(const char *type_string, int id)
+{
+     // Call the right function, cast it.
+  switch( toupper(*type_string) )
+  {
+    case 'B':
+      if( !strcmp(type_string+1,"ody") )
+        return get_body(id);
+      break;
+    case 'V':
+      if( !strcmp(type_string+1,"olume" ) )
+        return get_ref_volume(id);
+      else if(!strcmp(type_string+1,"ertex") )
+        return get_ref_vertex(id);
+      break;
+    case 'S':
+      if( !strcmp(type_string+1,"urface") )
+        return get_ref_face(id);
+      break;
+    case 'C':
+      if( !strcmp(type_string+1,"urve") )
+        return get_ref_edge(id);
+      break;
+    case 'G':
+      if( !strcmp(type_string+1,"roup") )
+        return get_ref_group(id);
+      break;
+  }   
+
+  PRINT_ERROR("Invalid list type for the get_ref_entity "
+              "function: %s\n", type_string);
+  return NULL;
+}
+//_________  Add Code by DZ of Cat,  3/17/99 11:24:22 AM  _________
+RefEntity* RefEntityFactory::get_ref_entity (const type_info& type, int id)
+{
+   // Call the right function, cast it.
+  if( type == typeid(RefGroup) )
+     return CAST_TO(get_ref_group(id), RefEntity);
+  else if( type == typeid(Body) )
+     return CAST_TO(get_body(id), RefEntity);
+  else if( type == typeid(RefVolume) )
+     return CAST_TO(get_ref_volume(id), RefEntity);
+  else if( type == typeid(RefFace) )
+     return CAST_TO(get_ref_face(id), RefEntity);
+  else if( type == typeid(RefEdge) )
+     return CAST_TO(get_ref_edge(id), RefEntity);
+  else if( type == typeid(RefVertex) )
+     return CAST_TO(get_ref_vertex(id), RefEntity);
+      
+   return NULL;
+}
+//_________  Code End by DZ of Cat,  3/17/99 11:24:22 AM  _________
+
+Body* RefEntityFactory::get_body (int id)
+{
+   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--; )
+   {
+      body_ptr = bodyList->get_and_step();
+      if (body_ptr->id() == id)
+          return body_ptr ;
+   }
+   return NULL ;
+}
+
+RefGroup* RefEntityFactory::get_ref_group   (int id)
+{
+   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--; )
+   {
+      ref_group_ptr = refGroupList->get_and_step();
+      if (ref_group_ptr->id() == id)
+          return ref_group_ptr ;
+   }
+   return NULL ;
+}
+
+RefVolume* RefEntityFactory::get_ref_volume (int id) 
+{
+   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--; )
+   {
+      ref_volume_ptr = refVolumeList->get_and_step() ;
+      if (ref_volume_ptr->id() == id)
+          return ref_volume_ptr ;
+   }
+   return NULL ;
+}
+
+RefFace* RefEntityFactory::get_ref_face (int id) 
+{
+   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--; )
+   {
+      ref_face_ptr = refFaceList->get_and_step() ;
+      if (ref_face_ptr->id() == id)
+          return ref_face_ptr ;
+   }
+   return NULL ;
+}
+
+RefEdge* RefEntityFactory::get_ref_edge (int id) 
+{
+   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--; )
+   {
+      ref_edge_ptr = refEdgeList->get_and_step() ;
+      if (ref_edge_ptr->id() == id)
+          return ref_edge_ptr ;
+   }
+   return NULL ;
+}
+
+RefVertex* RefEntityFactory::get_ref_vertex (int id) 
+{
+   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--; )
+   {
+      ref_vertex_ptr = refVertexList->get_and_step() ;
+      if (ref_vertex_ptr->id() == id)
+          return ref_vertex_ptr ;
+   }
+   return NULL ;
+}
+
+//* Methods: next*Id
+//** Increments the maximum object ID and returns this value.
+//==
+int RefEntityFactory::next_body_id () 
+{
+   return ++maxBodyId;
+}
+
+int RefEntityFactory::next_ref_group_id () 
+{
+   return ++maxRefGroupId;
+}
+
+int RefEntityFactory::next_ref_volume_id    () 
+{
+   return ++maxRefVolumeId;
+}
+
+int RefEntityFactory::next_ref_face_id () 
+{
+   return ++maxRefFaceId;
+}
+
+int RefEntityFactory::next_ref_edge_id () 
+{
+   return ++maxRefEdgeId;
+}
+
+int RefEntityFactory::next_ref_vertex_id () 
+{
+   return ++maxRefVertexId;
+}
+
+Body *RefEntityFactory::get_first_body()
+{
+	bodyList->reset(); 
+	return bodyList->size() ? bodyList->get() : 0;
+}
+
+RefVolume *RefEntityFactory::get_first_ref_volume()
+{
+	refVolumeList->reset(); 
+	return refVolumeList->size() ? refVolumeList->get() : 0;
+}
+
+RefGroup *RefEntityFactory::get_first_ref_group()
+{
+	refGroupList->reset(); 
+	return refGroupList->size() ? refGroupList->get() : 0;
+}
+
+RefFace *RefEntityFactory::get_first_ref_face()
+{
+	refFaceList->reset(); 
+	return refFaceList->size() ? refFaceList->get() : 0;
+}
+
+RefEdge *RefEntityFactory::get_first_ref_edge()
+{
+	refEdgeList->reset(); 
+	return refEdgeList->size() ? refEdgeList->get() : 0;
+}
+
+RefVertex *RefEntityFactory::get_first_ref_vertex()
+{
+	refVertexList->reset(); 
+	return refVertexList->size() ? refVertexList->get() : 0;
+}
+
+        
+Body *RefEntityFactory::get_next_body()
+{return bodyList->size() ? bodyList->step_and_get() : 0;}
+
+RefVolume *RefEntityFactory::get_next_ref_volume()
+{return refVolumeList->size() ? refVolumeList->step_and_get() : 0;}
+
+RefGroup *RefEntityFactory::get_next_ref_group()
+{return refGroupList->size() ? refGroupList->step_and_get() : 0;}
+
+RefFace *RefEntityFactory::get_next_ref_face()
+{return refFaceList->size() ? refFaceList->step_and_get() : 0;}
+
+RefEdge *RefEntityFactory::get_next_ref_edge()
+{return refEdgeList->size() ? refEdgeList->step_and_get() : 0;}
+
+RefVertex *RefEntityFactory::get_next_ref_vertex()
+{return refVertexList->size() ? refVertexList->step_and_get() : 0;}
+
+Body *RefEntityFactory::get_last_body()
+{
+	bodyList->last(); 
+	return bodyList->size() ? bodyList->get() : 0;
+}
+
+RefVolume *RefEntityFactory::get_last_ref_volume()
+{
+	refVolumeList->last(); 
+	return refVolumeList->size() ? refVolumeList->get() : 0;
+}
+
+RefGroup *RefEntityFactory::get_last_ref_group()
+{
+	refGroupList->last(); 
+	return refGroupList->size() ? refGroupList->get() : 0;
+}
+
+RefFace *RefEntityFactory::get_last_ref_face()
+{
+	refFaceList->last(); 
+	return refFaceList->size() ? refFaceList->get() : 0;
+}
+
+RefEdge *RefEntityFactory::get_last_ref_edge()
+{
+	refEdgeList->last(); 
+	return refEdgeList->size() ? refEdgeList->get() : 0;
+}
+
+RefVertex *RefEntityFactory::get_last_ref_vertex()
+{
+	refVertexList->last(); 
+	return refVertexList->size() ? refVertexList->get() : 0;
+}
+
+void RefEntityFactory::incorporate_id (RefEntity *ref_ent)
+{
+  if (ref_ent)
+  {
+//________  Change Code by DZ of Cat,  3/17/99 10:47:39 AM  ________
+     int max_ent_id = 0;
+
+     max_ent_id = ref_ent->id();
+        // Do nothing with groups
+     if( CAST_TO( ref_ent, RefGroup ) ) {
+       if (maxRefGroupId < max_ent_id)
+         maxRefGroupId = max_ent_id;
+     }
+     else if( CAST_TO( ref_ent, Body ) )
+     {
+       if (maxBodyId < max_ent_id)
+          maxBodyId = max_ent_id;
+     }
+     else if( CAST_TO( ref_ent, RefVolume ) )
+     {
+       if (maxRefVolumeId < max_ent_id)
+          maxRefVolumeId = max_ent_id;
+     }
+     else if( CAST_TO( ref_ent, RefFace ) )
+     {
+       if (maxRefFaceId < max_ent_id)
+          maxRefFaceId = max_ent_id;
+     }
+     else if( CAST_TO( ref_ent, RefEdge ) )
+     {
+       if (maxRefEdgeId < max_ent_id)
+          maxRefEdgeId = max_ent_id;
+     }
+     else if( CAST_TO( ref_ent, RefVertex ) )
+     {
+       if (maxRefVertexId < max_ent_id)
+          maxRefVertexId = max_ent_id;
+     }
+//________  Change End by DZ of Cat,  3/17/99 10:47:39 AM  ________
+  }
+}
+
+int RefEntityFactory::maximum_id(const char *entity_type)
+{
+   if (strcmp("body", entity_type) == 0)
+       return maxBodyId;
+   else if (strcmp("curve", entity_type) == 0)
+       return maxRefEdgeId;
+   else if (strcmp("group", entity_type) == 0)
+       return maxRefGroupId;
+   else if (strcmp("volume", entity_type) == 0)
+       return maxRefVolumeId;
+   else if (strcmp("vertex", entity_type) == 0)
+       return maxRefVertexId;
+   else if (strcmp("surface", entity_type) == 0)
+       return maxRefFaceId;
+   else {
+      PRINT_ERROR("Unrecognized entity_type: '%s'\n", entity_type);
+      return 0;
+   }
+}
+
+void RefEntityFactory::maximum_id (const type_info& type, int max_id)
+{
+  if( type == typeid(RefGroup) )
+     maxRefGroupId = max_id;
+  else if( type == typeid(Body) )
+     maxBodyId = max_id;
+  else if( type == typeid(RefVolume) )
+     maxRefVolumeId = max_id;
+  else if( type == typeid(RefFace) )
+     maxRefFaceId = max_id;
+  else if( type == typeid(RefEdge) )
+     maxRefEdgeId = max_id;
+  else if( type == typeid(RefVertex) )
+     maxRefVertexId = max_id;
+}
+      
+int RefEntityFactory::maximum_id (RefEntity *ref_ent)
+{
+   if (!ref_ent)
+      return 0;
+   else if( CAST_TO( ref_ent, RefGroup ) )
+      return maxRefGroupId;
+   else if( CAST_TO( ref_ent, Body ) )
+      return maxBodyId;
+   else if( CAST_TO( ref_ent, RefVolume ) )
+      return maxRefVolumeId;
+   else if( CAST_TO( ref_ent, RefFace ) )
+      return maxRefFaceId;
+   else if( CAST_TO( ref_ent, RefEdge ) )
+      return maxRefEdgeId;
+   else if( CAST_TO( ref_ent, RefVertex ) )
+      return maxRefVertexId;
+   else
+      return 0;
+}
+
+void RefEntityFactory::compress_ref_ids(const char *entity_type, int retain_max_id)
+{
+  const type_info& type = RefEntity::get_entity_type_info(entity_type);
+  assert(type != typeid(InvalidEntity));
+  
+  /*
+#ifdef VIRTUAL_GEOMETRY_ENGINE_HPP
+  VirtualGeometryEngine::instance()->
+    hidden_entity_mngr.compress_hidden_ids(type);
+#endif
+  */
+/*  
+  DLIList<GeometryQueryEngine*> gqeList;
+  GeometryQueryTool::instance()->get_gqe_list(gqeList);//Get the gqeList from the GQT 
+  gqeList.reset();
+  int i;
+  for (i = 0; i < gqeList.size(); i++)//Step through the list and call compress_ids.
+  {                                   //The VGE is the only engine that will do work. 
+    gqeList.get_and_step()->compress_ids(type);
+  }
+*/
+
+  DLIList<CubitEntity*> list;
+  DLIList<RefEntity*> temp_list;
+  CubitStatus result = ref_entity_list(entity_type, temp_list, CUBIT_FALSE);
+  if (  result == CUBIT_SUCCESS ) {
+    CAST_LIST_TO_PARENT(temp_list, list);
+    compress_ids(list);
+  }
+  
+    // set the maximum entity id to the new max values.
+  if (!retain_max_id)
+  {
+        // must use the num_xxx() functions here, since we may have a derived factory!
+    if( type == typeid(RefGroup) )
+       maxRefGroupId = num_ref_groups();
+    else if( type == typeid(Body) )
+       maxBodyId = num_bodies();
+    else if( type == typeid(RefVolume) )
+       maxRefVolumeId = num_ref_volumes();
+    else if( type == typeid(RefFace) )
+       maxRefFaceId = num_ref_faces();
+    else if( type == typeid(RefEdge) )
+       maxRefEdgeId = num_ref_edges();
+    else if( type == typeid(RefVertex) )
+       maxRefVertexId = num_ref_vertices();
+  }
+}
+
+//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;
+  CubitEntity* entity;
+  
+  if (list.size())
+  {
+    list.reset();
+      // if these are ref volumes, recompute color
+    CubitBoolean set_color = CUBIT_FALSE;
+    if (CAST_TO(list.get(), RefVolume)) set_color = CUBIT_TRUE;
+
+    // sort list so ids of entities are ascending order
+    list.sort( sort_by_ascending_ids); 
+
+    for (int i=list.size(); i > 0; i--)
+    {
+      entity = list.get_and_step();
+      if (entity->id() != id){
+        entity->set_id(id);
+        if (set_color) {
+          entity->color(CUBIT_DEFAULT_COLOR);
+        }
+      }
+      id++;
+    }
+  }
+}
+
+void RefEntityFactory::reset_ids()
+{
+  maxBodyId           = 0;
+  maxRefVolumeId      = 0;
+  maxRefGroupId       = 0;
+  maxRefFaceId        = 0;
+  maxRefEdgeId        = 0;
+  maxRefVertexId      = 0;
+  maxSurfSubDomainId  = 0;
+  maxCurveSubDomainId = 0;
+  maxRefCoordSysId    = 0;
+}
+
+#if 0
+static int re_factory_sort_volumes(RefVolume*& /*a*/, RefVolume*& /*b*/)
+{
+    // This is currently not implemented.  When it is added to CGM,
+    // look at MRefEntityFactory to see what to do.
+  return 0;
+}
+#endif
+
+void RefEntityFactory::renumber_geometry_by_properties(CubitBoolean retain_max)
+{
+    // See MRefEntityFactory::renumber_geometry_by_properties.
+    // If you want this implemented, copy what was done there.
+  PRINT_ERROR("'Sort' option not supported.\n"
+              "       Compressing IDs without sorting.");
+  compress_ref_ids("group", retain_max);
+  compress_ref_ids("body", retain_max);
+  compress_ref_ids("volume", retain_max);
+  compress_ref_ids("surface", retain_max);
+  compress_ref_ids("curve", retain_max);
+  compress_ref_ids("vertex", retain_max);
+}
+
+CubitStatus RefEntityFactory::notify_observer(CubitObservable *observable,
+                                              const CubitEvent &observer_event,
+                                              CubitBoolean )
+{
+  RefEntity *entity = CAST_TO(observable, RefEntity);
+  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);
+
+  return CUBIT_SUCCESS;
+}
+
Index: /cgm/geom/ModelEntity.hpp
===================================================================
--- /cgm/geom/ModelEntity.hpp (revision 1040)
+++ /cgm/geom/ModelEntity.hpp (revision 1040)
@@ -0,0 +1,135 @@
+//-------------------------------------------------------------------------
+// Copyright Notice
+//
+// Copyright (c) 1996 
+// by Malcolm J. Panthaki, DBA, and the University of New Mexico.
+//-------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------
+// Filename      : ModelEntity.hpp
+//
+// Purpose       : This class serves as the pure abstract class of
+//                 all the Model-related classes. Each ModelEntity Object
+//		   can be considered a Node in the DAG.
+//
+// Special Notes : This is a pure virtual class to prevent instantiation.
+//
+// Creator       : Raikanta Sahu
+//
+// Creation Date : 10/15/96
+//
+// Owner         : Malcolm J. Panthaki
+//-------------------------------------------------------------------------
+
+#ifndef MODEL_ENTITY_HPP
+#define MODEL_ENTITY_HPP
+
+// ********** BEGIN STANDARD INCLUDES         **********
+// ********** END STANDARD INCLUDES           **********
+
+// ********** BEGIN MOTIF INCLUDES            **********
+// ********** END MOTIF INCLUDES              **********
+
+// ********** BEGIN OPEN INVENTOR INCLUDES    **********
+// ********** END OPEN INVENTOR INCLUDES      **********
+
+// ********** BEGIN ACIS INCLUDES             **********
+// ********** END ACIS INCLUDES               **********
+
+// ********** BEGIN CUBIT INCLUDES            **********
+
+#include "CubitDefines.h"
+#include "DagType.hpp"
+#include "CubitGeomConfigure.h"
+
+// ********** END CUBIT INCLUDES              **********
+
+// ********** BEGIN FORWARD DECLARATIONS      **********
+
+template <class X> class DLIList;
+
+// ********** END FORWARD DECLARATIONS        **********
+
+// ********** BEGIN MACRO DEFINITIONS         **********
+// ********** END MACRO DEFINITIONS           **********
+
+// ********** BEGIN ENUM DEFINITIONS          **********
+// ********** END ENUM DEFINITIONS            **********
+
+class CUBIT_GEOM_EXPORT ModelEntity
+{
+
+// ********** BEGIN FRIEND CLASS DECLARATIONS **********
+
+   friend class ModelQueryEngine ;
+   friend class GroupingEntity;
+// ********** END FRIEND CLASS DECLARATIONS   **********
+
+ public:
+
+   ModelEntity();
+      //- Default constructor
+
+   virtual ~ModelEntity();
+
+   virtual int get_children( DLIList<ModelEntity*>* list = 0 ) const = 0;
+   virtual int get_parents ( DLIList<ModelEntity*>* list = 0 ) const = 0;
+      //- Returns number of parents/children.  
+      //- If a list is passed, pointers to parents/children will
+      //- be appended to the passed list.
+      
+   virtual DagType dag_type() const = 0;
+      
+   void deactivated(CubitBoolean flag) ;
+   CubitBoolean deactivated() const ;
+      //- Get and set funtions for the deactivation flag.
+	
+   CubitStatus remove_from_DAG(CubitBoolean recursive_flag = CUBIT_FALSE);
+   void disconnect_from_DAG();
+   virtual CubitStatus remove_child_link( ModelEntity* child_ptr ) = 0;
+
+   virtual CubitStatus 
+    disconnect_all_children( DLIList<ModelEntity*>* children = 0 ) = 0;
+   virtual CubitStatus
+    disconnect_all_parents( DLIList<ModelEntity*>* parents = 0 ) = 0;
+
+protected:
+
+   virtual CubitBoolean query_append_parents( DLIList<ModelEntity*>& list ) = 0;
+   virtual CubitBoolean query_append_children(DLIList<ModelEntity*>& list ) = 0;
+   
+   cBit deactivatedStatus_ : 1;
+     //- The deactivated flag
+   
+   cBit encountered_ : 1;
+    // Indicates if it has already been found in 
+    // in a DAG query.  
+
+
+
+private:
+
+   ModelEntity const& operator=(ModelEntity const& aModEnt) ;
+   ModelEntity(const ModelEntity& aModEnt);
+    // These are declared here to prevent the compiler
+    // from generating default ones.  These have no implementation.
+
+} ;
+
+
+// ********** BEGIN INLINE FUNCTIONS          **********
+
+
+// ********** END INLINE FUNCTIONS            **********
+
+// ********** BEGIN FRIEND FUNCTIONS          **********
+// ********** END FRIEND FUNCTIONS            **********
+
+// ********** BEGIN EXTERN FUNCTIONS          **********
+// ********** END EXTERN FUNCTIONS            **********
+
+// ********** BEGIN HELPER CLASS DECLARATIONS **********
+// ********** END HELPER CLASS DECLARATIONS   **********
+
+#endif
+
Index: /cgm/geom/RefVolume.cpp
===================================================================
--- /cgm/geom/RefVolume.cpp (revision 1040)
+++ /cgm/geom/RefVolume.cpp (revision 1040)
@@ -0,0 +1,369 @@
+//-------------------------------------------------------------------------
+// Filename      : RefVolume.cpp
+//
+// Purpose       : This file contains the implementation of the class 
+//                 RefVolume. 
+//
+// Special Notes :
+//
+// Creator       : 
+//
+// Creation Date : 
+//
+// Owner         : 
+//-------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+#include "CubitDefines.h"
+#include "CubitMessage.hpp"
+#include "CubitBox.hpp"
+
+#include "Body.hpp"
+#include "RefVolume.hpp"
+#include "RefFace.hpp"
+#include "RefEdge.hpp"
+#include "RefVertex.hpp"
+#include "CoVolume.hpp"
+#include "Shell.hpp"
+
+// tools
+#include "RefEntityFactory.hpp"
+#include "GeometryQueryTool.hpp"
+
+// lists
+#include "DLIList.hpp"
+
+#include "Lump.hpp"
+
+//-------------------------------------------------------------------------
+// Purpose       : Constructor with a pointer to a Lump 
+//
+// Special Notes :
+//
+// Creator       : Xuchen Liu
+//
+// Creation Date : 07/11/96
+//-------------------------------------------------------------------------
+RefVolume::RefVolume(Lump* lumpPtr)
+{
+   // Set the GeometryEntity pointer
+   if (lumpPtr != NULL)
+   {
+      set_geometry_entity_ptr(lumpPtr) ;
+
+      // Commented-out code from Phil Tuchinsky for FUTURE meshing
+      //   from a surface mesh with no solid model.
+      //
+//    hasGeometry = CUBIT_TRUE;
+//
+      // initialize the surface mesh entity lists exactly once
+//    nodes_boundary  ( surfaceNodes );
+//    edges_inclusive ( surfaceEdges );
+//    faces_inclusive ( surfaceFaces );
+   }
+   else
+   {
+      PRINT_ERROR("In the RefVolume(Lump*) constructor\n");
+      PRINT_ERROR("       Input Lump pointer is NULL\n");
+      assert(CUBIT_FALSE);
+   }
+   
+   // Initialize the member data
+   initialize();
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : The destructor.
+//
+// Special Notes :
+//
+// Creator       : Raikanta Sahu
+//
+// Creation Date : 10/22/96
+//-------------------------------------------------------------------------
+RefVolume::~RefVolume()
+{
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Return a pointer to the Lump associated with a volume.
+//
+// Special Notes :
+//
+// Creator       : Xuechen Liu
+//
+// Creation Date : 08/02/96
+//-------------------------------------------------------------------------
+
+Lump* RefVolume::get_lump_ptr() 
+{
+  return CAST_TO(get_geometry_entity_ptr(), Lump);
+}
+
+Lump const* RefVolume::get_lump_ptr() const 
+{
+  return CAST_TO(get_geometry_entity_ptr(), Lump);
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Get parent Body
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 02/11/03
+//-------------------------------------------------------------------------
+Body* RefVolume::get_body_ptr()
+{
+  SenseEntity* co_volume_ptr = get_first_sense_entity_ptr();
+  
+  if (!co_volume_ptr                  // no covolume 
+    || co_volume_ptr->next_on_bte() ) // multiple covolumes )
+  {
+    PRINT_ERROR("%s:%d RefVolume %d has other than one parent CoVolume.\n"
+                "This is a BUG -- please report it.\n",
+                __FILE__, __LINE__, id() );
+    return 0;
+  }
+  
+  return dynamic_cast<Body*>(co_volume_ptr->get_grouping_entity_ptr());
+}
+
+int RefVolume::genus() 
+{
+  int i;
+  DLIList<RefFace*> faces;
+  ref_faces(faces);
+  int gs = 0;
+  for (i = faces.size(); i > 0; i--)
+    gs += faces.get_and_step()->genus();
+  
+  return 1 - (num_ref_vertices() - num_ref_edges() + faces.size() - gs)/2;
+}
+
+CubitVector RefVolume::center_point()
+{
+  return bounding_box().center();
+}
+
+int RefVolume::dimension() const
+{
+  return 3;
+}
+
+CubitStatus RefVolume::mass_properties( 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( centroid, volume );
+  }
+}
+
+CubitString RefVolume::measure_label()
+{
+  return "volume";
+}
+
+// Draws each surface in the volume
+/*
+void RefVolume::draw_my_faces ( int color )
+{
+   DLIList<RefFace*> ref_face_list;
+   int i;
+
+   if (color == CUBIT_DEFAULT_COLOR)
+      color = this->color();
+   ref_faces ( ref_face_list );
+   ref_face_list.reset();
+   for (i = 0; i < ref_face_list.size(); i++ )
+      ref_face_list.get_and_step()->draw(color);
+}
+*/
+
+//-------------------------------------------------------------------------
+// Purpose       : Initializes member data
+//
+// Special Notes :
+//
+// Creator       : Malcolm J. Panthaki
+//
+// Creation Date : 10/07/96
+//-------------------------------------------------------------------------
+void RefVolume::initialize()
+{
+   // Set the Entity and Block IDs for this new RefVolume
+   GeometryEntity* geom_ptr = get_geometry_entity_ptr();
+   int saved_id = geom_ptr->get_saved_id();
+   if ( !saved_id || RefEntityFactory::instance()->get_ref_volume(saved_id) )
+   {
+     saved_id =  RefEntityFactory::instance()->next_ref_volume_id();
+     geom_ptr->set_saved_id(saved_id);
+   }
+   entityId = saved_id;
+
+     // read and initialize attributes
+   auto_read_cubit_attrib();
+   auto_actuate_cubit_attrib();
+
+     // Assign a default entity name
+   assign_default_name();   
+}
+
+// unmark this face, and
+// recursively unmark all other marked faces sharing an edge with this face.
+void unmark_component( RefFace *face )
+{
+  assert( face->marked() );
+  face->marked( CUBIT_FALSE );
+  DLIList<RefEdge*> edges;
+  face->ref_edges( edges );
+  DLIList<RefFace*> edge_faces;
+  RefEdge *edge;
+  for ( int e = edges.size(); e--; ) 
+  {
+    edge = edges.get_and_step();
+    edge_faces.clean_out();
+    edge->ref_faces( edge_faces );
+    for ( int f = edge_faces.size(); f--; ) 
+    {
+      face = edge_faces.get_and_step();
+      if ( face->marked() )
+         unmark_component( face );
+    }
+  }
+}
+
+int RefVolume::num_boundary_components() 
+{
+  // get all the surfaces
+  // march from one to the next, using shared-ref_edge connectivity
+  
+  int num_components = 0;
+  DLIList<RefFace*> face_list;
+  ref_faces( face_list );
+
+  // mark them as belonging to this volume and not seen yet.
+  int i;
+  RefFace *face;
+  for( i = face_list.size(); i--; )
+  {
+    face = face_list.get_and_step();
+    face->marked( CUBIT_FALSE );
+  }
+  
+  for ( i = face_list.size(); i--; ) 
+  {
+    face = face_list.get_and_step();
+    assert( !face->marked() );
+    face->marked( CUBIT_TRUE );
+  }
+
+  for ( i = face_list.size(); i--; ) 
+  {
+    face = face_list.get_and_step();
+    if ( face->marked() ) 
+    {
+      num_components++;
+      unmark_component( face );      
+    }
+  }
+  return num_components;
+}
+
+CubitBoolean RefVolume::about_spatially_equal( 
+    RefVolume* ref_vol_ptr_2,double tolerance_factor)
+{
+     // Get rid of the trivial case...
+   if( this == ref_vol_ptr_2)
+   {
+      return CUBIT_TRUE;
+   }
+
+   DLIList<RefEdge*> ref_edge_list_1, ref_edge_list_2;
+   this->ref_edges( ref_edge_list_1 );
+   ref_vol_ptr_2->ref_edges( ref_edge_list_2 );
+      
+        //compare the size of the two lists.
+   if ( ref_edge_list_1.size() != ref_edge_list_2.size() )
+     return CUBIT_FALSE;
+      
+   DLIList<RefFace*> ref_face_list_1, ref_face_list_2;
+   this->ref_faces( ref_face_list_1 );
+   ref_vol_ptr_2->ref_faces( ref_face_list_2 );
+      
+        //compare the size of the two lists.
+   if ( ref_face_list_1.size() != ref_face_list_2.size() )
+     return CUBIT_FALSE;
+      
+   
+     //This compare precedure does the following :
+     //   1. Test the bounding boxes of the 2 volumes for equality;
+        
+   CubitBox box_1 = this->bounding_box();
+   CubitBox box_2 = ref_vol_ptr_2->bounding_box();
+
+   CubitBoolean passes_b_box = CUBIT_FALSE;
+
+       // This test checks to see that the min and max vectors of the
+       // bounding boxes are within 10% of the length of the bbox diagonal.
+       // Note that this assumes the default values of resabs=1e-6 and
+       // tolerance_factor=500
+
+   CubitVector tol_vect(
+      CUBIT_MIN(box_1.x_range(), box_2.x_range()),
+      CUBIT_MIN(box_1.y_range(), box_2.y_range()),
+      CUBIT_MIN(box_1.z_range(), box_2.z_range()) );
+   tol_vect *= 200.0 * tolerance_factor * GEOMETRY_RESABS;
+   if( tol_vect.x() < GEOMETRY_RESABS )
+      tol_vect.x(GEOMETRY_RESABS);
+   if( tol_vect.y() < GEOMETRY_RESABS )
+      tol_vect.y(GEOMETRY_RESABS);
+   if( tol_vect.z() < GEOMETRY_RESABS )
+      tol_vect.z(GEOMETRY_RESABS);
+   
+   if((fabs(box_1.minimum().x() - box_2.minimum().x()) < tol_vect.x()) &&
+      (fabs(box_1.maximum().x() - box_2.maximum().x()) < tol_vect.x()) &&
+      (fabs(box_1.minimum().y() - box_2.minimum().y()) < tol_vect.y()) &&
+      (fabs(box_1.maximum().y() - box_2.maximum().y()) < tol_vect.y()) &&
+      (fabs(box_1.minimum().z() - box_2.minimum().z()) < tol_vect.z()) &&
+      (fabs(box_1.maximum().z() - box_2.maximum().z()) < tol_vect.z())) 
+   {
+     passes_b_box = CUBIT_TRUE;
+   }
+   
+   return passes_b_box;
+}    
+
+//-------------------------------------------------------------------------
+// Purpose       : Check if all shells are sheets
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 01/15/04
+//-------------------------------------------------------------------------
+CubitBoolean RefVolume::is_sheet()
+{
+  DLIList<Shell*> shells;
+  this->shells(shells);
+  while (shells.size())
+    if (!shells.pop()->is_sheet())
+      return CUBIT_FALSE;
+  return CUBIT_TRUE;
+}
+  
Index: /cgm/geom/DagDrawingTool.cpp
===================================================================
--- /cgm/geom/DagDrawingTool.cpp (revision 1040)
+++ /cgm/geom/DagDrawingTool.cpp (revision 1040)
@@ -0,0 +1,815 @@
+
+
+#include "DagDrawingTool.hpp"
+#include "RefFace.hpp"
+#include "RefEdge.hpp"
+#include "RefVertex.hpp"
+#include "RefVolume.hpp"
+#include "Body.hpp"
+#include "DLIList.hpp"
+#include "CubitColorConstants.hpp"
+#include "SenseEntity.hpp"
+#include "CastTo.hpp"
+#include "CoVertex.hpp"
+#include "Chain.hpp"
+#include "CoEdge.hpp"
+#include "Loop.hpp"
+#include "CoFace.hpp"
+#include "Shell.hpp"
+
+//constants:
+
+
+const char* const DDT_BODY_ABBREV    = "B";
+const char* const DDT_COVOL_ABBREV   = "CVm";
+const char* const DDT_REFVOL_ABBREV  = "Vm";
+const char* const DDT_SHELL_ABBREV   = "Sh";
+const char* const DDT_COFACE_ABBREV  = "CF";
+const char* const DDT_REFFACE_ABBREV = "F";
+const char* const DDT_LOOP_ABBREV    = "L";
+const char* const DDT_COEDGE_ABBREV  = "CE";
+const char* const DDT_REFEDGE_ABBREV = "E";
+const char* const DDT_CHAIN_ABBREV   = "Ch";
+const char* const DDT_COVTX_ABBREV   = "CVx";
+const char* const DDT_REFVTX_ABBREV  = "Vx";
+//Abbreviations used for type names.
+//Note: If abbreviations are not used, the
+// full type name is taken from 
+// CubitEntity::entity_name( EntityType ).
+
+
+//const CubitLink DDT_DEFAULT_TRAVERSE_TYPE = CUBIT_ALL_LINKS;
+
+DagDrawingTool* DagDrawingTool::instance_ = 0;
+
+//constats for query direction
+const int DDT_UP_DAG   =  1;
+const int DDT_DOWN_DAG = -1;
+
+//bit masks for link type
+const int DDT_LINK_NONE = 0;
+const int DDT_LINK_UP   = 1;
+const int DDT_LINK_DOWN = 2;
+const int DDT_LINK_BOTH = 3;
+const int DDT_BAD_LINK  = 4;
+
+DagDrawingTool::DagDrawingTool()
+{
+	node_table = 0;
+}
+
+void DagDrawingTool::one_sort_pass( int start, int end, float* val_list )
+{
+	int i, j, k;
+	DagNodeTable& table = *node_table;
+	//int row_count = table.rows();
+	int cur_row_len = 0;
+	if( start == end ) return;
+	int dir = (start < end) ? 1 : -1;
+	
+	//for each parent row of the passed row of nodes...
+	for( i = start; i != (end + dir); i += dir )
+	{
+		//populate the array with the values to sort by
+		cur_row_len = table[i].length();
+		for( j = 0; j < cur_row_len; j++ )
+		{
+			val_list[j] = 0.0;
+			int link_count = 0;
+			for( k = 0; k < table[i-dir].length(); k++ )
+			{
+				if( link_type( i, j, i - dir, k ) )
+				{
+					val_list[j] += (float)k;
+					link_count++;
+				}
+			}
+			if( link_count ) val_list[j] /= (float)link_count;
+		}		
+		
+		//sort the row by the values in value_list
+		for( j = 0; j < cur_row_len - 1; j++ )
+		{
+			int smallest = j;
+			for( k = j + 1; k < cur_row_len; k++ )
+			{
+				if( val_list[k] < val_list[smallest] )
+					smallest = k;
+			}
+			if( smallest != j )
+			{
+                                  //float temp = val_list[j];
+				val_list[j] = val_list[smallest];
+				val_list[smallest] = val_list[j];
+				
+				ModelEntity* node = table[i][j];
+				table[i][j] = table[i][smallest];
+				table[i][smallest] = node;
+			}
+		}
+	}
+	
+}	
+/*
+void DagDrawingTool::sort_table( )
+{
+	DagNodeTable& table = *node_table;
+	int passes = table.rows() - 1;
+	int i;
+	
+	int max_row_size = 0;
+	int row_count = table.rows();
+	for( i = 0; i < row_count; i++ )
+		if( table[i].length() > max_row_size )
+			max_row_size = table[i].length();
+	float* value_list = new float[max_row_size];
+
+	for( i = 0; i < passes; i++ )
+	{
+		one_sort_pass( 1, row_count - 1, value_list );
+		one_sort_pass( row_count - 2, 0, value_list );
+	}
+		
+	delete [] value_list;
+}
+*/ 
+
+void DagDrawingTool::sort_row( int row, int wrt_dir )
+{
+  assert((wrt_dir == 1) || (wrt_dir == -1));
+  
+  DagNodeTable& table = *node_table;
+  int row_len = table[row].length();
+  int rel_row = row + wrt_dir;
+  if( (row_len < 2) || (rel_row < 0) || (rel_row == table.rows()) )
+    return;
+  
+  int* index_array = new int[row_len];
+  int num_rels = table[rel_row].length();
+  int i, j, k, l, m;
+  
+  //Append first node to list
+  index_array[0] = 0;
+  
+  //For each remaining node, insert it in the location at which
+  //it causes the least intersections of links.
+  for( i = 1; i < row_len; i++ )
+  {
+    int best_index = 0;
+    int intersection_count = 0;
+    
+    //Get the intersection count if the node were inserted first
+    //in the row.
+
+    //For each possible parent node
+    for( k = 1; k < num_rels; k++ )
+    {
+      //Is it a parent?
+      if( ! link_type( row, i, rel_row, k ) )
+        continue;
+      
+      //Count how many other links that link intersects.
+      
+      //For all the other nodes in the list...
+      for( l = 0; l < i; l++ )
+      {
+        //For each parent to the left of my parent
+        for( m = 0; m < k; m++ )
+        {
+          if( link_type( row, index_array[l], rel_row, m ) )
+            intersection_count++;
+        }
+      }
+    }
+    
+    //Now check the intersection count for each additional
+    //possible location of insertion.       
+    for( j = 1; j <= i; j++ )
+    {
+      int current_count = 0;
+      
+      //For each possible parent node
+      for( k = 0; k < num_rels; k++ )
+      {
+        //Is it a parent?
+        if( ! link_type( row, i, rel_row, k ) )
+          continue;
+          
+        //Count how many other links from nodes to the
+        //left of me intersect with my link to this parent.
+        for( l = 0; l < j; l++ )  
+        {
+          //For each parent to the right of my parent
+          for( m = k+1; m < num_rels; m++ )
+          {
+            if( link_type( row, index_array[l], rel_row, m ) )
+              current_count++;
+          }
+        }
+        
+        //Count how many other links from nodes to the
+        //right of me intersect with my link to this parent.
+        for( l = j; l < i; l++ )
+        {
+          //For each parent to the left of my parent
+          for( m = 0; m < k; m++ )
+          {
+            if( link_type( row, index_array[l], rel_row, m ) )
+              current_count++;
+          }
+        }
+      }
+      
+      if( current_count <= intersection_count )
+      {
+        intersection_count = current_count;
+        best_index = j;
+      }
+    }
+    
+    //Now insert this node at the best location.
+    for( j = i; j > best_index; j-- )
+      index_array[j] = index_array[j-1];
+    index_array[best_index] = i;
+  }
+  
+  //Now rearrange the nodes in the actual row to match 
+  //what is stored in index_list
+  ModelEntity** node_array = new ModelEntity*[row_len];
+  for( i = 0; i < row_len; i++ )
+  {
+    node_array[i] = table[row][index_array[i]];
+  }
+  for( i = 0; i < row_len; i++ )
+  {
+    table[row][i] = node_array[i];
+  }
+  delete [] node_array;
+  delete [] index_array;
+}
+        
+        
+/*
+void DagDrawingTool::draw_table()
+{
+	int i, j, k;
+	DagNodeTable& table = *node_table;
+	for( i = 0; i < table.rows(); i++ )
+	{
+		int len = table[i].length();
+		for( j = 0; j < len; j++ )
+		{
+			draw_node( i, j );
+			if( i > 0 ) 
+			{
+				int len2 = table[i-1].length();
+				for( k = 0; k < len2; k++ ) draw_link( i, j, i - 1, k );
+			}
+      if( draw_host_para_links_ )
+      {
+        for( k = 0; k < j; k++ )
+          draw_host_link( i, k, j );
+		  }
+    }
+	}
+}
+
+
+void DagDrawingTool::draw_DAG( DLIList<ModelEntity*>& node_list, int up, int down )
+{
+	int i;
+	assert( (up >= 0) && (down >= 0) );
+	if( node_list.size() == 0 ) return;
+	
+	DLIList<ModelEntity*> relatives[2];
+	int num_rows = up + down + 1;
+	
+	assert( ! node_table );
+	node_table = new DagNodeTable( num_rows );
+	start_row = down;
+	node_table->initialize_row( start_row, node_list );
+	
+	relatives[ start_row % 2 ] = node_list;
+	for( i = start_row - 1; i >= 0; i-- )
+	{
+		relatives[i % 2].clean_out();
+		get_relatives( relatives[(i + 1) % 2], relatives[i % 2], DDT_DOWN_DAG );
+		node_table->initialize_row( i, relatives[i % 2] );
+	}
+	relatives[ start_row % 2 ] = node_list;
+	for( i = start_row + 1; i < num_rows; i++ )
+	{
+		relatives[i % 2].clean_out();
+		get_relatives( relatives[(i - 1) % 2], relatives[i % 2], DDT_UP_DAG );
+		node_table->initialize_row( i, relatives[i % 2] );
+	}
+	
+
+	sort_table();
+
+	initialize_graphics();
+	draw_table();
+	finalize_graphics();
+
+	delete node_table;
+	node_table = 0;
+}
+*/
+
+
+DagDrawingTool* DagDrawingTool::instance()
+{
+	return instance_ ? instance_ : instance_ = new DagDrawingTool();
+}
+
+DagDrawingTool::~DagDrawingTool()
+{
+	instance_ = 0;
+	assert( ! node_table );
+}
+
+/*
+void DagDrawingTool::draw_DAG( Body*      body,           int down ) 
+{
+  DLIList<RefEntity*> entity_list;
+  entity_list.append(body);
+  draw_DAG( entity_list, 0, down );
+}
+
+void DagDrawingTool::draw_DAG( RefVolume* volume, int up, int down )
+{
+  DLIList<RefEntity*> entity_list;
+  entity_list.append(volume);
+  draw_DAG( entity_list, up, down );
+}
+
+void DagDrawingTool::draw_DAG( RefFace*   face,   int up, int down )
+{
+  DLIList<RefEntity*> entity_list;
+  entity_list.append(face);
+  draw_DAG( entity_list, up, down );
+}
+
+void DagDrawingTool::draw_DAG( RefEdge*   edge,   int up, int down )
+{
+  DLIList<RefEntity*> entity_list;
+  entity_list.append(edge);
+  draw_DAG( entity_list, up, down );
+}
+
+void DagDrawingTool::draw_DAG( RefVertex* vertex, int up           )
+{
+  DLIList<RefEntity*> entity_list;
+  entity_list.append(vertex);
+  draw_DAG( entity_list, up, 0 );
+}
+
+void DagDrawingTool::draw_DAG( DLIList<RefEdge*>& edge_list, int up, int down )
+{
+	DLIList<RefEntity*> entity_list;
+	CAST_LIST_TO_PARENT( edge_list, entity_list );
+	draw_DAG( entity_list, up, down );
+}
+
+void DagDrawingTool::draw_DAG( DLIList<RefFace*>& face_list, int up, int down )
+{
+	DLIList<RefEntity*> entity_list;
+	CAST_LIST_TO_PARENT( face_list, entity_list );
+	draw_DAG( entity_list, up, down );
+}
+
+void DagDrawingTool::draw_DAG( DLIList<RefVertex*>& vtx_list, int up )
+{
+	DLIList<RefEntity*> entity_list;
+	CAST_LIST_TO_PARENT( vtx_list, entity_list );
+	draw_DAG( entity_list, up, 0 );
+}
+
+void DagDrawingTool::draw_DAG( DLIList<RefVolume*>& vol_list, int up, int down )
+{
+	DLIList<RefEntity*> entity_list;
+	CAST_LIST_TO_PARENT( vol_list, entity_list );
+	draw_DAG( entity_list, up, down );
+}
+
+void DagDrawingTool::draw_DAG( DLIList<Body*>& body_list, int down )
+{
+	DLIList<RefEntity*> entity_list;
+	CAST_LIST_TO_PARENT( body_list, entity_list );
+	draw_DAG( entity_list, 0, down );
+}
+
+void DagDrawingTool::draw_DAG( DLIList<RefEntity*>& entity_list, int up, int down )
+{
+	DLIList<ModelEntity*> node_list;
+	for( int i = entity_list.size(); i > 0; i-- )
+	{
+		RefEntity* re_ptr = entity_list.get_and_step();
+		ModelEntity* me_ptr = CAST_TO( re_ptr, ModelEntity);
+		node_list.append_unique( me_ptr );
+	}
+	draw_DAG( node_list, up, down );
+}
+*/
+
+
+/*
+void DagDrawingTool::draw_host_parasite_links( CubitBoolean yn )
+{ draw_host_para_links_ = yn; }
+CubitBoolean DagDrawingTool::draw_host_parasite_links() const
+{ return draw_host_para_links_; }
+void DagDrawingTool::primary_link_color( int color )
+{ prim_link_color_ = color; }
+void DagDrawingTool::secondary_link_color( int color )
+{ sec_link_color_ = color; }
+void DagDrawingTool::host_para_link_color( int color )
+{ host_para_color_ = color; }
+void DagDrawingTool::bad_link_color( int color )
+{ bad_link_color_ = color; }
+void DagDrawingTool::node_color( int color )
+{ node_color_ = color; }
+void DagDrawingTool::label_color( int color )
+{ label_color_ = color; }
+void DagDrawingTool::background_color( int color )
+{ background_color_ = color; }
+int DagDrawingTool::primary_link_color() const
+{ return prim_link_color_; }
+int DagDrawingTool::secondary_link_color() const
+{ return sec_link_color_; }
+int DagDrawingTool::host_para_link_color() const
+{ return host_para_color_; }
+int DagDrawingTool::bad_link_color() const
+{ return bad_link_color_; }
+int DagDrawingTool::node_color() const
+{ return node_color_; }
+int DagDrawingTool::label_color() const
+{ return label_color_; }
+int DagDrawingTool::background_color() const
+{ return background_color_; }
+	
+int DagDrawingTool::window_id() const
+{ return window_id_; }
+*/
+
+/*
+const char* DagDrawingTool::name( int row, int index )
+{
+	DagNodeTable& table = *node_table;
+	return name( table[row][index] );
+}
+*/
+/*
+int DagDrawingTool::name_width( int row )
+{
+	DagNodeTable& table = *(node_table);
+	ModelEntity* node_ptr = 0;
+	if( table[row].length() > 0 )
+		node_ptr = table[row][0];
+	return name_width( node_ptr );
+}
+*/
+	
+/*
+int DagDrawingTool::name_width( ModelEntity* node_ptr )
+{
+  if( node_ptr == NULL )
+     return 4;
+  else if( CAST_TO( node_ptr, Body ) ||
+           CAST_TO( node_ptr, RefVolume ) ||
+           CAST_TO( node_ptr, RefFace ) ||
+           CAST_TO( node_ptr, RefEdge ) ||
+           CAST_TO( node_ptr, RefVertex ) )
+  {
+    switch( ref_entity_label_type_ )
+    {
+      case DDT_LABEL_REFENTITY_WITH_NAME: 
+         return DDT_DEFAULT_NAME_LEN;
+      case DDT_LABEL_REFENTITY_WITH_TYPE: 
+         return DDT_DEFAULT_TYPE_LEN + DDT_DEFAULT_ID_LEN;
+      case DDT_LABEL_REFENTITY_WITH_ABBR: 
+         return DDT_DEFAULT_ABBREV_LEN + DDT_DEFAULT_ID_LEN - 1;
+      case DDT_LABEL_REFENTITY_WITH_ID: 
+         return DDT_DEFAULT_ID_LEN;
+      default: 
+         assert( ! ref_entity_label_type_ );
+    }
+  }
+	else
+  {
+    switch( other_entity_label_type_ )
+    {
+      case DDT_LABEL_OTHER_WITH_TYPE: return DDT_DEFAULT_TYPE_LEN;
+      case DDT_LABEL_OTHER_WITH_ABBR: return DDT_DEFAULT_ABBREV_LEN;
+      case DDT_LABEL_OTHER_NONE: return 1;
+      default: assert( ! other_entity_label_type_ );
+    }
+	}
+	
+	return 0;
+}
+*/
+/*
+const char* DagDrawingTool::name( ModelEntity* node_ptr )
+{
+	static char buffer[32];
+	
+	if( ! node_ptr )
+	{
+			strcpy( buffer, "NULL" );
+			return buffer;
+	}
+	
+	ModelEntity* entity_ptr = node_ptr;
+	if( ! entity_ptr )
+	{
+		strcpy( buffer, "NODE" );
+		return buffer;
+	}
+	
+	CubitString s;
+	RefEntity* re_ptr = CAST_TO( entity_ptr, RefEntity );
+	if( re_ptr )
+	{
+		switch( ref_entity_label_type_ )
+		{
+			case DDT_LABEL_REFENTITY_WITH_NAME:
+				s = re_ptr->entity_name();
+				strncpy( buffer, s.c_str(), 31 );
+				break;
+			case DDT_LABEL_REFENTITY_WITH_TYPE:
+				sprintf( buffer, "%0.24s %d",
+                                                 re_ptr->class_name(), re_ptr->id() );
+				break;
+			case DDT_LABEL_REFENTITY_WITH_ABBR:
+				sprintf( buffer, "%0.24s%d", short_name( re_ptr ), re_ptr->id() );
+				break;
+			case DDT_LABEL_REFENTITY_WITH_ID:
+				sprintf( buffer, "%d", re_ptr->id() );
+				break;
+			default: assert( ! ref_entity_label_type_ );
+		}
+	}
+	else
+	{
+		switch( other_entity_label_type_ )
+		{
+			case DDT_LABEL_OTHER_WITH_TYPE:
+				strncpy( buffer,  
+                 entity_ptr->class_name( ), 31 );
+				break;
+			case DDT_LABEL_OTHER_WITH_ABBR:
+				strncpy( buffer, short_name( entity_ptr ), 31 );
+				break;
+			case DDT_LABEL_OTHER_NONE:
+				buffer[0] = '\0';
+				break;
+			default: assert( ! other_entity_label_type_ );
+		}
+	}
+	return buffer;
+}
+*/
+
+
+
+void DagDrawingTool::get_relatives( ModelEntity* source_ptr,
+	DLIList<ModelEntity*>& result_set, int direction )
+{
+	result_set.clean_out();
+	if( direction == DDT_UP_DAG ) 
+		source_ptr->get_parents( &result_set );
+	else if( direction == DDT_DOWN_DAG )
+	  source_ptr->get_children( &result_set  );
+	else assert( (direction == DDT_UP_DAG) || (direction == DDT_DOWN_DAG) );
+}
+
+void DagDrawingTool::get_relatives( DLIList<ModelEntity*>& source_set,
+	DLIList<ModelEntity*>& result_set, int direction )
+{
+	DLIList<ModelEntity*> temp_set;
+	result_set.clean_out();
+	for( int i = 0; i < source_set.size();  i++ )
+	{
+		get_relatives( source_set.get_and_step(), temp_set, direction );
+		result_set.merge_unique( temp_set );
+	}
+}
+
+
+int DagDrawingTool::link_type( int source_row, int source_index, 
+                               int target_row, int target_index )
+{
+	DagNodeTable& table = *node_table;
+	if( abs( source_row - target_row ) != 1 ) return DDT_LINK_NONE;
+	return link_type( table[source_row][source_index], 
+	                  table[target_row][target_index], 
+										source_row < target_row ? DDT_UP_DAG : DDT_DOWN_DAG );
+}
+int DagDrawingTool::link_type( ModelEntity* source_node,
+	ModelEntity* target_node, int direction )
+{
+	int result = DDT_LINK_NONE;
+  DLIList<ModelEntity*> parents, children;
+	if( direction == DDT_UP_DAG )
+	{
+    source_node->get_parents(&parents);
+    target_node->get_children(&children);
+		bool down = parents.is_in_list(target_node);
+    bool up   = children.is_in_list(source_node);
+    if ( !down && !up )
+      result = DDT_LINK_NONE;
+    else if( down && up )
+      result = DDT_LINK_BOTH;
+    else
+      result = DDT_BAD_LINK;
+  }
+	else if( direction == DDT_DOWN_DAG )
+	{
+    source_node->get_children(&children);
+    target_node->get_parents(&parents);
+		bool up   = children.is_in_list(target_node);
+    bool down = parents.is_in_list(source_node);
+    if ( !down && !up )
+      result = DDT_LINK_NONE;
+    else if( down && up )
+      result = DDT_LINK_BOTH;
+    else
+      result = DDT_BAD_LINK;
+	}
+	return result;
+}
+
+
+
+DagNodeRow::DagNodeRow( DLIList<ModelEntity*>& node_list )
+{
+	length_ = node_list.size();
+	array_ = 0;
+	if( length_ > 0 )
+	{
+		array_ = new ModelEntity*[length_];
+		node_list.reset();
+		for( int i = 0; i < length_; i++ )
+			array_[i] = node_list.get_and_step();
+	}
+}
+
+DagNodeRow::~DagNodeRow()
+{
+	if( array_ ) delete [] array_;
+	array_ = 0;
+	length_ = 0;
+}
+
+ModelEntity*& DagNodeRow::operator[]( int index )
+{
+	assert( (index >= 0) && (index < length_) );
+	return array_[index];
+}
+
+
+
+
+
+DagNodeTable::~DagNodeTable( )
+{
+	if( array_ )
+	{
+		for( int i = 0; i < length_; i++ )
+		{
+			if( array_[i] ) 
+			{
+				delete array_[i];
+				array_[i] = 0;
+			}
+		}
+		delete [] array_;
+	}
+	array_ = 0;
+	length_ = 0;
+}
+
+DagNodeRow& DagNodeTable::operator[]( int row )
+{
+	assert( (row >= 0) && (row < length_) && array_[row] );
+	return *(array_[row]);
+}
+
+
+
+
+
+class DLT_IdTable
+{
+public:
+  DLT_IdTable( ){ current_insert_pos = 0; }
+  ~DLT_IdTable( ){ }
+  
+  int find_id( ModelEntity* ME_ptr );
+  
+private:
+  ModelEntity* ME_ptrs_[ 500 ];
+  int current_insert_pos;
+};
+
+void DagDrawingTool::printDag(DLIList<RefFace*> &face_list, int depth) 
+{
+  DLIList<ModelEntity*> entity_list;
+  CAST_LIST_TO_PARENT(face_list, entity_list);
+  printDag(entity_list, depth);
+}
+
+void DagDrawingTool::printDag(DLIList<Body*> &body_list, int depth)
+{
+  DLIList<ModelEntity*> entity_list;
+  CAST_LIST_TO_PARENT(body_list, entity_list);
+  printDag(entity_list, depth);
+}
+
+void DagDrawingTool::printDag(DLIList<ModelEntity*> &entity_list, int depth) 
+{
+  int i;
+  for (i = entity_list.size(); i > 0; i--) {
+    printDag(entity_list.get_and_step(), depth);
+  }
+}
+
+void DagDrawingTool::printDag( ModelEntity* ME_ptr, int depth )
+{
+  assert( ME_ptr != NULL );
+  ModelEntity* node = ME_ptr;
+  print_dag( node, depth );
+}
+
+void DagDrawingTool::print_dag( ModelEntity* any_dag_node, int depth )
+{
+	if( depth >= 0 ) print_node( any_dag_node, 0, "**" );
+	print_dag( any_dag_node, 1, depth );
+	if( depth < 0 ) print_node( any_dag_node, 0, "**" );
+}
+
+void DagDrawingTool::print_node( ModelEntity* node_ptr, int indent, const char* prefix ) 
+{
+	const char* name_ptr = typeid(*node_ptr).name();
+  while (isdigit(*name_ptr)) name_ptr++;
+
+  int id = get_id( node_ptr );
+	PRINT_INFO("%*c%s %s %d", indent*3, ' ', prefix, name_ptr, id);
+  
+  PRINT_INFO("\n");
+}
+
+int DagDrawingTool::get_id( ModelEntity* node_ptr )
+{
+  static DLT_IdTable SE_table;
+  static DLT_IdTable GpE_table;
+
+	RefEntity*       re_ptr = CAST_TO( node_ptr, RefEntity );
+	GroupingEntity* gpe_ptr = CAST_TO( node_ptr, GroupingEntity );
+	SenseEntity*     se_ptr = CAST_TO( node_ptr, SenseEntity );
+	if( re_ptr )      return re_ptr->id();
+	else if( gpe_ptr ) return GpE_table.find_id( gpe_ptr );
+	else if( se_ptr )  return SE_table.find_id( se_ptr );
+	else               return 0;
+}
+
+void DagDrawingTool::print_dag( ModelEntity* node_ptr, int indent, int depth )
+{
+	DLIList<ModelEntity*> relatives;
+	if( depth > 0 ) {
+		node_ptr->get_children( &relatives );
+		for( int i = relatives.size(); i > 0; i-- ) {
+			ModelEntity* child_ptr = relatives.get_and_step();
+				
+			print_node( child_ptr, indent, "<>" );
+			print_dag( child_ptr, indent + 1, depth - 1 );
+		}
+	}
+	else if( depth < 0 ) {
+		node_ptr->get_parents( &relatives );
+		for( int i = relatives.size(); i > 0; i-- ) {
+			ModelEntity* parent_ptr = relatives.get_and_step();
+				
+			print_dag( parent_ptr, indent + 1, depth + 1 );
+			print_node( parent_ptr, indent, "<>" );
+		}
+	}
+}
+
+int DLT_IdTable::find_id( ModelEntity* ME_ptr )
+{
+  ME_ptr = CAST_TO( ME_ptr, ModelEntity );
+  if( ME_ptr == NULL ) return -1;
+  
+  for( int i = 0; i < current_insert_pos; i++ )
+  {
+    if( ME_ptrs_[i] == ME_ptr ) return i + 1;
+  }
+  if( current_insert_pos == 500 ) return -1;
+  ME_ptrs_[ current_insert_pos ] = ME_ptr;
+  current_insert_pos++;
+  return current_insert_pos;
+}
+
+
+
Index: /cgm/geom/virtual/ImprintMatchData.hpp
===================================================================
--- /cgm/geom/virtual/ImprintMatchData.hpp (revision 1040)
+++ /cgm/geom/virtual/ImprintMatchData.hpp (revision 1040)
@@ -0,0 +1,66 @@
+//------------------------------------------------------------------------------
+// Class: ImprintMatchData
+// Description:  Holds data for the intersecting process of boundary imprinting.
+// Owner: David R. White
+// Date: 5/31/02
+//------------------------------------------------------------------------------
+#ifndef IMPRINTMATCHDATA_HPP
+#define IMPRINTMATCHDATA_HPP
+
+#include "CubitDefines.h"
+#include "CubitVector.hpp"
+//#include "ImprintPointData.hpp"
+class ImprintPointData;
+class ImprintLineSegment;
+
+class ImprintMatchData
+{
+private:
+  ImprintPointData *closestPoint;
+  ImprintLineSegment *closestSeg;
+  double closestDist;
+  CubitVector *pointOnSeg;
+  
+public :
+  ImprintMatchData ()
+    {
+      closestPoint = NULL;
+      closestSeg = NULL;
+      closestDist = CUBIT_DBL_MAX;
+      pointOnSeg = NULL;
+    }
+  ~ImprintMatchData ()
+    {
+      if ( pointOnSeg )
+        delete pointOnSeg;
+    }
+  void set_closest_point(ImprintPointData *point)
+    {closestPoint = point;}
+  ImprintPointData* get_closest_point()
+    {return closestPoint;}
+
+  void set_closest_seg(ImprintLineSegment *seg)
+    {closestSeg = seg;}
+  ImprintLineSegment* get_closest_seg()
+    {return closestSeg;}
+
+  void set_closest_dist(double dist)
+    {closestDist = dist;}
+  double get_closest_dist()
+    {return closestDist;}
+
+  void set_point_on(CubitVector &point_on)
+    {
+      if ( pointOnSeg == NULL )
+        pointOnSeg = new CubitVector(point_on);
+      else
+        pointOnSeg->set(point_on);
+    }
+  CubitVector* get_point_on()
+    {
+      return pointOnSeg;
+    }
+  
+};
+
+#endif
Index: /cgm/geom/virtual/Makefile.in
===================================================================
--- /cgm/geom/virtual/Makefile.in (revision 1040)
+++ /cgm/geom/virtual/Makefile.in (revision 1040)
@@ -0,0 +1,686 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+
+# If template defs are included, then the template definitions
+# need to be installed with the headers.  Otherwise they need
+# to be compiled.
+@INCLUDE_TEMPLATE_DEFS_TRUE@am__append_1 = \
+@INCLUDE_TEMPLATE_DEFS_TRUE@    VGArray.cpp \
+@INCLUDE_TEMPLATE_DEFS_TRUE@    VGLoopTool.cpp 
+
+@INCLUDE_TEMPLATE_DEFS_FALSE@am__append_2 = \
+@INCLUDE_TEMPLATE_DEFS_FALSE@    VGArray.cpp \
+@INCLUDE_TEMPLATE_DEFS_FALSE@    VGLoopTool.cpp 
+
+subdir = geom/virtual
+DIST_COMMON = $(am__libcubit_virtual_la_include_HEADERS_DIST) \
+	$(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+	"$(DESTDIR)$(libcubit_virtual_la_includedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libcubit_virtual_la_LIBADD =
+am__libcubit_virtual_la_SOURCES_DIST = AllocMemManagersVirtual.cpp \
+	CACompositeVG.cpp CAPartitionVG.cpp CAVirtualVG.cpp \
+	CollapseAngleTool.cpp CompositeAttrib.cpp CompositeBody.cpp \
+	CompositeCoEdge.cpp CompositeCoSurf.cpp CompositeCurve.cpp \
+	CompositeEngine.cpp CompositeGeom.cpp CompositeLoop.cpp \
+	CompositeLump.cpp CompositePoint.cpp CompositeShell.cpp \
+	CompositeSurface.cpp CompositeTool.cpp CompSurfFacets.cpp \
+	Faceter.cpp FaceterFacetData.cpp FaceterPointData.cpp \
+	FacetProjectTool.cpp HiddenEntitySet.cpp \
+	ImprintBoundaryTool.cpp ImprintLineSegment.cpp \
+	ImprintPointData.cpp PartitionBody.cpp PartitionCoEdge.cpp \
+	PartitionCoSurf.cpp PartitionCurve.cpp PartitionEngine.cpp \
+	PartitionEntity.cpp PartitionLoop.cpp PartitionLump.cpp \
+	PartitionLumpImprint.cpp PartitionPoint.cpp PartitionShell.cpp \
+	PartitionSurface.cpp PartitionTool.cpp PartPTCurve.cpp \
+	PartSurfFacetTool.cpp PST_Data.cpp SegmentedCurve.cpp \
+	SubCurve.cpp SubEntitySet.cpp SubSurface.cpp \
+	TDVGFacetOwner.cpp TDVGFacetSplit.cpp VirtualQueryEngine.cpp \
+	VirtualImprintTool.cpp VGArray.cpp VGLoopTool.cpp
+@INCLUDE_TEMPLATE_DEFS_FALSE@am__objects_1 = VGArray.lo VGLoopTool.lo
+am_libcubit_virtual_la_OBJECTS = AllocMemManagersVirtual.lo \
+	CACompositeVG.lo CAPartitionVG.lo CAVirtualVG.lo \
+	CollapseAngleTool.lo CompositeAttrib.lo CompositeBody.lo \
+	CompositeCoEdge.lo CompositeCoSurf.lo CompositeCurve.lo \
+	CompositeEngine.lo CompositeGeom.lo CompositeLoop.lo \
+	CompositeLump.lo CompositePoint.lo CompositeShell.lo \
+	CompositeSurface.lo CompositeTool.lo CompSurfFacets.lo \
+	Faceter.lo FaceterFacetData.lo FaceterPointData.lo \
+	FacetProjectTool.lo HiddenEntitySet.lo ImprintBoundaryTool.lo \
+	ImprintLineSegment.lo ImprintPointData.lo PartitionBody.lo \
+	PartitionCoEdge.lo PartitionCoSurf.lo PartitionCurve.lo \
+	PartitionEngine.lo PartitionEntity.lo PartitionLoop.lo \
+	PartitionLump.lo PartitionLumpImprint.lo PartitionPoint.lo \
+	PartitionShell.lo PartitionSurface.lo PartitionTool.lo \
+	PartPTCurve.lo PartSurfFacetTool.lo PST_Data.lo \
+	SegmentedCurve.lo SubCurve.lo SubEntitySet.lo SubSurface.lo \
+	TDVGFacetOwner.lo TDVGFacetSplit.lo VirtualQueryEngine.lo \
+	VirtualImprintTool.lo $(am__objects_1)
+libcubit_virtual_la_OBJECTS = $(am_libcubit_virtual_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir)
+depcomp = $(SHELL) $(top_srcdir)/./config_aux/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+	$(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libcubit_virtual_la_SOURCES)
+DIST_SOURCES = $(am__libcubit_virtual_la_SOURCES_DIST)
+am__libcubit_virtual_la_include_HEADERS_DIST = CACompositeVG.hpp \
+	CAPartitionVG.hpp CAVirtualVG.hpp CollapseAngleTool.hpp \
+	CompSurfFacets.hpp CompositeAttrib.hpp CompositeBody.hpp \
+	CompositeCoEdge.hpp CompositeCoSurf.hpp CompositeCurve.hpp \
+	CompositeEngine.hpp CompositeGeom.hpp CompositeLoop.hpp \
+	CompositeLump.hpp CompositePoint.hpp CompositeShell.hpp \
+	CompositeSurface.hpp CompositeTool.hpp FacetProjectTool.hpp \
+	Faceter.hpp FaceterFacetData.hpp FaceterPointData.hpp \
+	HiddenEntitySet.hpp ImprintBoundaryTool.hpp \
+	ImprintLineSegment.hpp ImprintMatchData.hpp \
+	ImprintPointData.hpp PST_Data.hpp PartPTCurve.hpp \
+	PartSurfFacetTool.hpp PartitionBody.hpp PartitionCoEdge.hpp \
+	PartitionCoSurf.hpp PartitionCurve.hpp PartitionEngine.hpp \
+	PartitionEntity.hpp PartitionLoop.hpp PartitionLump.hpp \
+	PartitionLumpImprint.hpp PartitionPoint.hpp PartitionShell.hpp \
+	PartitionSurface.hpp PartitionTool.hpp SegmentedCurve.hpp \
+	SplitSurfaceVirtual.hpp SubCurve.hpp SubEntitySet.hpp \
+	SubSurface.hpp TDVGFacetOwner.hpp TDVGFacetSplit.hpp \
+	VGArray.hpp VGDefines.h VGLoopTool.hpp VirtualImprintTool.hpp \
+	VirtualQueryEngine.hpp VGArray.cpp VGLoopTool.cpp
+libcubit_virtual_la_includeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libcubit_virtual_la_include_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACIS_DEFS = @ACIS_DEFS@
+ACIS_DIR = @ACIS_DIR@
+ACIS_HEALER = @ACIS_HEALER@
+ACIS_IGES_TRANSLATOR = @ACIS_IGES_TRANSLATOR@
+ACIS_INCLUDES = @ACIS_INCLUDES@
+ACIS_LIBS = @ACIS_LIBS@
+ACIS_LIB_DIR = @ACIS_LIB_DIR@
+ACIS_PLATFORM = @ACIS_PLATFORM@
+ACIS_STEP_TRANSLATOR = @ACIS_STEP_TRANSLATOR@
+ACIS_VERSION = @ACIS_VERSION@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CANT_USE_STD = @CANT_USE_STD@
+CANT_USE_STD_IO = @CANT_USE_STD_IO@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CGM_PARALLEL_INCLUDE = @CGM_PARALLEL_INCLUDE@
+CGM_PARALLEL_LIB = @CGM_PARALLEL_LIB@
+CGM_PARALLEL_LIB_FILE = @CGM_PARALLEL_LIB_FILE@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+
+# Override default defines with the ones we want from the configure script
+DEFS = $(TEMPLATE_DEFS_INCLUDED) $(LITTLE_ENDIAN)
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GREP = @GREP@
+INCLUDE_TEMPLATE_DEFS_FALSE = @INCLUDE_TEMPLATE_DEFS_FALSE@
+INCLUDE_TEMPLATE_DEFS_TRUE = @INCLUDE_TEMPLATE_DEFS_TRUE@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LITTLE_ENDIAN = @LITTLE_ENDIAN@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TEMPLATE_DEFS_INCLUDED = @TEMPLATE_DEFS_INCLUDED@
+USE_MPI_FALSE = @USE_MPI_FALSE@
+USE_MPI_TRUE = @USE_MPI_TRUE@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_ACIS_FALSE = @build_ACIS_FALSE@
+build_ACIS_TRUE = @build_ACIS_TRUE@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_parallel_FALSE = @build_parallel_FALSE@
+build_parallel_TRUE = @build_parallel_TRUE@
+build_vendor = @build_vendor@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+# Don't require GNU-standard files (Changelog, README, etc.)
+AUTOMAKE_OPTIONS = foreign
+INCLUDES = -I$(top_srcdir)/util \
+           -I$(top_srcdir)/geom \
+           -I$(top_srcdir)/geom/facet \
+           -I$(top_srcdir)/geom/Cholla
+
+
+# The name of the library to build
+lib_LTLIBRARIES = libcubit_virtual.la
+
+# The directory where headers will be installed
+libcubit_virtual_la_includedir = $(includedir)
+
+# The non-template sources
+libcubit_virtual_la_SOURCES = AllocMemManagersVirtual.cpp \
+	CACompositeVG.cpp CAPartitionVG.cpp CAVirtualVG.cpp \
+	CollapseAngleTool.cpp CompositeAttrib.cpp CompositeBody.cpp \
+	CompositeCoEdge.cpp CompositeCoSurf.cpp CompositeCurve.cpp \
+	CompositeEngine.cpp CompositeGeom.cpp CompositeLoop.cpp \
+	CompositeLump.cpp CompositePoint.cpp CompositeShell.cpp \
+	CompositeSurface.cpp CompositeTool.cpp CompSurfFacets.cpp \
+	Faceter.cpp FaceterFacetData.cpp FaceterPointData.cpp \
+	FacetProjectTool.cpp HiddenEntitySet.cpp \
+	ImprintBoundaryTool.cpp ImprintLineSegment.cpp \
+	ImprintPointData.cpp PartitionBody.cpp PartitionCoEdge.cpp \
+	PartitionCoSurf.cpp PartitionCurve.cpp PartitionEngine.cpp \
+	PartitionEntity.cpp PartitionLoop.cpp PartitionLump.cpp \
+	PartitionLumpImprint.cpp PartitionPoint.cpp PartitionShell.cpp \
+	PartitionSurface.cpp PartitionTool.cpp PartPTCurve.cpp \
+	PartSurfFacetTool.cpp PST_Data.cpp SegmentedCurve.cpp \
+	SubCurve.cpp SubEntitySet.cpp SubSurface.cpp \
+	TDVGFacetOwner.cpp TDVGFacetSplit.cpp VirtualQueryEngine.cpp \
+	VirtualImprintTool.cpp $(am__append_2)
+
+# Headers to be installed.  If any file in this list should
+# not be installed, move it to the _SOURCES list above.
+libcubit_virtual_la_include_HEADERS = CACompositeVG.hpp \
+	CAPartitionVG.hpp CAVirtualVG.hpp CollapseAngleTool.hpp \
+	CompSurfFacets.hpp CompositeAttrib.hpp CompositeBody.hpp \
+	CompositeCoEdge.hpp CompositeCoSurf.hpp CompositeCurve.hpp \
+	CompositeEngine.hpp CompositeGeom.hpp CompositeLoop.hpp \
+	CompositeLump.hpp CompositePoint.hpp CompositeShell.hpp \
+	CompositeSurface.hpp CompositeTool.hpp FacetProjectTool.hpp \
+	Faceter.hpp FaceterFacetData.hpp FaceterPointData.hpp \
+	HiddenEntitySet.hpp ImprintBoundaryTool.hpp \
+	ImprintLineSegment.hpp ImprintMatchData.hpp \
+	ImprintPointData.hpp PST_Data.hpp PartPTCurve.hpp \
+	PartSurfFacetTool.hpp PartitionBody.hpp PartitionCoEdge.hpp \
+	PartitionCoSurf.hpp PartitionCurve.hpp PartitionEngine.hpp \
+	PartitionEntity.hpp PartitionLoop.hpp PartitionLump.hpp \
+	PartitionLumpImprint.hpp PartitionPoint.hpp PartitionShell.hpp \
+	PartitionSurface.hpp PartitionTool.hpp SegmentedCurve.hpp \
+	SplitSurfaceVirtual.hpp SubCurve.hpp SubEntitySet.hpp \
+	SubSurface.hpp TDVGFacetOwner.hpp TDVGFacetSplit.hpp \
+	VGArray.hpp VGDefines.h VGLoopTool.hpp VirtualImprintTool.hpp \
+	VirtualQueryEngine.hpp $(am__append_1)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  geom/virtual/Makefile'; \
+	cd $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign  geom/virtual/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+	@$(NORMAL_INSTALL)
+	test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  if test -f $$p; then \
+	    f=$(am__strip_dir) \
+	    echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+	    $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+	  else :; fi; \
+	done
+
+uninstall-libLTLIBRARIES:
+	@$(NORMAL_UNINSTALL)
+	@set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  p=$(am__strip_dir) \
+	  echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+	  $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+	done
+
+clean-libLTLIBRARIES:
+	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+	@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+	  dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+	  test "$$dir" != "$$p" || dir=.; \
+	  echo "rm -f \"$${dir}/so_locations\""; \
+	  rm -f "$${dir}/so_locations"; \
+	done
+libcubit_virtual.la: $(libcubit_virtual_la_OBJECTS) $(libcubit_virtual_la_DEPENDENCIES) 
+	$(CXXLINK) -rpath $(libdir) $(libcubit_virtual_la_LDFLAGS) $(libcubit_virtual_la_OBJECTS) $(libcubit_virtual_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllocMemManagersVirtual.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CACompositeVG.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CAPartitionVG.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CAVirtualVG.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CollapseAngleTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompSurfFacets.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeAttrib.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeBody.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeCoEdge.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeCoSurf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeCurve.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeEngine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeGeom.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeLoop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeLump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositePoint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeShell.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeSurface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompositeTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FacetProjectTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Faceter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FaceterFacetData.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FaceterPointData.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HiddenEntitySet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImprintBoundaryTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImprintLineSegment.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImprintPointData.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PST_Data.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartPTCurve.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartSurfFacetTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionBody.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionCoEdge.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionCoSurf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionCurve.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionEngine.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionEntity.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionLoop.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionLump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionLumpImprint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionPoint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionShell.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionSurface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PartitionTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SegmentedCurve.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SubCurve.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SubEntitySet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SubSurface.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TDVGFacetOwner.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TDVGFacetSplit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VGArray.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VGLoopTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VirtualImprintTool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/VirtualQueryEngine.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@	if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@	if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@	then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@	$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+	-rm -f *.lo
+
+clean-libtool:
+	-rm -rf .libs _libs
+
+distclean-libtool:
+	-rm -f libtool
+uninstall-info-am:
+install-libcubit_virtual_la_includeHEADERS: $(libcubit_virtual_la_include_HEADERS)
+	@$(NORMAL_INSTALL)
+	test -z "$(libcubit_virtual_la_includedir)" || $(mkdir_p) "$(DESTDIR)$(libcubit_virtual_la_includedir)"
+	@list='$(libcubit_virtual_la_include_HEADERS)'; for p in $$list; do \
+	  if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+	  f=$(am__strip_dir) \
+	  echo " $(libcubit_virtual_la_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libcubit_virtual_la_includedir)/$$f'"; \
+	  $(libcubit_virtual_la_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libcubit_virtual_la_includedir)/$$f"; \
+	done
+
+uninstall-libcubit_virtual_la_includeHEADERS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(libcubit_virtual_la_include_HEADERS)'; for p in $$list; do \
+	  f=$(am__strip_dir) \
+	  echo " rm -f '$(DESTDIR)$(libcubit_virtual_la_includedir)/$$f'"; \
+	  rm -f "$(DESTDIR)$(libcubit_virtual_la_includedir)/$$f"; \
+	done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+	list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	    $$tags $$unique; \
+	fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+		$(TAGS_FILES) $(LISP)
+	tags=; \
+	here=`pwd`; \
+	list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+	unique=`for i in $$list; do \
+	    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+	  done | \
+	  $(AWK) '    { files[$$0] = 1; } \
+	       END { for (i in files) print i; }'`; \
+	test -z "$(CTAGS_ARGS)$$tags$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$tags $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && cd $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+	list='$(DISTFILES)'; for file in $$list; do \
+	  case $$file in \
+	    $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+	    $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+	  esac; \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+	  if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+	    dir="/$$dir"; \
+	    $(mkdir_p) "$(distdir)$$dir"; \
+	  else \
+	    dir=''; \
+	  fi; \
+	  if test -d $$d/$$file; then \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+	    fi; \
+	    cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+	  else \
+	    test -f $(distdir)/$$file \
+	    || cp -p $$d/$$file $(distdir)/$$file \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libcubit_virtual_la_includedir)"; do \
+	  test -z "$$dir" || $(mkdir_p) "$$dir"; \
+	done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	  install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	  `test -z '$(STRIP)' || \
+	    echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+	mostlyclean-am
+
+distclean: distclean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libcubit_virtual_la_includeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+	-rm -rf ./$(DEPDIR)
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
+	uninstall-libcubit_virtual_la_includeHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+	clean-libLTLIBRARIES clean-libtool ctags distclean \
+	distclean-compile distclean-generic distclean-libtool \
+	distclean-tags distdir dvi dvi-am html html-am info info-am \
+	install install-am install-data install-data-am install-exec \
+	install-exec-am install-info install-info-am \
+	install-libLTLIBRARIES \
+	install-libcubit_virtual_la_includeHEADERS install-man \
+	install-strip installcheck installcheck-am installdirs \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+	pdf pdf-am ps ps-am tags uninstall uninstall-am \
+	uninstall-info-am uninstall-libLTLIBRARIES \
+	uninstall-libcubit_virtual_la_includeHEADERS
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
Index: /cgm/geom/virtual/VirtualQueryEngine.cpp
===================================================================
--- /cgm/geom/virtual/VirtualQueryEngine.cpp (revision 1040)
+++ /cgm/geom/virtual/VirtualQueryEngine.cpp (revision 1040)
@@ -0,0 +1,1888 @@
+//-------------------------------------------------------------------------
+// Filename      : VirtualQueryEngine.cc 
+//
+// Purpose       : This file contains the implementation of the class 
+//                 VirtualQueryEngine. 
+//
+// Special Notes : There are several functions in this class which are 
+//                 inhereted from GeometryQueryEngine that are not
+//                 implemented or applicable in this class.  These
+//                 functions, if called, will print an error message
+//                 and return the most appropriate error condition available.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 08/01/97 
+//-------------------------------------------------------------------------
+
+// ********** BEGIN STANDARD INCLUDES      **********
+#include <assert.h>
+// ********** END STANDARD INCLUDES        **********
+
+// ********** BEGIN CUBIT INCLUDES         **********
+
+#include "VirtualQueryEngine.hpp"
+#include "CompositeTool.hpp"
+#include "PartitionTool.hpp"
+#include "CompositeEngine.hpp"
+#include "PartitionEngine.hpp"
+#include "GeometryUtil.hpp"
+
+#include "CubitDefines.h"
+#include "GeometryDefines.h"
+#include "CubitVector.hpp"
+
+#include "CastTo.hpp"
+#include "GMem.hpp"
+
+#include "ModelQueryEngine.hpp"
+#include "ModelEntity.hpp"
+
+#include "Body.hpp"
+#include "CoVolume.hpp"
+#include "RefVolume.hpp"
+#include "RefFace.hpp"
+#include "Loop.hpp"
+#include "CoEdge.hpp"
+#include "RefEdge.hpp"
+#include "Chain.hpp"
+#include "CoVertex.hpp"
+#include "RefVertex.hpp"
+#include "RefEntityFactory.hpp"
+#include "CoFace.hpp"
+
+
+#include "CompositePoint.hpp"
+#include "CompositeCurve.hpp"
+#include "CompositeSurface.hpp"
+#include "CompositeLump.hpp"
+#include "CompositeBody.hpp"
+#include "PartitionBody.hpp"
+#include "PartitionLump.hpp"
+#include "PartitionSurface.hpp"
+#include "PartitionCurve.hpp"
+
+
+#include "Shell.hpp"
+#include "GeometryQueryTool.hpp"
+#include "CubitPointData.hpp"
+#include "CubitFacetData.hpp"
+
+#include "CACompositeVG.hpp"
+#include "CAPartitionVG.hpp"
+#include "CAVirtualVG.hpp"
+
+// ********** END CUBIT INCLUDES           **********
+
+// ********** BEGIN STATIC DECLARATIONS    **********
+VirtualQueryEngine* VirtualQueryEngine::instance_ = NULL; 
+//- A pointer to the single instance of this class
+
+
+const int VirtualQueryEngine::VGE_MAJOR_VERSION = 10;
+const int VirtualQueryEngine::VGE_MINOR_VERSION = 0;
+const int VirtualQueryEngine::VGE_SUBMINOR_VERSION = 0;
+
+const double VirtualQueryEngine::param_epsilon_fraction = 1000000;
+//- This value is used to determine epsilon for
+//- compensating for rounding error in parameter
+//- conversion between virtaul geometry and real
+//- geometry.
+
+// ********** END STATIC DECLARATIONS      **********
+
+// ********** BEGIN PUBLIC FUNCTIONS       **********
+
+//-------------------------------------------------------------------------
+// Purpose	 : Destructor
+//
+// Special Notes :
+//
+// Creator	 : Jason Kraftcheck
+//
+// Creation Date : 08/01/97
+//-------------------------------------------------------------------------
+VirtualQueryEngine::~VirtualQueryEngine( )
+{
+//  destroy_all_virtual_entities();
+//	if( virtual_entity_list_.size() )
+//		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 );
+  instance_ = NULL;
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose	 : Return a description of this ModelingEngine
+//
+// Special Notes :
+//
+// Creator	 : Jason Kraftcheck
+//
+// Creation Date : 08/01/97
+//-------------------------------------------------------------------------
+int VirtualQueryEngine::get_major_version()
+{
+  return VGE_MAJOR_VERSION;
+}
+
+int VirtualQueryEngine::get_minor_version()
+{
+  return VGE_MINOR_VERSION;
+}
+
+int VirtualQueryEngine::get_subminor_version()
+{
+  return VGE_SUBMINOR_VERSION;
+}
+
+CubitString VirtualQueryEngine::get_engine_version_string()
+{
+  CubitString return_this(
+    "VirtualQueryEngine v1.2 by Jason Kraftcheck.\n" );
+  return_this += "I-CARVE Lab., University of Wisconsin - Madison,  August 1, 1997.\n";
+  return_this += "This ModelingEngine performs the necessary topological ";
+  return_this += "operations for working with VirtualEntities, including ";
+  return_this += "objects of type CompositeEntity, PartitionEntity, and ";
+  return_this += "ParasiteEntity.  ComposinteModelingEngine also ";
+  return_this += "provides the interface for creating, destroying, and ";
+  return_this += "modifying VirtualEntities.\n";
+  
+  return return_this;
+}
+
+CubitStatus VirtualQueryEngine::transform_vec_position(
+  CubitVector const& ,
+  BodySM *,
+  CubitVector & ) const
+{
+  return CUBIT_FAILURE;
+}
+//-------------------------------------------------------------------------
+// Purpose       : This function determines faceting information for use
+//		             by HOOPS.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 
+//-------------------------------------------------------------------------
+CubitStatus VirtualQueryEngine::get_graphics(
+  Surface* surf_ptr, int& number_triangles,
+  int& number_points, int& number_facets,
+  GMem* gMem,
+  unsigned short normal_tol,
+  double dist_tol,
+  double max_edge_length ) const
+{
+  CompositeSurface* cs_ptr = CAST_TO(surf_ptr, CompositeSurface );
+  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,
+                                            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,
+                                            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);
+    return CUBIT_FAILURE;
+  }
+}
+
+//-----------------------------------------------------------------------
+// Purpose	 : This function returns the necessary faceting information
+//		   to display the curve.
+//
+// Special Notes :
+//
+// Creator	 : Jason Kraftcheck
+//
+// Creation Date : 10/10/97
+//-----------------------------------------------------------------------
+CubitStatus VirtualQueryEngine::get_graphics( Curve* curve_ptr,
+                                                 int& num_points,
+                                                 GMem* gMem,
+                                                 double ) const
+{
+  CompositeCurve* ccurve = CAST_TO( curve_ptr, CompositeCurve );
+  PartitionCurve* pcurve = CAST_TO( curve_ptr, PartitionCurve );
+  
+  CubitStatus result;
+  
+  if( ccurve != NULL )
+  {
+    result = get_composite_curve_facetting( ccurve, num_points, gMem );
+  }
+  else if( pcurve != NULL )
+  {
+    result = get_partition_curve_facetting( pcurve, num_points, gMem );
+  }
+  else
+  {
+    PRINT_ERROR("Unknown curve type or NULL curve passed to "
+                "VirtualQueryEngine::get_graphics_edges()\n");
+    return CUBIT_FAILURE;
+  }
+  
+  return result;
+}
+
+// This is the template for an unimplemented version of this function.
+CubitStatus VirtualQueryEngine::get_isoparametric_points(Surface*,
+                                                            int& nu, int& nv,
+                                                            GMem*& ) const
+{
+  nu = nv = 0;
+  return CUBIT_FAILURE;
+}
+
+// This is the template for an unimplemented version of this function.
+CubitStatus VirtualQueryEngine::get_u_isoparametric_points(Surface*,
+                                                            double , int& ,
+                                                            GMem*& ) const
+{
+  return CUBIT_FAILURE;
+}
+
+// This is the template for an unimplemented version of this function.
+CubitStatus VirtualQueryEngine::get_v_isoparametric_points(Surface*,
+                                                            double , int&,
+                                                            GMem*&) const
+{
+  return CUBIT_FAILURE;
+}
+
+//-----------------------------------------------------------------------
+// Purpose	 : This function constructs the edge facetting information
+//		   of a CompositeCurve for use by HOOPS.
+//
+// Special Notes :
+//
+// Creator	 : Jason Kraftcheck
+//
+// Creation Date : 10/10/97
+//-----------------------------------------------------------------------
+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;
+  }
+  
+  GMem current_gmem; 
+  int point_count = 0; //Current total of points returned
+    // from underlying edges
+  
+  int next_index = 0; //index of next insert spot in passed GMem object.
+  
+    //Get points for each underlying curve
+  current_gmem.clean_out();
+  for( int i = 0; i < ccurve_ptr->num_curves(); i++ )
+  {
+      // Get the next curve and its GME
+    Curve* curve_ptr = ccurve_ptr->get_curve(i);
+    GeometryQueryEngine* GQE_ptr = 
+      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);
+    if( current_status == CUBIT_FAILURE )
+      return CUBIT_FAILURE;
+      
+    // Make sure the passed in gmem is big enough
+    gMem->allocate_more_polylines(this_point_count-1);
+      //assert( gMem->pts_size >= point_count );
+    
+      // If this isn't the first curve, we don't need to
+      // repeat one of the end nodes.
+    if (point_count != 0)
+      this_point_count--;
+      // Add to the total number of points so far
+    point_count += this_point_count;
+    
+      //Copy points to passed GMem, in the correct order
+      //for the sense of the underlying edge wrt the
+      //composite.
+    CubitSense sense = ccurve_ptr->get_sense( i );
+    
+    if( sense == CUBIT_FORWARD )
+    {
+      if (next_index == 0)
+        for(int j = 0; j < point_count; j++)
+        {
+          gMem->point_list()[j] = current_gmem.point_list()[j];
+        }
+      else
+          // cur_gmem has one more point than we will access,
+          // so last index is point_count-next_index.
+        for(int j = next_index; j < point_count; j++)
+        {
+          gMem->point_list()[j] = current_gmem.point_list()[j - next_index + 1];
+        }
+    }
+    else //( sense == CUBIT_REVERSED )
+    {
+        // All but the first curve will not use one of its points.
+        // This is taken into account by decrementing point_count
+        // earlier.
+      for(int j = next_index; j < point_count; j++)
+      {
+        gMem->point_list()[j] = current_gmem.point_list()[point_count-j-1];
+      }
+    }
+    next_index = point_count;
+    gMem->pointListCount = point_count;
+  }
+  
+  num_points = point_count;
+  gMem->pointListCount = point_count;
+  return CUBIT_SUCCESS;
+}
+
+//-----------------------------------------------------------------------
+// Purpose	 : This function constructs the edge facetting information
+//		   of a PartitionCurve for use by HOOPS.
+//
+// Special Notes : It is currently not possible to split a face which
+//                 has more than one loop (holes) because we cannot
+//                 determine which partition the holes should lie on with
+//                 the current implementation of ParasiteCurve.
+//
+// Creator       : Jason Kraftcheck 
+//
+// Creation Date : 10/10/97
+//-----------------------------------------------------------------------
+CubitStatus VirtualQueryEngine::get_partition_curve_facetting(
+  PartitionCurve* pcurve_ptr, int& num_steps, GMem* gMem ) const
+{
+  assert( gMem != NULL );
+  CubitStatus result = pcurve_ptr->get_graphics( *gMem );
+  num_steps = gMem->pointListCount;
+  return result;
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : get Hoops facetting information for a CompositeSurface.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/17/98
+//-------------------------------------------------------------------------
+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,
+  double longest_edge ) const
+{
+  if( gMem == NULL )
+    return CUBIT_FAILURE;
+    
+  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() ];
+  
+    // Get the facets of each Surface
+  int i;
+  for(i = 0; i < surf_ptr->num_surfs(); i++)
+  {
+    int tri_count, pt_count, facet_count;
+    Surface* surface_ptr = surf_ptr->get_surface(i);
+    
+    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]),
+                                  normal_tol, dist_tol, longest_edge );
+    
+    number_triangles += tri_count;
+    number_facets += gMem_list[i].fListCount;
+    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);
+  
+  for( i = 0; i < surf_ptr->num_surfs(); i++ )
+  {
+    int j;
+    for(  j = 0; j < gMem_list[i].pointListCount; j++ )
+    {
+      assert((point_offset + j) < gMem->pointListCount );
+      gMem->point_list()[j + point_offset].x = gMem_list[i].point_list()[j].x;
+      gMem->point_list()[j + point_offset].y = gMem_list[i].point_list()[j].y;
+      gMem->point_list()[j + point_offset].z = gMem_list[i].point_list()[j].z;
+    }
+    
+    int k;
+    for( k = 0; k < gMem_list[i].fListCount;)
+    {
+      int count = gMem_list[i].facet_list()[k];
+      assert( k + count < gMem->fListCount );
+      
+      gMem->facet_list()[k + face_offset] = count;
+      k++;
+      for( int l = 0; l < count; l++, k++ )
+      {
+        assert( k + face_offset < gMem->fListCount );
+        assert( k < gMem_list[i].fListCount );
+        gMem->facet_list()[k + face_offset] = gMem_list[i].facet_list()[k] 
+          + point_offset;
+      }
+    }
+    
+    point_offset += j;
+    face_offset += k;
+  }
+  
+  gMem->consolidate_points(10*GEOMETRY_RESABS);
+  number_points = gMem->pointListCount;
+//     // Debug!!!
+//   int q;
+//   for (q = 0; q < bte_list.size(); q++)
+//   {
+//     PRINT_INFO("Printing Points for Surface %d.\n", q);
+//     int r;
+//     for (r = 0; r < gMem_list[q].pointListCount; r++)
+//     {
+//       PRINT_INFO("%g %g %g\n",
+//                  gMem_list[q].point_list()[r].x,
+//                  gMem_list[q].point_list()[r].y,
+//                  gMem_list[q].point_list()[r].z);
+//     }
+//     PRINT_INFO("Printing FList for Surface %d.\n", q);
+//     for (r = 0; r < gMem_list[q].fListCount; r++)
+//     {
+//       PRINT_INFO("%d %s",
+//                  gMem_list[q].facet_list()[r],
+//                  r % 4 ? "" : "\n");
+//     }
+//   }
+//   PRINT_INFO("Composite points:\n");
+//   for (q = 0; q < gMem->pointListCount; q++)
+//   {
+//     PRINT_INFO("%g %g %g\n",
+//                gMem->point_list()[q].x,
+//                gMem->point_list()[q].y,
+//                gMem->point_list()[q].z);
+//   }
+//   PRINT_INFO("Composite facet list:\n");
+//   for (q = 0; q < gMem->fListCount; q++)
+//   {
+//     PRINT_INFO("%d %s",
+//                gMem->facet_list()[q],
+//                q % 4 ? "" : "\n");
+//   }
+  
+  delete [] gMem_list;	
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : get hoops facets for a partition surface
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck 
+//
+// Creation Date : 06/18/98
+//-------------------------------------------------------------------------
+CubitStatus VirtualQueryEngine::get_partition_surface_facetting(
+  PartitionSurface* surf_ptr,
+  int& num_triangles,
+  int& num_points,
+  int& num_facets,
+  GMem* gMem,
+  unsigned short ,
+  double,
+  double ) const
+{
+  int i, j;
+  
+  DLIList<CubitFacetData*> surf_facets;
+  DLIList<CubitPoint*> surf_points;
+  
+    // get surface facets
+  surf_ptr->get_facet_data( surf_facets );
+
+    // get list of points from list of facets
+  for( i = surf_facets.size(); i--; )
+  {
+    CubitFacetData* facet = surf_facets.step_and_get();
+    for( j = 0; j< 3; j++ )
+      facet->point(j)->marked(1);
+  }
+  for( i = surf_facets.size(); i--; )
+  {
+    CubitFacetData* facet = surf_facets.step_and_get();
+    for( j = 0; j< 3; j++ )
+    {
+      if( facet->point(j)->marked() )
+      {
+        facet->point(j)->marked(0);
+        surf_points.append( facet->point(j) );
+      }
+    }
+  }
+
+  if( ! gMem ) return CUBIT_SUCCESS;
+
+    // allocate storage for facet data
+  gMem->allocate_tri( surf_facets.size() );
+  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();
+  for( i = 0; i < gMem->pointListCount; i++ )
+  {
+    GPoint* gpt = gMem->point_list() + i;
+    CubitPoint* pt = surf_points.get_and_step();
+    pt->marked(i);
+    gpt->x = (float)(pt->coordinates().x() );
+    gpt->y = (float)(pt->coordinates().y() );
+    gpt->z = (float)(pt->coordinates().z() );
+  }
+  
+    // put each facet in the GMem.  retreive
+    // point indices from marks.
+  surf_facets.reset();
+  int* gfacet_ptr = gMem->facet_list();
+  for( i = 0; i < surf_facets.size(); i++ )
+  {
+    CubitFacetData* facet = surf_facets.get_and_step();
+    *gfacet_ptr = 3;
+    gfacet_ptr++;
+    for( j = 0; j < 3; j++ )
+    {
+      *gfacet_ptr = facet->point(j)->marked();
+      gfacet_ptr++;
+    }
+  }
+  
+    // clear point marks
+  for( i = surf_points.size(); i--; )
+    surf_points.step_and_get()->marked(0);
+  
+  return CUBIT_SUCCESS;
+}
+
+// ********** END PUBLIC FUNCTIONS         **********
+
+// ********** BEGIN PROTECTED FUNCTIONS    **********
+
+//-------------------------------------------------------------------------
+// Purpose       : The constructor of the VirtualQueryEngine class.
+//
+// Special Notes : 
+//
+// Creator       : Wes Gill
+//
+// Creation Date : 10/5/01
+//-------------------------------------------------------------------------
+
+VirtualQueryEngine::VirtualQueryEngine()
+{
+  assert( !instance_);
+    //Add the VirtualQueryEngine to the GeometryQueryTool's gqeList and
+    //set the VGE to the GQT's default engine.
+   //GeometryQueryTool::instance()->add_gqe(this);
+   //GeometryQueryTool::instance()->set_default_engine(this); 
+  CompositeEngine::instance();
+  PartitionEngine::instance();
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : get child virtual geometry
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck 
+//
+// Creation Date : 08/11/98
+//-------------------------------------------------------------------------
+void VirtualQueryEngine::get_VEs( TopologyEntity* te_ptr,
+                                     DLIList<TopologyBridge*>& ve_list, 
+                                     CubitBoolean visible,
+                                     const CubitBoolean children_too)
+{
+  DLIList<TopologyBridge*> child_list;
+  Body*      body_ptr   = CAST_TO( te_ptr, Body );
+  CoVolume*  covol_ptr  = CAST_TO( te_ptr, CoVolume );
+  RefVolume* vol_ptr    = CAST_TO( te_ptr, RefVolume );
+  Shell*     shell_ptr  = CAST_TO( te_ptr, Shell );
+  CoFace*    coface_ptr = CAST_TO( te_ptr, CoFace );
+  RefFace*   face_ptr   = CAST_TO( te_ptr, RefFace );
+  Loop*      loop_ptr   = CAST_TO( te_ptr, Loop );
+  CoEdge*    coedge_ptr = CAST_TO( te_ptr, CoEdge );
+  RefEdge*   edge_ptr   = CAST_TO( te_ptr, RefEdge );
+  Chain*     chain_ptr  = CAST_TO( te_ptr, Chain );
+  CoVertex*  covex_ptr  = CAST_TO( te_ptr, CoVertex );
+  RefVertex* vex_ptr    = CAST_TO( te_ptr, RefVertex );
+  
+  if( (body_ptr != NULL) || (covol_ptr != NULL) )
+  {
+    if (children_too) {
+      DLIList<RefVolume*> vol_list;
+      te_ptr->ref_volumes( vol_list );
+      for( int i = vol_list.size(); i > 0; i-- )
+      {
+        child_list.clean_out();
+        get_VEs( vol_list.get_and_step(), child_list, visible,
+                 children_too);
+        ve_list.merge_unique( child_list );
+      }
+    }
+  }
+  else if( vol_ptr != NULL )
+  {
+    get_VEs( vol_ptr, ve_list, visible, children_too );
+  }
+  else if( (shell_ptr != NULL) || (coface_ptr != NULL) )
+  {
+    if (children_too) {
+      DLIList<RefFace*> face_list;
+      te_ptr->ref_faces( face_list );
+      for( int i = face_list.size(); i> 0; i-- )
+      {
+        child_list.clean_out();
+        get_VEs( face_list.get_and_step(), child_list, visible,
+                 children_too);
+        ve_list.merge_unique( child_list );
+      }
+    }
+  }
+  else if( face_ptr != NULL )
+  {
+    get_VEs( face_ptr, ve_list, visible, children_too );
+  }
+  else if( (loop_ptr != NULL) || (coedge_ptr != NULL) )
+  {
+    if (children_too) {
+      DLIList<RefEdge*> edge_list;
+      te_ptr->ref_edges( edge_list );
+      for( int i = edge_list.size(); i > 0; i-- )
+      {
+        child_list.clean_out();
+        get_VEs( edge_list.get_and_step(), child_list, visible,
+                 children_too);
+        ve_list.merge_unique( child_list );
+      }
+    }
+  }
+  else if( edge_ptr != NULL )
+  {
+    get_VEs( edge_ptr, ve_list, visible, children_too );
+  }
+  else if( (chain_ptr != NULL) || (covex_ptr != NULL ) )
+  {
+    if (children_too) {
+      DLIList<RefVertex*> vertex_list;
+      te_ptr->ref_vertices( vertex_list );
+      for( int i = vertex_list.size(); i > 0; i-- )
+      {
+        child_list.clean_out();
+        get_VEs( vertex_list.get_and_step(), child_list, visible,
+                 children_too);
+        ve_list.merge_unique( child_list );
+      }
+    }
+  }
+  else if( vex_ptr != NULL )
+  {
+    get_VEs( vex_ptr, ve_list, visible, children_too );
+  }
+  else
+	{
+	  PRINT_ERROR("Unknown type of TopologyEntity passed to "
+		            "VirtualQueryEngine::get_VEs(..).  Passed pointer"
+								" may be stale.\n");
+	}
+}
+
+void VirtualQueryEngine::get_VEs( RefVolume* volume_ptr,
+                                     DLIList<TopologyBridge*>& ve_list,
+                                     CubitBoolean visible,
+                                     const CubitBoolean children_too )
+{
+#ifdef BOYD17
+  DLIList<BasicTopologyEntity*> tmp_list, bte_list;
+#endif  
+  DLIList<BasicTopologyEntity*> bte_list;
+  int i;
+  
+  DLIList<TopologyBridge*> tb_list;
+  volume_ptr->bridge_manager()->get_bridge_list( tb_list );
+  
+  for( i = tb_list.size(); i--; )
+  {  
+    TopologyBridge* tb_ptr = tb_list.get_and_step();
+    PartitionEntity* ve_ptr = dynamic_cast<PartitionEntity*>(tb_ptr);
+    CompositeLump* ce_ptr = dynamic_cast<CompositeLump*>(tb_ptr);
+    if( ve_ptr || ce_ptr )
+    {
+      ve_list.append( tb_ptr );
+    }
+  }
+  
+  if (!children_too) return;
+  DLIList<TopologyBridge*> child_list;
+  
+  DLIList<RefFace*> face_list;
+  volume_ptr->ref_faces( face_list );
+  DLIList<BasicTopologyEntity*> temp_face_list;
+  CAST_LIST_TO_PARENT( face_list, temp_face_list );
+  bte_list.merge_unique( temp_face_list );
+//  bte_list.merge_unique( face_list );
+  for( i = bte_list.size();i > 0;i--)
+  {
+    child_list.clean_out();
+    get_VEs( bte_list.get_and_step(), child_list, visible );
+    ve_list.merge_unique( child_list );
+  }
+}
+
+void VirtualQueryEngine::get_VEs( RefFace* face_ptr,
+                                     DLIList<TopologyBridge*>& ve_list,
+                                     CubitBoolean visible,
+                                     const CubitBoolean children_too )
+{
+#ifdef BOYD17
+  DLIList<BasicTopologyEntity*> tmp_list, bte_list;
+#endif 
+  DLIList<BasicTopologyEntity*> bte_list;
+  DLIList<TopologyBridge*> tb_list;
+  int i;
+  
+  face_ptr->bridge_manager()->get_bridge_list( tb_list );
+  tb_list.reset();
+  
+  for( i = tb_list.size(); i--; )
+  {
+  
+    TopologyBridge* ve_ptr = tb_list.get_and_step();
+    if( dynamic_cast<PartitionEntity*>(ve_ptr) ||
+        dynamic_cast<CompositeSurface*>(ve_ptr) )
+    {
+      ve_list.append( ve_ptr );
+    }
+  }
+  
+  
+  if (!children_too) return;
+
+  DLIList<TopologyBridge*> child_list;
+  DLIList<RefEdge*> edge_list;
+  face_ptr->ref_edges( edge_list );
+  DLIList<BasicTopologyEntity*> temp_edge_list;
+  CAST_LIST_TO_PARENT( edge_list, temp_edge_list );
+  bte_list.merge_unique( temp_edge_list );
+
+  for( i = bte_list.size();i > 0;i--)
+  {
+    child_list.clean_out();
+    get_VEs( bte_list.get_and_step(), child_list, visible );
+    ve_list.merge_unique( child_list );
+  }
+}
+
+void VirtualQueryEngine::get_VEs( RefEdge* edge_ptr,
+                                     DLIList<TopologyBridge*>& ve_list,
+                                     CubitBoolean visible,
+                                     const CubitBoolean children_too )
+{
+#ifdef BOYD17
+  DLIList<BasicTopologyEntity*> tmp_list, bte_list;
+#endif
+  DLIList<BasicTopologyEntity*> bte_list;
+  DLIList<TopologyBridge*> tb_list;
+  int i;
+  
+  edge_ptr->bridge_manager()->get_bridge_list( tb_list );
+  tb_list.reset();
+  
+  for( i = tb_list.size(); i--; )
+  {
+  
+    TopologyBridge* ve_ptr = tb_list.get_and_step();
+    if( dynamic_cast<PartitionCurve*>(ve_ptr) ||
+        dynamic_cast<CompositeCurve*>(ve_ptr) )
+    {
+      ve_list.append( ve_ptr );
+    }
+  }
+  
+  if (!children_too) return;
+  DLIList<TopologyBridge*> child_list;
+  DLIList<RefVertex*> vex_list;
+  edge_ptr->ref_vertices( vex_list );
+  DLIList<BasicTopologyEntity*> temp_vex_list;
+  CAST_LIST_TO_PARENT( vex_list, temp_vex_list );
+  bte_list.merge_unique( temp_vex_list );
+
+  for( i = bte_list.size();i > 0;i--)
+  {
+    child_list.clean_out();
+    get_VEs( bte_list.get_and_step(), child_list, visible );
+    ve_list.merge_unique( child_list );
+  }
+}
+
+void VirtualQueryEngine::get_VEs( RefVertex* vex_ptr,
+                                     DLIList<TopologyBridge*>& ve_list,
+                                     CubitBoolean ,
+                                     const CubitBoolean )
+{
+  DLIList<TopologyBridge*> tb_list;
+  vex_ptr->bridge_manager()->get_bridge_list( tb_list );
+  tb_list.reset();
+  for( int i = tb_list.size(); i--; )
+  {
+    TopologyBridge* tb = tb_list.get_and_step();
+    if( dynamic_cast<PartitionPoint*>(tb) ||
+        dynamic_cast<CompositePoint*>(tb) )
+      ve_list.append( tb );
+  }
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : check if the entity is virtual or has virtual entities. 
+//
+// Special Notes : all is_virtual entity, has_virtual = true
+//                 only body, refvolume, refface can be non-virtual but has
+//                 virtual.
+//
+// Creator       : Jane Hu
+//
+// Creation Date : 10/01/04
+//-------------------------------------------------------------------------
+CubitBoolean VirtualQueryEngine::has_virtual(TopologyEntity* te_ptr)
+{
+  if (te_ptr == NULL)
+    return CUBIT_FALSE;
+  
+  if (is_virtual(te_ptr))
+    return CUBIT_TRUE;
+  
+    // check if children has partition or composite entities
+  int i;
+  Body      * body_ptr = CAST_TO (te_ptr, Body);
+  RefVolume * vol_ptr  = CAST_TO (te_ptr, RefVolume);
+  RefFace   * face_ptr = CAST_TO (te_ptr, RefFace);
+  CubitBoolean has_vir = CUBIT_FALSE;
+  
+  if (body_ptr != NULL)
+  {
+    DLIList<RefVolume*> vol_list;
+    te_ptr->ref_volumes(vol_list);
+    for (i = vol_list.size(); i > 0; i--)
+    {
+      if (has_virtual(vol_list.get_and_step()))
+      {
+        has_vir = CUBIT_TRUE;
+        break;
+      }
+    }
+  }
+                                                                                
+  if (vol_ptr != NULL)
+  {
+    DLIList<RefFace*> face_list;
+    te_ptr->ref_faces(face_list);
+    for (i = face_list.size(); i > 0; i --)
+    {
+       if (has_virtual(face_list.get_and_step()))
+       { 
+         has_vir = CUBIT_TRUE;
+         break;
+       }
+    }
+  }
+                                                                                
+  if (face_ptr != NULL)
+  {
+    DLIList<RefEdge *> edge_list;
+    te_ptr->ref_edges(edge_list);
+    for (i = edge_list.size(); i > 0; i --)
+    {
+       if (is_virtual(edge_list.get_and_step()))
+       {
+         has_vir = CUBIT_TRUE;
+         break;
+       }
+    }
+  }
+
+  return has_vir;
+} 
+
+CubitBoolean VirtualQueryEngine::is_virtual(TopologyEntity *entity,
+                                               const CubitBoolean children_too)
+//Check if a TopologyEntity has any topologyBridge that is composite or 
+//partition type.
+{
+  if ( entity == NULL )
+      return CUBIT_FALSE;
+  
+  if (CAST_TO(entity, Body) !=NULL)
+  {
+     int i;
+     DLIList<TopologyBridge*> list;
+     entity->bridge_manager()->get_bridge_list(list);
+     TopologyBridge * tb;
+     for (i = list.size(); i > 0; i--)
+     {
+        tb =  list.get_and_step();
+        if (CAST_TO(tb, PartitionBody) != NULL ||
+            CAST_TO(tb, CompositeBody) != NULL)
+           return CUBIT_TRUE;
+      }
+  }
+
+  DLIList<TopologyBridge*> ve_list;
+  get_VEs(entity, ve_list, CUBIT_TRUE, children_too);
+  return (ve_list.size() ? CUBIT_TRUE : CUBIT_FALSE);
+}
+
+CubitBoolean VirtualQueryEngine::is_virtual(DLIList<Body*> &entity_list,
+                                               const CubitBoolean children_too)
+{
+  if (!children_too) return CUBIT_FALSE;
+                                                                                
+  int i;
+  for (i = entity_list.size(); i > 0; i--)
+    if (is_virtual(entity_list.get_and_step(), children_too)) return CUBIT_TRUE;                                                                                
+  return CUBIT_FALSE;
+}
+
+CubitBoolean VirtualQueryEngine::is_virtual(DLIList<RefEntity*> &entity_list,
+                                               const CubitBoolean children_too)
+{
+  int i;
+  for (i = entity_list.size(); i > 0; i--) {
+    RefEntity *ref_entity = entity_list.get_and_step();
+    if (is_virtual(CAST_TO(ref_entity, TopologyEntity), children_too)) return CUBIT_TRUE;
+  }
+                                                                                
+  return CUBIT_FALSE;
+}
+
+//-------------------------------------------------------------------------
+// Purpose	 : Sort a DLList of RefEdges to be used in the construction
+//		   of a CompositeCurve.
+//
+// Special Notes : Sorted using topological information
+//
+// Creator	 : Jason Kraftcheck
+//
+// Creation Date : 08/04/97
+//-------------------------------------------------------------------------
+CubitStatus VirtualQueryEngine::sort_edges( 
+  DLIList<RefEdge*>& edge_list ) const
+{
+  DLIList<RefEdge*> sorted_edge_list;
+  RefEdge *first, *current = NULL, *prev;
+  CubitStatus return_value = CUBIT_SUCCESS;
+  
+  if( edge_list.size( ) <= 0 )
+  {
+    return CUBIT_FAILURE;
+  }
+  
+  if( edge_list.size() == 1 )
+  {
+    return CUBIT_SUCCESS;
+  }
+  
+    //Note: this part badly needs some optimization.  Given the array-based
+    // implementation of the DLList class, this is a very inefficient
+    // approach to sorting the edges.  Look into a different seach
+    // algorithm, and possible switching functions in DLList.
+  
+    //add first Curve
+  edge_list.reset( );
+  first = prev = edge_list.remove( );
+  sorted_edge_list.append( first );
+  
+    //sort the rest of the Curves
+  int i;
+  for( i = 0; i < edge_list.size( ); i++ ) //loop for each remaining RefEdge
+  {
+    edge_list.reset( );
+      //look through list for next RefEdge
+    for( int j = 0; j < edge_list.size( ); j++ )
+    {
+      current = edge_list.get( );
+      if( prev->common_ref_vertex( current ) != NULL )
+      {
+        edge_list.remove( );
+        sorted_edge_list.append( current );
+        i--; //edge_list.size() decreases with removal of edge
+        prev = current;
+        break;
+      }
+      else if( first->common_ref_vertex( current ) != NULL )
+      {
+        edge_list.remove( );
+        sorted_edge_list.insert_first( current );
+        first = current;
+        i--; //edge_list.size() decreases with removal of edge
+        break;
+      }
+      else
+      {
+        edge_list.step( );
+      }
+    }//end for(j)
+  }//end for(i)
+  
+    //check if all the RefEdges got sorted
+  if( edge_list.size( ) > 0 )
+  {
+    return_value =  CUBIT_FAILURE;
+    
+      //Sort the rest of the edges anyway, for use by
+      //other functions than composite edge creation.
+    
+    sort_edges( edge_list );
+    edge_list.reset( );
+    for( i = 0; i < edge_list.size(); i++ )
+    {
+      current = edge_list.get_and_step( );
+      sorted_edge_list.append( current );
+    }
+  }
+  else
+  {
+    return_value = CUBIT_SUCCESS;
+  }
+  
+  edge_list.clean_out( );
+  edge_list = sorted_edge_list;
+  edge_list.reset( );
+  return return_value;
+}
+
+
+
+// ********** BEGIN PRIVATE FUNCTIONS      **********
+
+//-------------------------------------------------------------------------
+// Purpose: Display a default error message for certain inherited functions
+//-------------------------------------------------------------------------
+void VirtualQueryEngine::default_error_message( 
+  const char callers_name[] ) const
+{
+  PRINT_ERROR("A call was made to:\n");
+  PRINT_ERROR("VirtualQueryEngine::");
+  PRINT_ERROR(callers_name);
+  PRINT_ERROR("\n");
+  PRINT_ERROR("Although this function is inhereted from GeometryQueryEngine\n");
+  PRINT_ERROR("it is not applicable or implememtend in VirtualQueryEngine.\n");
+  PRINT_ERROR("\nTHIS IS A BUG.  This function should NEVER be called.\n");
+  PRINT_ERROR("\nThis function exists only because it is pure virtual in\n");
+  PRINT_ERROR("the abstract class GeometryQueryEngine, and must be\n");
+  PRINT_ERROR("defined in VirtualQueryEngine for the class to be\n");
+  PRINT_ERROR("instantiated.\n");
+}
+
+// ********** END PRIVATE FUNCTIONS        **********
+
+// ********** BEGIN HELPER CLASSES         **********
+// ********** END HELPER CLASSES           **********
+
+// ********** BEGIN EXTERN FUNCTIONS       **********
+// ********** END EXTERN FUNCTIONS         **********
+
+// ********** BEGIN STATIC FUNCTIONS       **********
+// ********** END STATIC FUNCTIONS         **********
+
+
+	
+CubitStatus 
+VirtualQueryEngine::get_intersections( Curve* , Curve* ,
+                                         DLIList<CubitVector*>& /*intersection_list*/,
+                                         CubitBoolean /*bounded*/,
+                                         CubitBoolean /*closest*/ )
+{
+  return CUBIT_FAILURE;
+}
+
+CubitStatus
+VirtualQueryEngine::get_intersections(Curve* curve, CubitVector &point1,
+                                         CubitVector &point2,
+                                         DLIList<CubitVector*>& intersection_list,
+                                         CubitBoolean bounded,
+                                         CubitBoolean closest )
+{
+  DLIList<TopologyBridge*> curve_list;
+  get_underlying_curves( curve, curve_list );
+  int i;
+  for (i = 0; i < curve_list.size(); i++)
+  {
+    // Get the next curve and its GME
+    Curve* curve_ptr = CAST_TO(curve_list.get_and_step(), Curve);
+    GeometryQueryEngine* GQE_ptr =
+      curve_ptr->get_geometry_query_engine();
+    GQE_ptr->get_intersections(curve_ptr, point1, point2, intersection_list,
+                               bounded, closest);
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus 
+VirtualQueryEngine::get_intersections( Curve*, Surface*,
+                                          DLIList<CubitVector*>& /* intersection_list */,
+                                          CubitBoolean /* bounded */)
+{
+   return CUBIT_FAILURE;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : This function get underlying curves for virtual curves
+//
+// Special Notes :
+//
+// Creator       : Jane Hu
+//
+// Creation Date :
+//-------------------------------------------------------------------------
+CubitStatus VirtualQueryEngine::get_underlying_curves(Curve * curve_ptr,
+                                        DLIList<TopologyBridge*>& curve_list)
+{
+   assert (curve_ptr);
+   CompositeCurve *comp_curve = CAST_TO(curve_ptr, CompositeCurve);
+   PartitionCurve *part_curve = CAST_TO(curve_ptr, PartitionCurve);
+   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)
+         curve_list.append_unique(CAST_TO(comp_curve->get_curve(i),
+                                  TopologyBridge));
+       else
+       {
+         if(dynamic_cast<Curve*>(part_curve->partitioned_entity()))
+         {
+           curve_list.append_unique(CAST_TO(part_curve->partitioned_entity(),
+                                    TopologyBridge));
+         }
+       }
+     }
+   }
+   else if ( part_curve )
+     curve_list.append(CAST_TO(part_curve->partitioned_entity(),
+                       TopologyBridge));
+   return CUBIT_SUCCESS;
+}
+
+CubitStatus VirtualQueryEngine::get_underlying_surfaces(Surface * surf_ptr,
+                                        DLIList<TopologyBridge*>& surf_list)
+{
+   assert (surf_ptr);
+   CompositeSurface *comp_surf = CAST_TO(surf_ptr, CompositeSurface);
+   PartitionSurface *part_surf = CAST_TO(surf_ptr, PartitionSurface);
+   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)
+         surf_list.append_unique(CAST_TO(comp_surf->get_surface(i),
+                                  TopologyBridge));
+       else
+       {
+         if(dynamic_cast<Surface*>(part_surf->partitioned_entity()))
+         {
+           surf_list.append_unique(CAST_TO(part_surf->partitioned_entity(),
+                                    TopologyBridge));
+         }
+       }
+     }
+   }
+   else if ( part_surf )
+     surf_list.append(CAST_TO(part_surf->partitioned_entity(),
+                       TopologyBridge));
+   return CUBIT_SUCCESS;
+}
+
+//================================================================================
+// Description: Find extrema position on an entity list
+// Author     : 
+// Date       : 
+//================================================================================
+CubitStatus 
+VirtualQueryEngine::entity_extrema( DLIList<GeometryEntity*> &, 
+                                       const CubitVector *, 
+                                       const CubitVector *,
+                                       const CubitVector *, 
+                                       CubitVector &,
+                                       GeometryEntity *& )
+{
+  PRINT_ERROR("Entity extrema calculation not yet supported for virtual geometry.\n");
+  return CUBIT_FAILURE;
+}
+ 
+//================================================================================
+// Description: Find distance between two entities and closest positions.
+// Author     : 
+// Date       : 
+//================================================================================
+CubitStatus
+VirtualQueryEngine::entity_entity_distance( GeometryEntity *ge1,
+                                           GeometryEntity *ge2,
+                                           CubitVector &p1, CubitVector &p2,
+                                           double &distance )
+{
+  CompositeCurve *cc1 = dynamic_cast<CompositeCurve*>(ge1);
+  CompositeCurve *cc2 = dynamic_cast<CompositeCurve*>(ge2);
+  CompositeSurface *cs1 = dynamic_cast<CompositeSurface*>(ge1);
+  CompositeSurface *cs2 = dynamic_cast<CompositeSurface*>(ge2);
+
+  DLIList<GeometryEntity*> geometry_entities_1;
+  DLIList<GeometryEntity*> geometry_entities_2;
+  DLIList<GeometryQueryEngine*> gqes_1;
+  DLIList<GeometryQueryEngine*> gqes_2;
+
+  int i, j;
+  int still_ok = 1;
+
+  if(cc1)
+  {
+    for(i=cc1->num_curves()-1; i>-1 && still_ok; i--)
+    {
+      GeometryEntity *ge = cc1->get_curve(i);
+      if(dynamic_cast<PartitionEntity*>(ge))
+        still_ok = 0;
+      GeometryQueryEngine *gqe = ge->get_geometry_query_engine();
+      geometry_entities_1.append(ge);
+      gqes_1.append(gqe);
+    }
+  }
+  else if(cs1)
+  {
+    for(i=cs1->num_surfs()-1; i>-1 && still_ok; i--)
+    {
+      GeometryEntity *ge = cs1->get_surface(i);
+      if(dynamic_cast<PartitionEntity*>(ge))
+        still_ok = 0;
+      GeometryQueryEngine *gqe = ge->get_geometry_query_engine();
+      geometry_entities_1.append(ge);
+      gqes_1.append(gqe);
+    }
+  }
+  else
+  {
+    if(dynamic_cast<PartitionEntity*>(ge1))
+      still_ok = 0;
+    else if(dynamic_cast<Curve*>(ge1) || dynamic_cast<Surface*>(ge1))
+    {
+      GeometryQueryEngine *gqe = ge1->get_geometry_query_engine();
+      geometry_entities_1.append(ge1);
+      gqes_1.append(gqe);
+    }
+    else
+    {
+      PRINT_ERROR("Entity-entity distance not yet supported for virtual geometry.\n");
+      return CUBIT_FAILURE;
+    }
+  }
+  if(cc2)
+  {
+    for(i=cc2->num_curves()-1; i>-1 && still_ok; i--)
+    {
+      GeometryEntity *ge = cc2->get_curve(i);
+      if(dynamic_cast<PartitionEntity*>(ge))
+        still_ok = 0;
+      GeometryQueryEngine *gqe = ge->get_geometry_query_engine();
+      geometry_entities_2.append(ge);
+      gqes_2.append(gqe);
+    }
+  }
+  else if(cs2)
+  {
+    for(i=cs2->num_surfs()-1; i>-1 && still_ok; i--)
+    {
+      GeometryEntity *ge = cs2->get_surface(i);
+      if(dynamic_cast<PartitionEntity*>(ge))
+        still_ok = 0;
+      GeometryQueryEngine *gqe = ge->get_geometry_query_engine();
+      geometry_entities_2.append(ge);
+      gqes_2.append(gqe);
+    }
+  }
+  else
+  {
+    if(dynamic_cast<PartitionEntity*>(ge2))
+      still_ok = 0;
+    else if(dynamic_cast<Curve*>(ge2) || dynamic_cast<Surface*>(ge2))
+    {
+      GeometryQueryEngine *gqe = ge2->get_geometry_query_engine();
+      geometry_entities_2.append(ge2);
+      gqes_2.append(gqe);
+    }
+    else
+    {
+      PRINT_ERROR("Entity-entity distance not yet supported for virtual geometry.\n");
+      return CUBIT_FAILURE;
+    }
+  }
+
+  if(still_ok)
+  {
+    double smallest_distance = CUBIT_DBL_MAX;
+    for(i=geometry_entities_1.size(); i--;)
+    {
+      GeometryEntity *ge1 = geometry_entities_1.get_and_step();
+      GeometryQueryEngine *gqe1 = gqes_1.get_and_step();
+      for(j=geometry_entities_2.size(); j--;)
+      {
+        GeometryEntity *ge2 = geometry_entities_2.get_and_step();
+        GeometryQueryEngine *gqe2 = gqes_2.get_and_step();
+
+        CubitVector cur_pos1, cur_pos2;
+        double cur_distance;
+
+        gqe1->entity_entity_distance(ge1, ge2, cur_pos1, cur_pos2, cur_distance);
+
+        if(cur_distance < smallest_distance)
+        {
+          smallest_distance = cur_distance;
+          distance = cur_distance;
+          p1 = cur_pos1;
+          p2 = cur_pos2;
+        }
+      }
+    }
+  }
+  else
+  {
+    PRINT_ERROR("Entity-entity distance not yet supported for virtual geometry.\n");
+    return CUBIT_FAILURE;
+  }
+
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Remove all possible virtual geometry.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 06/28/00
+//-------------------------------------------------------------------------
+void VirtualQueryEngine::remove_virtual_geometry( RefEntity* entity_ptr,
+                                             CubitBoolean all_children )
+{
+  if ( Body* body_ptr = dynamic_cast<Body*>(entity_ptr) )
+    remove_virtual_geometry(body_ptr, all_children);
+  else if( RefVolume* vol_ptr = dynamic_cast<RefVolume*>(entity_ptr) )
+    remove_virtual_geometry(vol_ptr, all_children);
+  else if( RefFace* face_ptr = dynamic_cast<RefFace*>(entity_ptr) )
+    remove_virtual_geometry(face_ptr);
+}
+
+void VirtualQueryEngine::remove_virtual_geometry( Body* body_ptr,
+                                             bool all_children )
+{
+  int i;
+  DLIList<RefVolume*> volumes, part_results;
+  body_ptr->ref_volumes(volumes);
+  for ( i = volumes.size(); i--; ) {
+    RefVolume* vol = volumes.step_and_get();
+    if ( ! dynamic_cast<PartitionLump*>(vol->get_lump_ptr()) )
+      volumes.change_to(0);
+  }
+  volumes.remove_all_with_value(0);
+  if ( volumes.size() )
+    PartitionTool::instance()->unpartitionAll(volumes, part_results);
+  
+  if ( !all_children )
+    return;
+    
+  volumes.clean_out();
+  body_ptr->ref_volumes(volumes);
+  for ( i = volumes.size(); i--; )
+    remove_virtual_geometry( volumes.step_and_get(), true );
+}
+
+void VirtualQueryEngine::remove_virtual_geometry( RefVolume* vol_ptr,
+                                             bool all_children )
+{
+  int i;
+  DLIList<RefFace*> faces, part_results;
+  vol_ptr->ref_faces( faces );
+  for ( i = faces.size(); i--; ) {
+    if ( dynamic_cast<CompositeSurface*>(faces.step_and_get()->get_surface_ptr()) )
+      CompositeTool::instance()->uncomposite(faces.get());
+  }
+  
+  faces.clean_out();
+  vol_ptr->ref_faces( faces );
+  for ( i = faces.size(); i--; ) {
+    if ( !dynamic_cast<PartitionSurface*>(faces.step_and_get()->get_surface_ptr()))
+      faces.change_to(0);
+  }
+  faces.remove_all_with_value(0);
+  if ( faces.size() )
+    PartitionTool::instance()->unpartitionAll(faces, part_results);
+  
+  if ( !all_children )  
+    return;
+  
+  faces.clean_out();
+  vol_ptr->ref_faces( faces );
+  for ( i = faces.size(); i--; )
+    remove_virtual_geometry( faces.step_and_get() );
+}
+
+void VirtualQueryEngine::remove_virtual_geometry( RefFace* face_ptr )
+{
+  int i;
+  DLIList<RefEdge*> edges, part_results;
+  face_ptr->ref_edges( edges );
+  for ( i = edges.size(); i--; ) {
+    if ( dynamic_cast<CompositeCurve*>(edges.step_and_get()->get_curve_ptr()) )
+      CompositeTool::instance()->uncomposite(edges.get());
+  }
+  
+  edges.clean_out();
+  face_ptr->ref_edges( edges );
+  for ( i = edges.size(); i--; ) {
+    if ( !dynamic_cast<PartitionCurve*>(edges.step_and_get()->get_curve_ptr()))
+      edges.change_to(0);
+  }
+  edges.remove_all_with_value(0);
+  if ( edges.size() )
+    PartitionTool::instance()->unpartitionAll(edges, part_results);
+}
+  
+   
+  
+       
+CubitStatus VirtualQueryEngine::export_solid_model( DLIList<TopologyBridge*>& ,
+                                        const char* ,
+                                        const char* ,
+                                        const CubitString &,
+                                                       const char* )  
+{
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::save_temp_geom_file( DLIList<TopologyBridge*>& ,
+                                        const char* ,
+                                        const CubitString &,
+                                        CubitString &, 
+                                        CubitString &) 
+{
+  return CUBIT_FAILURE;
+}
+  
+CubitStatus VirtualQueryEngine::import_temp_geom_file(FILE* , 
+                                 const char* ,
+                                 const char* ,
+                                 DLIList<TopologyBridge*> &)
+{ return CUBIT_FAILURE; }
+
+CubitStatus VirtualQueryEngine::import_solid_model(
+                                                      const char* ,
+                                                      const char* ,
+                                                      DLIList<TopologyBridge*>&,
+                                                      CubitBoolean ,
+                                                      const char* ,
+                                                      CubitBoolean ,
+                                                      CubitBoolean ,
+                                                      CubitBoolean ,
+                                                      CubitBoolean ,
+                                                      CubitBoolean ,
+                                                      CubitBoolean  )  
+{
+  PRINT_INFO("VirtualQueryEngine::import_solid_model\n");
+  
+  default_error_message( "import_solid_model()");
+  return CUBIT_FAILURE;
+}
+
+void VirtualQueryEngine::delete_solid_model_entities(DLIList<BodySM*>& list) const
+{
+  for ( int i = list.size(); i--; )
+    delete_solid_model_entities( list.get_and_step() );
+}
+      
+
+
+CubitStatus VirtualQueryEngine::delete_solid_model_entities(
+  BodySM* bodysm ) const
+{ 
+  CompositeBody* compbod = dynamic_cast<CompositeBody*>(bodysm);
+  if (compbod)
+  {
+    while (compbod->num_bodies())
+    {
+      BodySM* dead_body = compbod->get_body( compbod->num_bodies() - 1 );
+      dead_body->get_geometry_query_engine()->delete_solid_model_entities( dead_body );
+    }
+  
+    CompositeEngine::instance().clean_out_deactivated_geometry();
+    return CUBIT_SUCCESS;
+  }
+  
+  
+  PartitionBody* bod = dynamic_cast<PartitionBody*>(bodysm);
+  if ( !bod )
+    return CUBIT_FAILURE;
+  
+  PartitionEngine::instance().delete_solid_model_entities( bod, bodysm );
+  if ( bodysm ) {
+    bodysm->get_geometry_query_engine()->delete_solid_model_entities(bodysm);
+  }
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus VirtualQueryEngine::delete_solid_model_entities(
+  Surface* surf_ptr ) const
+{
+  PartitionSurface* ps_ptr = dynamic_cast<PartitionSurface*>(surf_ptr);
+  CompositeSurface* cs_ptr = dynamic_cast<CompositeSurface*>(surf_ptr);
+  
+  if (cs_ptr)
+  {
+    while(cs_ptr->num_surfs())
+    {
+      Surface* dead_surf = cs_ptr->get_surface(cs_ptr->num_surfs()-1);
+      dead_surf->get_geometry_query_engine()->delete_solid_model_entities(dead_surf);
+    }
+    
+    CompositeEngine::instance().clean_out_deactivated_geometry();
+  }
+  
+  else if( ps_ptr )
+  {
+    PartitionEngine::instance().delete_solid_model_entities( ps_ptr, surf_ptr );
+    if ( surf_ptr )
+      surf_ptr->get_geometry_query_engine()->delete_solid_model_entities(surf_ptr);
+  }
+  
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus VirtualQueryEngine::delete_solid_model_entities(
+  Curve* curve_ptr ) const
+{
+  CompositeCurve* cc_ptr = dynamic_cast<CompositeCurve*>(curve_ptr);
+  PartitionCurve* pc_ptr = dynamic_cast<PartitionCurve*>(curve_ptr);
+
+  if( cc_ptr )
+  {
+    while(cc_ptr->num_curves())
+    {
+      Curve* dead_curv = cc_ptr->get_curve(cc_ptr->num_curves()-1);
+      dead_curv->get_geometry_query_engine()->delete_solid_model_entities(dead_curv);
+    }
+    
+    CompositeEngine::instance().clean_out_deactivated_geometry();
+  }
+  else if( pc_ptr )
+  {
+    PartitionEngine::instance().delete_solid_model_entities( pc_ptr, curve_ptr );
+    if ( curve_ptr )
+      curve_ptr->get_geometry_query_engine()->delete_solid_model_entities(curve_ptr);
+  }
+ 
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus VirtualQueryEngine::delete_solid_model_entities( Point* ) const
+{
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::fire_ray(BodySM *,
+                                            const CubitVector &,
+                                            const CubitVector &,
+                                            DLIList<double>& ,
+                                            DLIList<GeometryEntity*> *) const
+{
+  PRINT_INFO("VirtualQueryEngine::fire_ray\n");
+  
+  default_error_message( "fire_ray()");
+  return CUBIT_FAILURE;
+}
+
+double VirtualQueryEngine::get_sme_resabs_tolerance() const
+{
+  return GEOMETRY_RESABS;
+}
+
+double VirtualQueryEngine::set_sme_resabs_tolerance( double )
+{
+  PRINT_INFO("VirtualQueryEngine::set_sme_resabs_tolerance\n");
+  
+  default_error_message( "set_sme_resabs_tolerance()");
+  return 0;
+}
+
+CubitStatus VirtualQueryEngine::set_int_option( const char* , int )
+{
+  PRINT_INFO("VirtualQueryEngine::set_int_option\n");
+  
+  default_error_message( "set_int_option()");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::set_dbl_option( const char* , double )
+{
+  PRINT_INFO("VirtualQueryEngine::set_dbl_option\n");
+  
+  default_error_message( "set_dbl_option()");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::set_str_option( const char* , const char* )
+{
+  PRINT_INFO("VirtualQueryEngine::set_str_option\n");
+  
+  default_error_message( "set_str_option()");
+  return CUBIT_FAILURE;
+}
+
+void VirtualQueryEngine::register_attributes()
+{
+  CubitStatus result;
+  result = CGMApp::instance()->attrib_manager()->register_attrib_type(
+                                               CA_PARTITION_VG, "partition vg", "PARTITION_VG",
+                                               CAPartitionVG_creator, CUBIT_FALSE,
+                                               CUBIT_FALSE, CUBIT_TRUE, CUBIT_TRUE,
+                                               CUBIT_FALSE, CUBIT_FALSE);
+  assert (CUBIT_SUCCESS == result);
+
+  result = CGMApp::instance()->attrib_manager()->register_attrib_type(
+                                               CA_COMPOSITE_VG, "composite vg", "COMPOSITE_VG",
+                                               CACompositeVG_creator, CUBIT_FALSE,
+                                               CUBIT_FALSE, CUBIT_TRUE, CUBIT_TRUE,
+                                               CUBIT_FALSE, CUBIT_FALSE);
+  assert (CUBIT_SUCCESS == result);
+
+  result = CGMApp::instance()->attrib_manager()->register_attrib_type(
+                                               CA_VIRTUAL_VG, "virtual vg", "VIRTUAL_VG",
+                                               CAVirtualVG_creator, CUBIT_FALSE,
+                                               CUBIT_FALSE, CUBIT_TRUE, CUBIT_TRUE,
+                                               CUBIT_FALSE, CUBIT_FALSE);
+  assert (CUBIT_SUCCESS == result);
+
+}
+
+
+
+CubitStatus VirtualQueryEngine::translate( BodySM* body, 
+                                              const CubitVector& offset )
+{
+  if (PartitionBody* part = dynamic_cast<PartitionBody*>(body))
+    return PartitionEngine::instance().translate( part, offset );
+  else if(CompositeBody* comp = dynamic_cast<CompositeBody*>(body))
+    return CompositeEngine::instance().translate( comp, offset );
+
+  PRINT_ERROR("Non-virtual entity in VGE::translate.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::rotate   ( BodySM* body, 
+                                              const CubitVector& axis, 
+                                              double angle )
+{
+  if (PartitionBody* part = dynamic_cast<PartitionBody*>(body))
+    return PartitionEngine::instance().rotate( part, axis, angle );
+  else if(CompositeBody* comp = dynamic_cast<CompositeBody*>(body))
+    return CompositeEngine::instance().rotate( comp, axis, angle );
+
+  PRINT_ERROR("Non-virtual entity in VGE::rotate.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::scale    ( BodySM* body, 
+                                              double factor )
+{
+  return scale( body, CubitVector(factor,factor,factor) );
+}
+
+CubitStatus VirtualQueryEngine::scale    ( BodySM* body, 
+                                              const CubitVector& factors )
+{
+  if (PartitionBody* part = dynamic_cast<PartitionBody*>(body))
+    return PartitionEngine::instance().scale( part, factors );
+  else if(CompositeBody* comp = dynamic_cast<CompositeBody*>(body))
+    return CompositeEngine::instance().scale( comp, factors );
+
+  PRINT_ERROR("Non-virtual entity in VGE::scale.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::reflect  ( BodySM* body, 
+                                              const CubitVector& axis )
+{
+  if (PartitionBody* part = dynamic_cast<PartitionBody*>(body))
+    return PartitionEngine::instance().reflect( part, axis );
+  else if(CompositeBody* comp = dynamic_cast<CompositeBody*>(body))
+    return CompositeEngine::instance().reflect( comp, axis );
+
+  PRINT_ERROR("Non-virtual entity in VGE::reflect.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::restore_transform( BodySM* body )
+{
+  if (PartitionBody* part = dynamic_cast<PartitionBody*>(body))
+    return PartitionEngine::instance().restore_transform( part );
+  else if(CompositeBody* comp = dynamic_cast<CompositeBody*>(body))
+    return CompositeEngine::instance().restore_transform( comp );
+
+  PRINT_ERROR("Non-virtual entity in VGE::restore_transform.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::translate( GeometryEntity* ent, 
+                                              const CubitVector& offset )
+{
+  if (PartitionEntity* part = dynamic_cast<PartitionEntity*>(ent))
+    return PartitionEngine::instance().translate( part, offset );
+  else if(CompositeSurface* csurf = dynamic_cast<CompositeSurface*>(ent))
+    return CompositeEngine::instance().translate( csurf, offset );
+  else if(CompositeCurve* ccurve = dynamic_cast<CompositeCurve*>(ent))
+    return CompositeEngine::instance().translate( ccurve, offset );
+
+  PRINT_ERROR("Non-virtual entity in VGE::translate.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::rotate   ( GeometryEntity* ent, 
+                                              const CubitVector& axis, 
+                                              double degrees )
+{
+  if (PartitionEntity* part = dynamic_cast<PartitionEntity*>(ent))
+    return PartitionEngine::instance().rotate( part, axis, degrees );
+  else if(CompositeSurface* csurf = dynamic_cast<CompositeSurface*>(ent))
+    return CompositeEngine::instance().rotate( csurf, axis, degrees );
+  else if(CompositeCurve* ccurve = dynamic_cast<CompositeCurve*>(ent))
+    return CompositeEngine::instance().rotate( ccurve, axis, degrees );
+
+  PRINT_ERROR("Non-virtual entity in VGE::rotate.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::scale    ( GeometryEntity* ent, 
+                                              double factor )
+{
+  return scale( ent, CubitVector( factor, factor, factor ) );
+}
+
+CubitStatus VirtualQueryEngine::scale    ( GeometryEntity* ent, 
+                                              const CubitVector& factors )
+{
+  if (PartitionEntity* part = dynamic_cast<PartitionEntity*>(ent))
+    return PartitionEngine::instance().scale( part, factors );
+  else if(CompositeSurface* csurf = dynamic_cast<CompositeSurface*>(ent))
+    return CompositeEngine::instance().scale( csurf, factors );
+  else if(CompositeCurve* ccurve = dynamic_cast<CompositeCurve*>(ent))
+    return CompositeEngine::instance().scale( ccurve, factors );
+
+  PRINT_ERROR("Non-virtual entity in VGE::scale.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitStatus VirtualQueryEngine::reflect  ( GeometryEntity* ent, 
+                                              const CubitVector& axis )
+{
+  if (PartitionEntity* part = dynamic_cast<PartitionEntity*>(ent))
+    return PartitionEngine::instance().reflect( part, axis );
+  else if(CompositeSurface* csurf = dynamic_cast<CompositeSurface*>(ent))
+    return CompositeEngine::instance().reflect( csurf, axis );
+  else if(CompositeCurve* ccurve = dynamic_cast<CompositeCurve*>(ent))
+    return CompositeEngine::instance().reflect( ccurve, axis );
+
+  PRINT_ERROR("Non-virtual entity in VGE::reflect.\n");
+  return CUBIT_FAILURE;
+}
+
+CubitBoolean VirtualQueryEngine::bodies_overlap (BodySM *body_ptr_1, BodySM *body_ptr_2 ) const
+{
+  PartitionBody* partition_body1 = dynamic_cast<PartitionBody*>(body_ptr_1);
+  PartitionBody* partition_body2 = dynamic_cast<PartitionBody*>(body_ptr_2);
+
+  BodySM *body1 = body_ptr_1;
+  if( partition_body1 )
+    body1 = partition_body1->real_body();
+
+  BodySM *body2 = body_ptr_2;
+  if( partition_body2 )
+    body2 = partition_body2->real_body();
+  
+  GeometryQueryEngine *gqe = body1->get_geometry_query_engine();
+  if( gqe != body2->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->bodies_overlap( body1, body2 );
+
+}
+
+
Index: /cgm/geom/virtual/SubEntitySet.cpp
===================================================================
--- /cgm/geom/virtual/SubEntitySet.cpp (revision 1040)
+++ /cgm/geom/virtual/SubEntitySet.cpp (revision 1040)
@@ -0,0 +1,803 @@
+#include "VGDefines.h"
+#include "SubEntitySet.hpp"
+#include "PartitionEntity.hpp"
+#include "CoEdgeSM.hpp"
+#include "DLIList.hpp"
+#include "CubitSimpleAttrib.hpp"
+#include "TDUniqueId.hpp"
+#include "CubitVector.hpp"
+#include "PartitionEngine.hpp"
+#include "GeometryEntity.hpp"
+#include "PartitionBody.hpp"
+
+
+const char* const PARTITION_DATA_ATTRIB_NAME = "PARTITION_ATTRIB";
+const char* const PARTITION_GEOM_ATTRIB_NAME = "PARTITION_GEOM";
+const char* const PARTITION_UID_ATTRIB_NAME  = "PARTITION_UID";
+
+void SubEntitySet::strip_attributes( TopologyBridge* bridge )
+{
+  DLIList<CubitSimpleAttrib*> list;
+
+  bridge->get_simple_attribute( PARTITION_DATA_ATTRIB_NAME, list );
+  while ( list.size() )
+  {
+    CubitSimpleAttrib* csa = list.pop();
+    bridge->remove_simple_attribute_virt( csa );
+    delete csa;
+  }
+ 
+  bridge->get_simple_attribute( PARTITION_GEOM_ATTRIB_NAME, list );
+  while ( list.size() )
+  {
+    CubitSimpleAttrib* csa = list.pop();
+    bridge->remove_simple_attribute_virt( csa );
+    delete csa;
+  }
+ 
+  bridge->get_simple_attribute( PARTITION_UID_ATTRIB_NAME, list );
+  while ( list.size() )
+  {
+    CubitSimpleAttrib* csa = list.pop();
+    bridge->remove_simple_attribute_virt( csa );
+    delete csa;
+  }
+}
+  
+
+SubEntitySet::SubEntitySet( TopologyBridge* real_entity, 
+                            PartitionEntity* first_part )
+  : bodyNext(0), bodyPtr(0), subEntityHead(0), lowerOrderHead(0), lastId(0), 
+    layerNumber(SUBCOMP_PARTITION_LAYER), uniqueId(0)
+{
+//  if( real_entity->owner() )
+//    real_entity->owner()->swap_bridge( real_entity, 
+//        dynamic_cast<TopologyBridge*>(first_part) );
+  
+//  real_entity->owner( this );
+  myEntity = real_entity;
+  assert(!!myEntity);
+  
+    // Scan for existing partition geometry stored
+    // in attributes on the real entity.  We need
+    // to start new Ids after any existing ones
+    // to avoid conflicts as the stored entities
+    // are restored.
+  DLIList<CubitSimpleAttrib*> csa_list;
+  
+  real_entity->get_simple_attribute( PARTITION_GEOM_ATTRIB_NAME, csa_list );
+  while( csa_list.size() )
+  {
+    CubitSimpleAttrib* csa = csa_list.pop();
+    if( csa->character_type() == PARTITION_GEOM_ATTRIB_NAME )
+    {
+      csa->int_data_list()->reset();
+      int id = *csa->int_data_list()->get();
+      if( id > lastId )
+        lastId = id;
+    }
+    
+    delete csa;
+  }
+  
+  real_entity->get_simple_attribute( PARTITION_UID_ATTRIB_NAME, csa_list );
+  if ( csa_list.size() )
+  {
+    assert(csa_list.size() == 1);
+    CubitSimpleAttrib* csa = csa_list.pop();
+    //real_entity->remove_simple_attribute_virt(csa);
+    assert(csa->int_data_list()->size() == 1);
+    uniqueId = *csa->int_data_list()->get();
+    PartitionEngine::instance().add_to_id_map( this, uniqueId );
+    delete csa;
+  }
+  
+  // add first partition into the SubEntitySet's linked list
+  add_partition( first_part, 0 );
+  
+  csa_list.clean_out();
+  real_entity->get_simple_attribute( PARTITION_DATA_ATTRIB_NAME, csa_list );
+  while ( csa_list.size() )
+  {
+    CubitSimpleAttrib* csa = csa_list.pop();
+    real_entity->remove_simple_attribute_virt(csa);
+    wrap_attribute(csa, first_part->entitySetId );
+    real_entity->append_simple_attribute_virt(csa);
+    delete csa;
+  }
+}
+
+void SubEntitySet::unwrap_attributes()
+{
+  DLIList<CubitSimpleAttrib*> csa_list;
+  if ( myEntity) 
+    myEntity->get_simple_attribute( PARTITION_DATA_ATTRIB_NAME, csa_list );
+  while( csa_list.size() )
+  {
+    CubitSimpleAttrib* csa = csa_list.pop();
+    myEntity->remove_simple_attribute_virt(csa);
+    unwrap_attribute(csa);
+    myEntity->append_simple_attribute_virt(csa);
+    delete csa;
+  }
+}
+  
+
+int SubEntitySet::get_unique_id()
+{
+  if( uniqueId == 0 )
+  {
+    uniqueId = TDUniqueId::generate_unique_id();
+    CubitSimpleAttrib attrib( PARTITION_UID_ATTRIB_NAME, 0, 0, &uniqueId );
+    myEntity->append_simple_attribute_virt( &attrib );
+    PartitionEngine::instance().add_to_id_map( this, uniqueId );
+  }
+  return uniqueId;
+}
+
+SubEntitySet::~SubEntitySet()
+{
+  if( uniqueId )
+    PartitionEngine::instance().remove_from_id_map(this,uniqueId);
+  assert( subEntityHead == 0 && lowerOrderHead == 0 );
+  if( myEntity ) {
+    strip_attributes(myEntity);
+    if( myEntity->owner() == this )
+      myEntity->owner(0);
+  }
+    
+  if( bodyPtr )
+  {
+      // keep copy because calling bodyPtr->remove
+      // means that bodyPtr will become NULL
+    PartitionBody* body = bodyPtr;
+    body->remove(*this);
+
+    assert(body->entitySet != this);
+    if( !body->has_children() )
+    {
+      BodySM* real_body = body->real_body();
+      body->sub_entity_set().remove_bridge(real_body);
+      if( body->owner() )
+        body->owner()->swap_bridge( body, real_body, false );
+      delete body;
+    }
+  }
+}
+
+void SubEntitySet::add_lower_order( PartitionEntity* partition )
+{
+  assert( partition->entitySet == 0 &&
+          partition->entitySetNext == 0 );
+  partition->entitySet = this;
+  partition->entitySetNext = lowerOrderHead;
+  lowerOrderHead = partition;
+  partition->entitySetId = ++lastId;
+}
+
+void SubEntitySet::add_lower_order( PartitionEntity* partition,
+                                    CubitSimpleAttrib& attrib,
+                                    int dimension,
+                                    DLIList<CubitVector*>& points,
+                                    DLIList<int>& facets,
+                                    DLIList<int>& children,
+                                    DLIList<int>& point_owners )
+{
+  assert( partition->entitySet == 0 &&
+          partition->entitySetNext == 0 );
+          
+  int id, dim;
+  CubitStatus result = read_geometry( id, dim, points, facets, children, 
+                                      point_owners, attrib );
+  assert( result && dimension == dim );
+  
+  partition->entitySet = this;
+  partition->entitySetNext = lowerOrderHead;
+  lowerOrderHead = partition;
+  
+  partition->entitySetId = id;
+}
+/*
+void SubEntitySet::fix_duplicate_id( int id )
+{
+  for( int i = 0; i < 2; i++ )
+  {
+    PartitionEntit* list = i ? subEntityHead : lowerOrderHead;
+    for( ; list; list = list->entitySetNext )
+    {
+      if( list->entitySetId == id )
+        list->entitySetId = ++lastId;
+    }
+  }
+}
+*/
+void SubEntitySet::add_partition( PartitionEntity* partition,
+                                  PartitionEntity* after )
+{
+  assert( partition->entitySet == 0 && partition->entitySetNext == 0 );
+  partition->entitySet = this;
+  
+  if( after )
+  {
+    assert( after->entitySet == this );
+    partition->entitySetNext = after->entitySetNext;
+    after->entitySetNext = partition;
+  }
+  else
+  {
+    partition->entitySetNext = subEntityHead;
+    subEntityHead = partition;
+  }
+  partition->entitySetId = ++lastId;
+}
+
+
+void SubEntitySet::remove( PartitionEntity* partition )
+{
+  assert( partition->entitySet == this );
+  partition->entitySet = 0;
+  
+  if( lowerOrderHead == partition )
+  {
+    lowerOrderHead = partition->entitySetNext;
+  }
+  else if( subEntityHead == partition )
+  {
+    subEntityHead = partition->entitySetNext;
+  }
+  else
+  {
+    PartitionEntity* curr = subEntityHead;
+    while( curr && curr->entitySetNext != partition )
+      curr = curr->entitySetNext;
+    if( curr == 0 )
+    {  
+      curr = lowerOrderHead;
+      while( curr && curr->entitySetNext != partition )
+      	curr = curr->entitySetNext;
+    }
+    
+    assert( curr && curr->entitySetNext == partition );
+    curr->entitySetNext = partition->entitySetNext;
+  }
+  
+  partition->entitySetNext = 0;
+
+  if( !subEntityHead && !lowerOrderHead )
+  {
+    delete this;
+  }
+  
+  partition->entitySetId = 0;
+}
+
+CubitStatus SubEntitySet::bridge_destroyed( TopologyBridge* bridge )
+{
+  if( myEntity && myEntity == bridge )
+  {
+    if( myEntity->owner() == this )
+      myEntity->owner(0);
+    myEntity = 0;
+    return CUBIT_SUCCESS;
+  }
+  return CUBIT_FAILURE;
+}
+
+CubitStatus SubEntitySet::remove_bridge( TopologyBridge* bridge )
+{
+  if (myEntity && myEntity == bridge)
+  {
+    strip_attributes(myEntity);
+    return bridge_destroyed(myEntity);
+  }
+  return CUBIT_FAILURE;
+}
+
+CubitStatus SubEntitySet::swap_bridge( TopologyBridge* remove,
+                                       TopologyBridge* add,
+                                       bool reversed )
+{
+  if( remove_bridge( remove ) )
+  {
+    if( add->owner() )
+    {
+      add->owner()->remove_bridge( add );
+    }
+    add->owner(this);
+    myEntity = add;
+    if (reversed)
+      notify_reversed(add);
+    return CUBIT_SUCCESS;
+  }
+  return CUBIT_FAILURE;
+}
+
+void SubEntitySet::get_owners( DLIList<TopologyBridge*>& owner_list ) const
+{
+  for( PartitionEntity* ent = subEntityHead; ent; ent = ent->entitySetNext )
+    owner_list.append( dynamic_cast<TopologyBridge*>(ent) );
+    
+  CoEdgeSM* coedge = dynamic_cast<CoEdgeSM*>(get_entity());
+  if( coedge && coedge->sense() == CUBIT_REVERSED )
+    owner_list.reverse();
+}
+
+    
+bool SubEntitySet::has_multiple_sub_entities() const
+  { return subEntityHead && subEntityHead->entitySetNext; }
+
+void SubEntitySet::print_debug_info( const char* prefix ) const
+{
+  if( !prefix ) prefix = "";
+  
+  PRINT_INFO("%sSubEntitySet for %s %p\n", prefix, 
+    myEntity ? fix_type_name(typeid(*myEntity).name()) : "TopologyBridge", 
+    myEntity );
+
+  PRINT_INFO("%s  SubEntities:\n", prefix );
+  PartitionEntity* ent = subEntityHead;
+  while( ent )
+  {
+    PRINT_INFO("%s    %s %d (%p)\n", prefix, 
+      fix_type_name(typeid(*ent).name()), ent->entitySetId, ent );
+    ent = ent->entitySetNext;
+  }
+
+  PRINT_INFO("%s  Lower-order entities:\n", prefix );
+  ent = lowerOrderHead;
+  while( ent )
+  {
+    PRINT_INFO("%s    %s %d (%p)\n", prefix, 
+      fix_type_name(typeid(*ent).name()), ent->entitySetId, ent );
+    ent = ent->entitySetNext;
+  }
+  
+  PRINT_INFO("%s  Body: %p\n",prefix,  bodyPtr );
+}
+
+bool SubEntitySet::is_attribute( CubitSimpleAttrib* csa, int id ) const
+{
+  if( csa->string_data_list()->size() < 1 )
+    return false;
+
+  if( csa->character_type() != PARTITION_DATA_ATTRIB_NAME )
+    return false;
+  
+  assert( csa->int_data_list()->size() );
+  csa->int_data_list()->reset();
+  if( id && *csa->int_data_list()->get() != id )
+    return false;
+  
+  return true;
+}    
+
+CubitStatus SubEntitySet::wrap_attribute( CubitSimpleAttrib* csa, int id ) const
+{
+  if( is_attribute( csa ) )
+    return CUBIT_FAILURE;
+    
+  csa->string_data_list()->insert_first( new CubitString(PARTITION_DATA_ATTRIB_NAME) );
+  csa->int_data_list()->insert_first( new int(id) );
+  return CUBIT_SUCCESS;
+}
+
+int SubEntitySet::unwrap_attribute( CubitSimpleAttrib* csa ) const
+{
+  if( ! is_attribute( csa ) )
+    return 0;
+
+  csa->string_data_list()->reset();
+  delete csa->string_data_list()->remove();
+  csa->int_data_list()->reset();
+  int* id_ptr = csa->int_data_list()->remove();
+  int id = *id_ptr;
+  delete id_ptr;
+  
+  return id;
+}
+
+void SubEntitySet::add_attribute( PartitionEntity* entity, CubitSimpleAttrib* csa )
+{
+  assert( entity->entitySet == this );
+  
+  if( !myEntity )
+    return;
+  
+  if( wrap_attribute( csa, entity->entitySetId ) )
+  {
+    myEntity->append_simple_attribute_virt( csa );
+    unwrap_attribute( csa );
+  }
+}
+
+void SubEntitySet::rem_attribute( PartitionEntity* entity, CubitSimpleAttrib* csa )
+{
+  assert( entity->entitySet == this );
+  
+  if( !myEntity )
+    return;
+  
+  if( wrap_attribute( csa, entity->entitySetId ) )
+  {
+    myEntity->remove_simple_attribute_virt( csa );
+    unwrap_attribute( csa );
+  }
+}
+
+void SubEntitySet::get_attributes( PartitionEntity* entity,
+                                   DLIList<CubitSimpleAttrib*>& list )
+{
+  assert( entity->entitySet == this );
+  assert( !list.size() );
+  list.clean_out();
+  
+  if( !myEntity )
+    return;
+  
+  myEntity->get_simple_attribute( PARTITION_DATA_ATTRIB_NAME, list );
+  for( int i = list.size(); i--; )
+  {
+    CubitSimpleAttrib* csa = list.step_and_get();
+    if( is_attribute( csa, entity->entitySetId ) )
+    {
+      unwrap_attribute( csa );
+    }
+    else
+    {
+      delete csa;
+      list.change_to(0);
+    }
+  }
+  list.remove_all_with_value(0);
+}
+void SubEntitySet::get_attributes( PartitionEntity* entity, const char* name,
+                                   DLIList<CubitSimpleAttrib*>& list )
+{
+  get_attributes(entity,list);
+  
+  for ( int i = list.size(); i--; )
+    if ( list.step_and_get()->character_type() != name )
+    {
+      delete list.get();
+      list.change_to(0);
+    }
+    
+  list.remove_all_with_value(0);
+}
+
+void SubEntitySet::rem_all_attrib( PartitionEntity* entity )
+{
+  assert( entity->entitySet == this );
+  
+  if( !myEntity )
+    return;
+
+  DLIList<CubitSimpleAttrib*> dead_list;
+  myEntity->get_simple_attribute( PARTITION_DATA_ATTRIB_NAME, dead_list );
+  for( int i = dead_list.size(); i--; )
+  {
+    CubitSimpleAttrib* csa = dead_list.get_and_step();
+    if( is_attribute( csa, entity->entitySetId ) )
+      myEntity->remove_simple_attribute_virt( csa );
+    delete csa;
+  }
+}
+
+int SubEntitySet::get_id( PartitionEntity* entity ) const
+{
+  if( entity->entitySet != this )
+    return 0;
+  return entity->entitySetId;
+}
+
+PartitionEntity* SubEntitySet::entity_from_id( int id ) const
+{
+  PartitionEntity* ent;
+  for( ent = subEntityHead; ent; ent = ent->entitySetNext )
+    if( ent->entitySetId == id )
+      return ent;
+  for( ent = lowerOrderHead; ent; ent = ent->entitySetNext )
+    if( ent->entitySetId == id )
+      return ent;
+  return 0;
+}
+
+void SubEntitySet::get_sub_entities( DLIList<PartitionEntity*>& list ) const
+{
+  for( PartitionEntity* ent = subEntityHead; ent; ent = ent->entitySetNext )
+    list.append(ent);
+}
+
+
+void SubEntitySet::get_lower_order( DLIList<PartitionEntity*>& list ) const
+{
+  for( PartitionEntity* ent = lowerOrderHead; ent; ent = ent->entitySetNext )
+    list.append(ent);
+}
+
+void SubEntitySet::set_id( PartitionEntity* entity, int id )
+{
+  if( entity->entitySet != this )
+    assert(0);
+  else
+  {
+    entity->entitySetId = id;
+    if( id > lastId )
+      lastId = id;
+  }
+}
+
+void SubEntitySet::renumerate( int lowest_value, bool higher_only )
+{
+  lastId = lowest_value - 1;
+  
+  PartitionEntity* ent;
+  for( ent = subEntityHead; ent; ent = ent->entitySetNext )
+    if( !higher_only || ent->entitySetId >= lowest_value )
+      ent->entitySetId = ++lastId;
+  for( ent = lowerOrderHead; ent; ent = ent->entitySetNext )
+    if( !higher_only || ent->entitySetId >= lowest_value )
+      ent->entitySetId = ++lastId;
+}
+
+void SubEntitySet::notify_reversed( TopologyBridge* bridge )
+{
+  assert( !bridge || bridge == myEntity );
+  
+    // reverse list order (only really necessary for curves)
+  PartitionEntity* entity = subEntityHead;
+  subEntityHead = 0;
+  while( entity )
+  {
+    PartitionEntity* next = entity->entitySetNext;
+    entity->entitySetNext = subEntityHead;
+    subEntityHead = entity;
+    entity = next;
+  }
+  
+    // reverse the sense of all subentities
+  for( entity = subEntityHead; entity; entity = entity->entitySetNext )
+    entity->reverse_sense();  
+}    
+
+
+CubitStatus SubEntitySet::save_geometry( int id, int dimension, 
+                                         DLIList<CubitVector*>* point_list,
+                                         DLIList<int>* point_connectivity,
+                                         DLIList<int>* topo_connectivity,
+                                         DLIList<int>* point_owners,
+                                         CubitSimpleAttrib& attrib )
+{
+  int i;
+  int integer_count = 5;
+  int double_count = 0;
+  if( point_connectivity && point_connectivity->size() ) 
+  {
+    assert( point_list && point_owners );
+    integer_count += point_connectivity->size();
+    integer_count += point_owners->size();
+    double_count = point_list->size() * 3;
+    assert( point_owners->size() == 2 * point_list->size() );
+  }
+  else 
+  {
+    assert( !point_owners );
+    if ( point_list )
+      double_count = point_list->size() * 3;
+  }
+  if( topo_connectivity  ) integer_count +=  topo_connectivity->size();
+  
+  while( attrib.int_data_list()->size() > integer_count )
+    delete attrib.int_data_list()->pop();
+  while( attrib.int_data_list()->size() < integer_count )
+    attrib.int_data_list()->append( new int );
+  attrib.int_data_list()->reset();
+    
+  while( attrib.double_data_list()->size() > double_count )
+    delete attrib.double_data_list()->pop();
+  while( attrib.double_data_list()->size() < double_count )
+    attrib.double_data_list()->append( new double );
+  attrib.double_data_list()->reset();
+  
+  *attrib.int_data_list()->get_and_step() = id;
+  *attrib.int_data_list()->get_and_step() = dimension;
+  int point_list_size = point_list ? point_list->size() : 0;
+  *attrib.int_data_list()->get_and_step() = point_list_size;
+  int point_conn_size = point_connectivity ? point_connectivity->size() : 0;
+  *attrib.int_data_list()->get_and_step() = point_conn_size;
+  int topo_conn_size = topo_connectivity ? topo_connectivity->size() : 0;
+  *attrib.int_data_list()->get_and_step() = topo_conn_size;
+  
+  if( point_list )
+  {
+    point_list->reset();
+    for( i = point_list->size(); i--; )
+    {
+      CubitVector* p = point_list->get_and_step();
+      *attrib.double_data_list()->get_and_step() = p->x();
+      *attrib.double_data_list()->get_and_step() = p->y();
+      *attrib.double_data_list()->get_and_step() = p->z();
+      delete p;
+    }
+    point_list->clean_out();
+  }
+    
+  if( point_connectivity )
+  {
+    point_connectivity->reset();
+    for( i = point_connectivity->size(); i--; )
+      *attrib.int_data_list()->get_and_step() = point_connectivity->get_and_step();
+  }
+    
+  if( topo_connectivity )
+  {
+    topo_connectivity->reset();
+    for( i = topo_connectivity->size(); i--; )
+      *attrib.int_data_list()->get_and_step() = topo_connectivity->get_and_step();
+  }
+  
+  if ( point_owners )
+  {
+    point_owners->reset();
+    for ( i = point_owners->size(); i--; )
+      *attrib.int_data_list()->get_and_step() = point_owners->get_and_step();
+  }
+ 
+  myEntity->append_simple_attribute_virt( &attrib );
+
+  return CUBIT_SUCCESS;
+}
+
+
+CubitStatus SubEntitySet::read_geometry( int& id, int& dimension, 
+                                         DLIList<CubitVector*>& point_list,
+                                         DLIList<int>& point_connectivity,
+                                         DLIList<int>& topo_connectivity,
+                                         DLIList<int>& point_owners,
+                                         CubitSimpleAttrib& attrib )
+{
+  int i;
+  
+    // read metadata
+  attrib.int_data_list()->reset();
+  id              = *attrib.int_data_list()->get_and_step();
+  dimension       = *attrib.int_data_list()->get_and_step();
+  int point_count = *attrib.int_data_list()->get_and_step();
+  int conn_count  = *attrib.int_data_list()->get_and_step();
+  int topo_count  = *attrib.int_data_list()->get_and_step();
+  int owner_count = conn_count ? 2 * point_count : 0;
+  
+    // consistancy checks
+  if( id < 0 || dimension < 0 || dimension > 3 ||
+      point_count < 0 || conn_count < 0 || topo_count < 0 )
+  {
+    attrib.string_data_list()->reset();
+    PRINT_ERROR("Invalid %s attribute read.  Corrupted file?\n"
+                "\tId = %d\n\tDimension = %d\n\tPoint Count = %d\n"
+                "\tPoint Connectivity Count = %d\n"
+                "\tTopology Connectivity Count = %d\n",
+                attrib.string_data_list()->get()->c_str(),
+                id, dimension, point_count, conn_count, topo_count );
+    attrib.int_data_list()->reset();
+    return CUBIT_FAILURE;
+  }
+  
+  if( (conn_count + topo_count + owner_count + 5) != attrib.int_data_list()->size() ||
+      attrib.int_data_list()->size() < 5 )
+  {
+    attrib.string_data_list()->reset();
+    PRINT_ERROR("Invalid %s attribute read.  Corrupted file?\n"
+                "\tInsufficient/Excess integer data:\n"
+                "\tAvailable integer data: %d\n"
+                "\tMetadata              : 5\n"
+                "\tPoint Connectivity    : %d\n"
+                "\tTopology Connectivity : %d\n"
+                "\tFacet Point Assoc.    : %d\n"
+                "\tTotal Expected Ints   : %d\n",
+                attrib.string_data_list()->get()->c_str(),
+                attrib.int_data_list()->size(),
+                conn_count, topo_count, owner_count,
+                conn_count + topo_count + owner_count + 5 );
+    attrib.int_data_list()->reset();
+    return CUBIT_FAILURE;
+  }
+                
+  if( (point_count * 3) != attrib.double_data_list()->size() )
+  {
+    attrib.string_data_list()->reset();
+    PRINT_ERROR("Invalid %s attribute read.  Corrupted file?\n"
+                "\tInsufficient/Excess real data: %d for %d points.\n",
+                attrib.string_data_list()->get()->c_str(),
+                attrib.double_data_list()->size(), point_count );
+    attrib.int_data_list()->reset();
+    return CUBIT_FAILURE;
+  }
+  
+    // read point coordinates
+  attrib.double_data_list()->reset();
+  for( i = 0; i < point_count; i++ )
+  {
+    double x = *attrib.double_data_list()->get_and_step();
+    double y = *attrib.double_data_list()->get_and_step();
+    double z = *attrib.double_data_list()->get_and_step();
+    point_list.append( new CubitVector(x,y,z) );
+  }
+  
+    // read point connectivity (facets)
+  for( i = 0; i < conn_count; i++ )
+    point_connectivity.append( *attrib.int_data_list()->get_and_step() );
+  
+    // read topology connectivity (children)
+  for( i = 0; i < topo_count; i++ )
+    topo_connectivity.append( *attrib.int_data_list()->get_and_step() );
+    
+    // read facet point owners
+  for( i = 0; i < owner_count; i++ )
+    point_owners.append( *attrib.int_data_list()->get_and_step() );
+  
+  return CUBIT_SUCCESS;
+}
+
+
+int SubEntitySet::get_geom_dimension( CubitSimpleAttrib& attrib )
+{
+  assert(attrib.int_data_list()->size() > 1);
+  attrib.int_data_list()->reset();
+  return *attrib.int_data_list()->next();
+}
+
+int SubEntitySet::get_geom_id( CubitSimpleAttrib& attrib )
+{
+  assert(attrib.int_data_list()->size() > 1);
+  attrib.int_data_list()->reset();
+  return *attrib.int_data_list()->get();
+}
+
+int SubEntitySet::get_segment_count( CubitSimpleAttrib& attrib )
+{
+  assert(attrib.int_data_list()->size() > 2);
+  attrib.int_data_list()->reset();
+
+  int point_count = *attrib.int_data_list()->next(2);
+  if ( point_count == 0 )
+    return 0;
+
+  assert( point_count > 1 );
+  return point_count - 1;
+}
+
+CubitStatus SubEntitySet::save_geometry()
+{
+  if( !lowerOrderHead )
+    return CUBIT_SUCCESS;
+    
+  DLIList<CubitSimpleAttrib*> old_list;
+  myEntity->get_simple_attribute(PARTITION_GEOM_ATTRIB_NAME, old_list);
+  while (old_list.size())
+  {
+    CubitSimpleAttrib* old_attrib = old_list.pop();
+    myEntity->remove_simple_attribute_virt(old_attrib);
+    delete old_attrib;
+  }  
+  
+  CubitSimpleAttrib attrib(PARTITION_GEOM_ATTRIB_NAME);
+  
+  CubitStatus result = CUBIT_SUCCESS;
+  for( int i = 0; i < 2; i++ )
+  {
+    PartitionEntity* list_node = i ? subEntityHead : lowerOrderHead;
+    for( ; list_node; list_node = list_node->entitySetNext )
+      if(dynamic_cast<GeometryEntity*>(list_node) && !list_node->save(attrib))
+        result = CUBIT_FAILURE;
+  }
+  
+  return result;
+}
+ 
+
+void SubEntitySet::strip_attributes() 
+{
+  strip_attributes( myEntity );
+}
+      
+  
Index: /cgm/geom/virtual/PartitionEngine.hpp
===================================================================
--- /cgm/geom/virtual/PartitionEngine.hpp (revision 1040)
+++ /cgm/geom/virtual/PartitionEngine.hpp (revision 1040)
@@ -0,0 +1,609 @@
+//-------------------------------------------------------------------------
+// Filename      : PartitionEngine.hpp
+//
+// Purpose       : 
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 04/23/02
+//-------------------------------------------------------------------------
+
+#ifndef PARTITION_ENGINE_HPP
+#define PARTITION_ENGINE_HPP
+
+#include "CubitDefines.h"
+#include "VGDefines.h"
+#include <map>
+#include "IntermediateGeomEngine.hpp"
+#include "DLIList.hpp"
+
+class TopologyBridge;
+class Point;
+class Curve;
+class Surface;
+class Lump;
+class LoopSM;
+class BodySM;
+
+class SubSurface;
+class SubCurve;
+class SegmentedCurve;
+
+class PartitionEntity;
+class PartitionBody;
+class PartitionLump;
+class PartitionShell;
+class PartitionCoSurf;
+class PartitionSurface;
+class PartitionCurve;
+class PartitionPoint;
+class PartitionLoop;
+class PartitionCoEdge;
+class PartPTCurve;
+
+class PST_Point;
+class SubEntitySet;
+class FacetProjectTool;
+class CubitSimpleAttrib;
+
+class CubitPoint;
+class CubitFacet;
+class CubitPointData;
+class CubitFacetData;
+class CubitFacetEdgeData;
+class Body;
+
+class CubitVector;
+class CubitTransformMatrix;
+template <class X> class DLIList;
+
+class PartitionEngine : public IntermediateGeomEngine
+{
+
+public:
+  bool is_partition(TBOwner *bridge_owner);
+  bool is_composite(TBOwner *bridge_owner);
+  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,
+                                                    DLIList<TopologyBridge*> &att_tbs,
+                                                    DLIList<BodySM*> &new_sms,
+                                                    DLIList<Body*> &old_bodies){};
+  virtual void remove_attributes_from_unmodifed_virtual(DLIList<TopologyBridge*> &bridges){};
+
+
+
+  virtual ~PartitionEngine();
+
+  /** Get singleton instance */
+  static PartitionEngine& instance();
+
+  int level() const { return SUBCOMP_PARTITION_LAYER; }
+
+  void notify_deactivated (PartitionBody* body);
+  void notify_deactivated( PartitionLump* vol);
+  void notify_deactivated (PartitionSurface* surface);
+  void notify_deactivated (PartitionCurve* curve);
+  void notify_deactivated (PartitionPoint* point);
+  void add_to_deactivated_list(PartitionBody* body);
+  void add_to_deactivated_list(PartitionLump* vol);
+  void add_to_deactivated_list(PartitionSurface* sur);
+  void add_to_deactivated_list(PartitionCurve* cur);
+  void add_to_deactivated_list(PartitionPoint* pt);
+  /** Restore partitions on passed geometry
+   *
+   * Reads partition geometry saved as attributes on the passed
+   * geometry, restores the partitions and udpates the passed
+   * list
+   */
+  CubitStatus import_geometry( DLIList<TopologyBridge*>& imported_geometry );
+
+  /** Save partition geometry.
+   *
+   * Saves any partition geometry in the passed list (or on children
+   * of entities int the passed list) as attributes on the underlying
+   * geometry, and update the passed list to contain the underlying
+   * geometry.
+   */
+  CubitStatus export_geometry( DLIList<TopologyBridge*>& geometry_to_save );
+
+  /** Partition a curve
+   *
+   * @param curve The curve to partition
+   * @param u     The location at which to split the curve.
+   * @return      The new point created at the split location.
+   */
+  Point* insert_point( Curve* curve, double u );
+  
+  /** Undo curve partitioning or point-curve creation.
+   * 
+   * @param point The point to remove.
+   * @param dead_curves If non-null, polulated with pointers to the
+   *                    destroyed PartitionCurves (pointers are by
+   *                    definition stale pointers.)
+   * @return The surviving curve, or null if a point-curve was removed..
+   */
+  Curve* remove_point( PartitionPoint* point, 
+                       PartitionCurve* dead_curves[2] = 0 );
+  
+  /** Single-surface interface to insert_curve(DLIList<Surface*>&,...)
+   *
+   * @see insert_curve( DLIList<Surface*>&, DLIList<CubitVector*>&, DLIList<Surface*>,& DLIList<Curve*>& ) 
+   */                   
+  Surface* insert_curve( Surface* surface, 
+                         DLIList<CubitVector*>& segment_points,
+                         DLIList<Curve*>& new_curves,
+                         const double *tolerance_length = NULL);
+  
+  /** Partition surfaces
+   * 
+   * Split surfaces by projecting the passed polyline onto the patch
+   * of surfaces.
+   * @param surfaces     The list of surfaces to split.
+   * @param polyline     The curve to imprint the surfaces with.
+   * @param new_surfaces Populated with new surfaces created during partitioning.
+   * @param polyline_curves Popolated with new curves.
+   */
+  CubitStatus insert_curve( DLIList<Surface*>& surfaces,
+                            DLIList<CubitVector*>& polyline,
+                            DLIList<Surface*>& new_surfaces,
+                            DLIList<Curve*>& polyline_curves,
+                            const double *tolerance_length = NULL,
+                            DLIList<Surface*>* surfs_to_reverse = NULL);
+  
+  /** Imprint a point on a surface, creating a zero-length (point) curve.
+   *
+   * Imprint a point on a surface, creating a zero-length (point) curve.
+   * @param surface  The surface on which to create the point-curve
+   * @param position The location on the surface at which to create the point.
+   * @return         The point created (and owned by the point-curve).  The
+   *                 point curve will be the only parent curve of this point.
+   */
+  Point* insert_point_curve( Surface* surf,
+                             const CubitVector& position,
+                             Surface *&partitioned_surf );
+
+  /** Partition a lump.
+   *
+   * Create a new surface in the lump as a copy of the passed surface.
+   * This function may partition the lump if the surface copy divides
+   * a shell of the lump into two distinct regions.
+   * @param surface_to_copy  The geometry from which to create the new surface
+   * @param lump             The lump into which the surface is to be inserted.
+   * @return If an error occured, the return value will be NULL.  If the lump
+   *         was split, the return value will be the new lump.  Otherwise it
+   *         will be the passed lump.
+   */
+  Lump* insert_surface( Surface* surf_to_copy, Lump* lump );
+  
+  /** Partition a lump.
+   *
+   * Create a new surface in the lump from the passed facet patch.
+   * This function may partition the lump if the surface divides
+   * a shell of the lump into two distinct regions.
+   * @param facets  The geometry from which to create the new surface
+   * @param lump    The lump into which the surface is to be inserted.
+   * @return If an error occured, the return value will be NULL.  If the lump
+   *         was split, the return value will be the new lump.  Otherwise it
+   *         will be the passed lump.
+   */
+  Surface* insert_surface( DLIList<CubitFacet*>& facets, Lump* lump );
+  
+  
+  /** Undo surface partitioning
+   *
+   * Remove a previously inserted split curve.
+   * @param curve The curve to remove.
+   * @param dead_surfs If non-null, will be populated with pointers to
+   *                   any surfaces destroyed by this operation.
+   * @return The surviving surface.
+   */
+  Surface* remove_curve( PartitionCurve* curve,
+                         PartitionSurface* dead_surfs[2] = 0 );			
+  
+  /** Undo lump partitioning
+   *
+   * Remove a previously inserted split surface.
+   * @param surface The surface to remove.
+   * @return The surviving lump.
+   */
+  Lump* remove_surface( PartitionSurface* surface );
+
+  /** Return layer in the TopologyBridge graph that this engine handles */
+  int layer() { return SUBCOMP_PARTITION_LAYER; }
+  
+  //static void destroy_facet( CubitFacetData* facet );
+  
+  /** Add SubEntitySet to ID map (used for save/restore */
+  CubitStatus add_to_id_map( SubEntitySet* set, int unique_id );
+
+  /** Remove SubEntitySet from ID map (used for save/restore */
+  CubitStatus remove_from_id_map( SubEntitySet* set, int unique_id );
+
+  /** Retreive SubEntitySet from ID map given ID. */
+  SubEntitySet* get_from_id_map( int unique_id );
+
+  /** Retreive a PartitionEntity given ID pair.
+   *
+   * PartitionEntities are identified by the ID of their
+   * SubEntitySet and the ID of the entity in that set. 
+   * Retreive the PartitionEntity given these IDs.
+   *
+   * @param set_id The UniqueID of the SubEntitySet.
+   * @param geom_id The ID of the PartitionEntity within the
+   *                SubEntitySet
+   * @param default_set The SubEntitySet to retreive the 
+   *                entity from if the set_id == 0.
+   * @return The requested PartitionEntit, or NULL if it does
+   *         not exist.
+   */
+  PartitionEntity* entity_from_id( int set_id, int geom_id, 
+                                   SubEntitySet& default_set );
+  
+  
+  /** Destroy a surface and child topology.  
+   *
+   * Destroy a surface with no parent topology, destroying any
+   * child topology that is used only by the passed surface.
+   */
+  CubitStatus destroy_surface( PartitionSurface* surface );
+  
+  /** Destroy a lump and child topology.  
+   *
+   * Destroy the passed lump and any child topology used
+   * only by the passed lump.
+   */
+  CubitStatus destroy_lump( PartitionLump* lump );
+
+  static void delete_facet( CubitFacet* );
+
+  CubitStatus delete_solid_model_entities( PartitionBody* body,
+                                           BodySM*& real_body );
+  CubitStatus delete_solid_model_entities( PartitionSurface* surface,
+                                           Surface*& real_surface );
+  CubitStatus delete_solid_model_entities( PartitionCurve* curve,
+                                           Curve*& real_curve );
+
+  static void curves_from_surfaces( const DLIList<PartitionSurface*>& input_surfs,
+                                    DLIList<PartitionCurve*>& output_curves );
+
+  void clean_out_deactivated_geometry();
+  
+  CubitStatus translate( PartitionBody* ent, const CubitVector& delta );
+  CubitStatus rotate( PartitionBody* ent, const CubitVector& axis, double degrees );
+  CubitStatus scale( PartitionBody* ent, const CubitVector& factors );
+  CubitStatus reflect( PartitionBody* ent, const CubitVector& axis );
+  CubitStatus restore_transform( PartitionBody* ent );
+  
+  CubitStatus translate( PartitionEntity* ent, const CubitVector& delta );
+  CubitStatus rotate( PartitionEntity* ent, const CubitVector& axis, double degrees );
+  CubitStatus scale( PartitionEntity* ent, const CubitVector& factors );
+  CubitStatus reflect( PartitionEntity* ent, const CubitVector& axis );
+
+  CubitStatus notify_transform( TopologyBridge* bridge,
+                                const CubitTransformMatrix& xform );
+   
+  void remove_attributes( DLIList<TopologyBridge*> &bridge_list );
+    //remove Composite attributes off of topology bridges
+  void remove_modified(DLIList<TopologyBridge*>& geometry_list);
+    
+private:
+
+  CubitStatus notify_transform_internal( TopologyBridge* bridge,
+                                const CubitTransformMatrix& xform );
+
+  PartitionEngine();
+
+  friend class PartitionLumpImprint;
+
+  /** Find location to insert a curve into a loop.
+   *
+   * Given a curve and an end point on the curve, find
+   * the two coedges in the loop between which the curve
+   * should be inserted.
+   *
+   *@param surface The surface the curve is to be inserted into.
+   *@param curve   The curve to be inserted.
+   *@param point   The end point of the curve to find the loop intersection for
+   *@param previous A CoEdge ending at the passed point (output).
+   *@param next     A CoEdge beginning at the passed point (output).
+   */
+  CubitStatus find_coedges( PartitionSurface* surface,
+                            PartitionCurve* curve,
+                            PartitionPoint* point,
+                            PartitionCoEdge*& previous,
+                            PartitionCoEdge*& next );
+  
+  /** Helper function for find_coedges(..).
+   *
+   * Use facet connectivity to find next/prev curve in loop.
+   *
+   *@param surface The owning surface
+   *@param edge    A facet edge owned by the surface
+   *@param point   The facet point to search around
+   *@param backwards The search direction (false for clockwise)
+   *@return The next curve in the specified order around the passed facet point.
+   */
+  PartitionCurve* next_curve_around_point( PartitionSurface *const surface,
+                                           CubitFacetEdgeData *const edge,
+                                           CubitPointData *const point,
+                                           const bool backwards );
+  
+
+  /** Remove a point-curve */
+  CubitStatus remove_point_curve( PartitionPoint* point );
+  
+  /** Create a point curve 
+   * 
+   * Create point-curve topology.
+   * After the surface facetting has been updated with the 
+   * location of a point-curve, create the point curve given
+   * the facet point.
+   *
+   * Called by insert_point_curve(ParttionSurface*, const CubitVector& )
+   */
+  PartitionPoint* insert_point_curve( PartitionSurface* surface,
+                                      CubitPointData* point );
+  CubitStatus insert_point_curve( PartitionSurface* surface,
+                                  PartPTCurve* curve,
+                                  bool update_topology = true );
+                                  
+  
+  /** Partition a curve using the passed point.
+   *
+   * Split a curve.
+   *
+   * Used by restore_from_attrib(), insert_point(PartitionCurve*,double),
+   * and insert_point(CubitPointData*)
+   *
+   * @param curve  The curve to split.
+   * @param point  The new point splitting the curve.
+   * @return       The new curve.
+   */
+  PartitionCurve* insert_point( PartitionCurve* curve, PartitionPoint* point );
+  
+  /** Partition surfaces
+   * 
+   * Split surfaces by projecting the passed polyline onto the patch
+   * of surfaces.
+   * @param surfaces     The list of surfaces to split.
+   * @param polyline     The curve to imprint the surfaces with.
+   * @param new_surfaces Populated with new surfaces created during partitioning.
+   * @param polyline_curves Popolated with new curves.
+   */
+  CubitStatus insert_curve( DLIList<PartitionSurface*>& surfaces,
+                            DLIList<CubitVector*>& polyline,
+                            DLIList<PartitionSurface*>& new_surfaces,
+                            DLIList<PartitionCurve*>& polyline_curves,
+                            const double *tolerance_length = NULL);
+
+  /** Insert a new curve into surface topology.
+   *
+   * Insert a new curve into the topology of the passed surface,
+   * splitting the surface if the curve splits a loop in the surface.
+   *
+   * The surface facet connectivity is used to determine which
+   * curves belong with which surface after the split.  This function
+   * assumes that the surface facetting has already been updated with
+   * the projection of the new curve, and that the resulting facet 
+   * edges are associated with the passed curve.
+   * 
+   * Used by insert_curve(DLIList<CubitFacetEdgeData*>&), 
+   * and restore_from_attrib(Surface*).
+   *
+   * @param surface  The surface to split
+   * @param curve    The split curve
+   * @return NULL if an error occured, the new surface if the surface
+   *         was split, otherwise the passed surface.
+   */
+  PartitionSurface* insert_curve( PartitionSurface* surface, 
+                                  SegmentedCurve* curve );
+  
+  /** Insert a curve into surface topology.
+   *
+   * Given the imprint if a curve on the surface facetting, create
+   * a new curve and insert it in the surface topology, splitting
+   * the surface if necessary.  The surface is determined from the
+   * owners of the facets adjacent to the passed edges.  The new
+   * curve is returned.
+   *
+   * If the list of curve segments is not specified, the facet edges
+   * will be used to define the curve geometry.  The list of curve
+   * segments may optionally be specified to provide a more precise
+   * definition of the curve geometry.
+   *
+   * Used by insert_Curve( DLIList<Surface*>&, DLIList<CubitVector*&, ... );
+   */
+  SegmentedCurve* insert_curve( DLIList<CubitFacetEdgeData*>& facet_edges,
+                                DLIList<CubitVector*>* curve_segments = 0 );
+  
+  /** Project a point into the surface facetting
+   *
+   * Project a position onto the facetting of a surface, updating
+   * the surface facetting to contain the resulting point.
+   *
+   * Used by insert_point_curve(Surface*, const CubitVector&), and
+   * restore_from_attrib(Surface*)
+   *
+   * @param surface   The surface to project onto.
+   * @param position  The position to project.
+   * @return The new facet point added to the surface facetting.
+   */
+  CubitPointData* project_to_surface( PartitionSurface* surface,
+                                      const CubitVector& position );
+  
+  /** Project a polyline onto a facet patch.
+    * 
+    * Project a polyline onto a patch of facets.  Modifies facets
+    * and updates owners of facets.  The passed facet patch will
+    * no longer be valid after this operation.  If necessary, the
+    * facets should be re-aquired from the owning geometry, which
+    * will have been updated appropriately.
+    *
+    * Used by insert_curve(DLIList<Surface*>&, DLIList<CubitVector*>&, ...),
+    * and restore_from_attrib(Surface*)
+    *
+    * @param facets       The facet patch to project onto.
+    * @param polyline_in  The polyline to project.
+    * @param polyline_out The resulting polyline created in the
+    *                     facetting.
+    * @param polyline_pts The points in the facetting corresponding to
+    *                     each input position in polyline_in.  List
+    *                     may contain NULL values.
+    */
+  CubitStatus project_to_surface( DLIList<CubitFacetData*>& facets,
+                                  DLIList<CubitVector*>& polyline_in,
+                                  DLIList<CubitFacetEdgeData*>& polyline_out,
+                                  DLIList<CubitPointData*>& polyline_pts,
+                                  const double *tolerance_length = NULL);
+  
+  /** Insert a surface into a lump
+   *
+   * Update lump topology for the creation of a new surface.  Splits
+   * the lump if necessary.  
+   *
+   * Used by insert_surface(Surface*,Lump*) and restore_from_attrib(Lump*)
+   *
+   * @param lump  The lump to insert the surface in
+   * @param surf  The surface to insert
+   * @return      NULL if an error occured, the new lump if the passed
+   *              lump was split, or the passed lump otherwise.
+   */
+  PartitionLump* insert_surface( PartitionLump* lump, PartitionSurface* surf );
+  
+  
+  /** Find or create the owning body for a new PartitionPoint */
+  PartitionBody* make_body( PartitionPoint* pt );
+  /** Find or create the owning body for a new PartitionCurve */
+  PartitionBody* make_body( PartitionCurve* curve );
+  /** Find or create the owning body for a new PartitionSurface */
+  PartitionBody* make_body( PartitionSurface* surf );
+  /** Find or create the owning body for a new PartitionLump */
+  PartitionBody* make_body( PartitionLump* lump );
+  /** Common code used by make_body(..) methods. */
+  PartitionBody* make_body_internal( TopologyBridge* child_ptr );
+
+  /** Replicate topology in partition layer */
+  PartitionLump* replace_lump( Lump* lump );
+  /** Remove partition layer topolgy and restore real topology */
+  Lump* restore_lump( PartitionLump* lump );
+  /** Helper for destroying PartitionLump topology*/
+  CubitStatus destroy_shell( PartitionShell* shell );
+
+
+public: /* temporarily public for debugging */
+  /** Replicate topology in partition layer */
+  SubSurface* replace_surface( Surface* surface );
+private:
+  /** Remove partition layer topolgy and restore real topology */
+  Surface* restore_surface( SubSurface* surface );
+
+  /** Replicate topology in partition layer */
+  SubCurve* replace_curve( Curve* curve );
+  /** Remove partition layer topolgy and restore real topology */
+  Curve* restore_curve( SubCurve* curve );
+  
+  /** Replicate topology in partition layer */
+  PartitionPoint* replace_point( Point* point );
+  /** Remove partition layer topolgy and restore real topology */
+  Point* restore_point( PartitionPoint* point );
+  
+  /** Split a surface
+   * 
+   * Split surface and move loops to new surface.
+   * When inserting a curve results in a loop being split 
+   * (or a new hole-loop being created) this method is called.
+   * This method uses facet connectivity and facet-owenr 
+   * associativity to move the appropriate surface facets
+   * and PartitionLoops to the new surface.
+   *
+   * Used by insert_curve(PartitionSurface*, SegmentedCurve*).
+   *
+   *@param surface   The surface to split.
+   *@param new_curve A coedge owning the curve that caused the split.
+   *@return NULL if an error occured, the new surface if one was
+   *        created, or the passed surface if the surface isn't to
+   *        be split yet.
+   */
+  PartitionSurface* split_surface( PartitionSurface* surface, 
+                                   PartitionCoEdge* new_curve );
+  
+  /** Split a lump
+   *
+   * Split a lump and move shells to new lump.
+   * If inserting a surface could potentially result in the
+   * lump being partitioned, this method is called to attempt
+   * to split the shell and move the appropriate shells to the
+   * new lump.
+   *
+   * Called by insert_surface( PartitionLump*, PartitionSurface*)
+   *
+   *@param shell  The shell that is potentially to be split.
+   *@return NULL if an error occured, a pointer to the new lump
+   *        if the shell was split.  The orignal shells owner otherwise.
+   */
+  PartitionLump* split_lump( PartitionShell* shell );
+  
+  /** Split a shell
+   *
+   * Check if a shell can be split, and if so split it.
+   *
+   * Called by split_lump(PartitionShell*) and remove_surface(PartitionSurface*)
+   */
+  PartitionShell* split_shell( PartitionShell* shell );
+  
+  /** Put non-manifold surfaces in appropriate shell.
+   *
+   * After a shell is split, figure out which of the new shells
+   * each surface in the passed list of non-manifold surfaces belongs 
+   * in, and add it to that shell.
+   *
+   * Called by split_shell(PartitionShell*)
+   *
+   * @param surfaces  A list of non-manifold surfaces with co-surfaces
+   *                  already created, but not beloning to any shell.
+   * @param shell1    One of the two shells.
+   * @param shell2    The other of the two shells.
+   */
+  void insert_nonmanifold_surfaces( DLIList<PartitionSurface*>& surfaces,
+                             PartitionShell* shell1, PartitionShell* shell2);
+  
+  /** Test if a surface is on the inside of a shell.
+   *
+   * Given a surface which shares at least one curve with the
+   * boundary of the shell (i.e. two non-manifold surfaces in the
+   * shell), determine if the surface is inside or outside of the
+   * shell.
+   *
+   * This is a helper function for insert_nonmanifold_surfaces(..)
+   */
+  CubitStatus inside_shell( PartitionShell* const shell, 
+                            PartitionSurface* const surf, 
+                            bool& result );
+  
+  /** Save partition curve geometry as attributes.*/
+  CubitStatus save_curves( SubEntitySet* curve_set );
+  /** Save surface partitions as attributes. */
+  CubitStatus save_surfaces( SubEntitySet* surface_set );
+  /** Save lump partitions as attributes. */
+  CubitStatus save_lumps( SubEntitySet* lump_set );
+  
+  /** Restore curve partitions from attributes */
+  CubitStatus restore_from_attrib( Curve* partitioned_curve );
+  /** Restore surface partitions from attributes */
+  CubitStatus restore_from_attrib( Surface* partitioned_surface );
+  /** Restore lump partitions from attributes */
+  CubitStatus restore_from_attrib( Lump* partitioned_lump );
+  
+  /** Map for getting a SubEntitySet given its unique ID */  
+  std::map<int,SubEntitySet*> uniqueIdMap;
+
+  DLIList<TopologyBridge*> deactivatedList;
+};
+
+#endif
Index: /cgm/geom/virtual/PST_Data.hpp
===================================================================
--- /cgm/geom/virtual/PST_Data.hpp (revision 1040)
+++ /cgm/geom/virtual/PST_Data.hpp (revision 1040)
@@ -0,0 +1,638 @@
+//-------------------------------------------------------------------------
+// Filename      : PST_Data.hpp
+//
+// Purpose       : Classes for representing geometry facets.  Used by 
+//                 PartSurfTess to find the graphis faceting for 
+//                 PartitionSurfaces.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 05/17/01
+//-------------------------------------------------------------------------
+#ifndef PST_DATA_HPP
+#define PST_DATA_HPP
+#include <vector>
+
+#include "CubitVector.hpp"
+#include "CubitDefines.h"
+#include "DLIList.hpp"
+#include "CubitPlane.hpp"
+
+#define PST_OTHER(A,B,C) (((A)==(B))?(C):(((A)==(C))?(B):0))
+
+class PST_CoEdge;
+class PST_Edge;
+class PST_Point;
+class PST_Face;
+class GMem;
+
+class PST_Entity;
+
+class PST_EntityOwner {
+  public:
+  virtual void 
+  notify_split( PST_Entity* old_entity, PST_Entity* new_entity ) = 0;
+};
+
+class PST_Entity
+{
+  public:
+  
+  inline PST_EntityOwner* owner() const;
+  
+  inline void owner( PST_EntityOwner* );
+  
+  protected:
+  
+  inline PST_Entity();
+  
+  virtual ~PST_Entity() = 0;
+  
+  private:
+  
+  PST_EntityOwner* myOwner;
+};
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Class representing a vertex in facet data structure
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 05/16/01
+//-------------------------------------------------------------------------
+class PST_Point : public CubitVector, public PST_Entity
+{
+  friend class PST_Edge;
+
+  public:
+  
+    PST_Point( const CubitVector& position )
+      : CubitVector( position ),
+        mark(0), private_mark_(false), edge_(0)
+      { }
+
+    ~PST_Point() ;
+      //- Destroys this point, and all edges and faces that
+      //- the point exists in.
+    
+    PST_Edge* edge() 
+      { return edge_; }
+    
+    inline PST_Edge* next( PST_Edge* prev );
+    
+    PST_Edge* common( PST_Point* pt );
+    
+#ifdef BOYD15
+    int edges( DLIList<PST_Edge*>* list = 0 );
+#endif
+    
+    int faces( DLIList<PST_Face*>* list = 0 );
+    
+    //PST_Face* boundary_face();
+    
+    void debug_draw( int color = 1, bool flush = true );
+    static void debug_draw_points( DLIList<PST_Point*>& list, 
+                             int color, bool flush = true );
+  
+    int validate( CubitBoolean print = CUBIT_FALSE );
+    
+    void print();
+
+    int mark;
+  
+    int sequence;
+    
+  private:
+    cBit private_mark_ : 1;
+  
+    PST_Edge* edge_;
+};
+
+//-------------------------------------------------------------------------
+// Purpose       : Association between a PST_Edge and a PST_Face
+//
+// Special Notes : Allocated inline in PST_Edge -- Do NOT memory manage!
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 05/16/01
+//-------------------------------------------------------------------------
+class PST_CoEdge
+{
+  friend class PST_Edge;
+  
+  public:
+  
+    PST_CoEdge* next()
+      { return next_; }
+      
+    PST_Edge* edge()
+      { return edge_; }
+    
+    PST_Face* face()
+      { return face_; }
+    
+    inline CubitSense sense();
+    
+    inline PST_Point* start_point();
+    inline PST_Point* end_point();
+    inline PST_Point* common( PST_CoEdge* coedge );
+    inline PST_Point* other( PST_Point* point );
+    
+    inline const CubitVector& start_coord();
+    inline const CubitVector& end_coord();
+    inline CubitVector direction();
+    
+    inline PST_CoEdge* other();
+    
+    PST_CoEdge* previous();
+      
+    int validate( CubitBoolean print = CUBIT_FALSE );
+      
+  private:
+  
+    PST_CoEdge( PST_Edge* owner )
+      : next_(0), edge_(owner), face_(0)
+      { }
+    
+    ~PST_CoEdge() 
+      { assert( !face_ ); } 
+    
+    PST_CoEdge* next_;
+    PST_Edge*   edge_;
+    PST_Face*   face_;
+};
+    
+
+//-------------------------------------------------------------------------
+// Purpose       : Edge in facet data structure
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 05/16/01
+//-------------------------------------------------------------------------
+class PST_Edge : public PST_Entity
+{
+  public:
+    
+    static void make_gmem( GMem& gmem, DLIList<PST_Face*>& facets );
+    static void make_gmem( GMem& gmem, DLIList<PST_Edge*>& edges );
+    static void make_facets( GMem& gmem, double tolerance,
+                             DLIList<PST_Edge*>& edges );
+    static void make_facets(
+     			     const std::vector<double>& coordinates, 
+               const std::vector<int>& connections,
+    			     double tolerance, 
+               DLIList<PST_Edge*>& edge_list );
+
+    PST_Edge( PST_Point* start_pt, PST_Point* end_pt )
+      : mark(0), private_mark_(false),
+        start_(0), end_(0),
+        forward_( this ), reverse_( this )
+      { 
+        assert( start_pt != end_pt );
+        set_start_point( start_pt );
+        set_end_point( end_pt );
+      }
+    
+    
+    static PST_Face* create_face( PST_Point* p1,
+                                  PST_Point* p2,
+                                  PST_Point* p3 );
+
+    static PST_Edge* split_face( PST_Point* start,
+                                 PST_Point* end,
+                                 PST_Face* hint = 0 );
+      //- This method splits a face by creating an edge
+      //- between two existing points on that face.   
+      //- If the face to split is not specified, both
+      //- points must have exactly one face in common.
+      //- If the points do not have a common face, have
+      //- more than one common face and no face is 
+      //- specified, do not exist in the passed face, 
+      //- or already have a common edge, NULL is returned.
+                                 
+    static PST_Edge* split_face( PST_CoEdge* after_coedge_1,
+                                 PST_CoEdge* after_coedge_2 );
+      //- Split a face with an edge from the end of the first
+      //- coedge to the end of the second coedge.  NULL is
+      //- returned if the coedges do not have a common face,
+      //- or the desired edge already exists.
+                                 
+    static PST_Edge* insert_in_face( PST_Point* end,
+                                     PST_CoEdge* after_this );
+      //- Create a non-manifold edge in a face.  The edge is
+      //- inserted starting at the end of the passed coedge,
+      //- and terminating at the passed point.  If the 
+      //- passed point already exists in a face, null is
+      //- returned.
+                                     
+#ifdef BOYD15
+    static PST_Edge* join_faces( PST_CoEdge* prev_on_first_face,
+                                 PST_CoEdge* prev_on_second_face );
+      //- Join two faces by creating a non-manifold "bridge" edge
+      //- between them.  If the coedges are part of the same face,
+      //- or the desired edge already exists, null is returned.
+      //- The edge is created between the ends of the passed
+      //- coedges.
+#endif
+
+    PST_Edge* split( PST_Point* point );
+      //- Split an existing edge.  Creates a new edge in the 
+      //- same face(s) as the existing edge.  Returns null
+      //- if the passed already exists in any face.
+
+    ~PST_Edge();
+      //- Destroy this edge, splitting or merging faces as
+      //- necessary.  Does NOT destroy unused points.
+    
+    PST_Point* start_point()
+      { return start_; }
+    
+    PST_Point* end_point()
+      { return end_; }
+    
+    const CubitVector& start_coord()
+      { return *start_; }
+      
+    const CubitVector& end_coord()
+      { return *end_; }
+    
+    CubitVector direction()
+      { return end_coord() - start_coord(); }
+      
+    
+    CubitVector position( double t )
+      { return start_coord() + t * direction(); }
+  
+    double closest_on_line( const CubitVector& pos );
+    double closest_on_edge( const CubitVector& pos );
+      // Parameter of the closest position on 
+      // a) the line containing this edge or 
+      // b) this bounded edge.
+      
+    double closest_on_line( const CubitVector& base, 
+                            const CubitVector& direction );
+      // The parameter of the closest position on
+      // the line containing this edge to the passed line.
+      // Use position(..) function above to get coordinates.
+      
+#ifdef BOYD15
+    void closest_on_edges( PST_Edge* other_edge,
+                           double& t_this,
+                           double& t_other );
+      // Find the pair of positions, one on this
+      // bounded edge and one on the passed edge,
+      // that are closest to each other.  
+      //
+      // If edges are parallel, it is possible for
+      // a range of points on each edge to be
+      // equidistant from the other edge.  In such
+      // a case, this method will return the point
+      // in that range closest to the start of 
+      // this edge.
+#endif
+    
+    
+    PST_Point* other( PST_Point* pt )
+      { return PST_OTHER(pt,start_,end_); }
+    
+    inline PST_Point* common_point( PST_Edge* edge );
+    
+    PST_CoEdge* forward() 
+      { return &forward_; }
+    
+    PST_CoEdge* reverse()
+      { return &reverse_; }
+      
+    PST_CoEdge* other( PST_CoEdge* coedge )
+      { return PST_OTHER(coedge,&forward_,&reverse_); }
+    
+    inline PST_CoEdge* coedge( PST_Face* face );
+    
+    
+    PST_Face* other( PST_Face* face )
+      { return PST_OTHER(face,forward_.face(),reverse_.face()); }
+   
+    
+    inline PST_Face* common_face( PST_Edge* edge );
+    
+    inline CubitSense sense( PST_Face* face );
+    
+    CubitSense sense( PST_CoEdge* coedge )
+      { return coedge == forward() ? CUBIT_FORWARD  :
+               coedge == reverse() ? CUBIT_REVERSED : CUBIT_UNKNOWN; }
+
+    PST_Edge* other( PST_Point* point, PST_Face* face );
+      // Find the other edge in the passed face that
+      // shares the passed point.  Returns NULL if multiple
+      // matches in a non-manifold face.
+
+    PST_Edge* next( PST_Point* pt )
+      { return pt == start_ ? start_next_ : 
+               pt == end_   ? end_next_ : 0; }
+               
+    //inline bool boundary();
+    
+    static void faces( DLIList<PST_Edge*>& edges, DLIList<PST_Face*>& faces );
+    static void edges( DLIList<PST_Face*>& faces, DLIList<PST_Edge*>& edges );
+    static void edges( DLIList<PST_Point*>& pts,  DLIList<PST_Edge*>& edges );
+    static void points( DLIList<PST_Edge*>& edges, DLIList<PST_Point*>& pts );
+    
+    void debug_draw( int color = 1, bool flush = true );
+    static void debug_draw_points( DLIList<PST_Edge*>& list, 
+                             int color, int bcolor = 0, bool flush = true );
+    static void debug_draw_edges ( DLIList<PST_Edge*>& list, 
+                             int color, int bcolor = 0, bool flush = true );
+    static void debug_draw_faces ( DLIList<PST_Edge*>& list, 
+                             int color, bool flush = true );
+    
+    static int validate( DLIList<PST_Edge*>& edges, CubitBoolean print = CUBIT_FALSE );
+    int validate( CubitBoolean print = CUBIT_FALSE );
+    
+    void print();
+
+    int mark;
+
+  private:
+    cBit private_mark_ : 1;
+    
+    void remove_point( PST_Point*& ptr, PST_Edge*& next );
+    void remove_start_point() { remove_point( start_, start_next_ ); }
+    void remove_end_point()   { remove_point( end_, end_next_); }
+    
+    void set_point( PST_Point* pt, PST_Point*& ptr, PST_Edge*& next );
+    void set_start_point( PST_Point* pt )
+      { set_point( pt, start_, start_next_ ); }
+    void set_end_point( PST_Point* pt )
+      { set_point( pt, end_, end_next_ ); }
+      
+    PST_Point* start_;
+    PST_Point* end_;
+    PST_Edge* start_next_;
+    PST_Edge* end_next_;
+    
+    PST_CoEdge forward_;
+    PST_CoEdge reverse_;
+};
+
+//-------------------------------------------------------------------------
+// Purpose       : Face in facet data structure
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 05/16/01
+//-------------------------------------------------------------------------
+class PST_Face : public PST_Entity
+{
+  friend class PST_Edge;
+  friend class PST_Point;
+
+  public:
+      
+    const CubitPlane& plane()
+      {
+        if( update_plane_ )
+          calculate_plane();
+        return plane_;
+      }
+  
+    CubitVector normal()
+      { return plane().normal(); }
+      
+      
+#ifdef BOYD15
+    double area( CubitVector* area_center = 0 );
+#endif
+
+    double bounding_length();
+    
+    PST_CoEdge* first_coedge()
+      { return coedge_; }
+      
+    void append_points( DLIList<PST_Point*>& result_list );
+    
+    PST_Point* opposite( PST_Edge* edge );
+    PST_Edge* opposite( PST_Point* point );
+      // for triangles
+      
+    bool two_edges( PST_Point* point, PST_Edge*& edge1, PST_Edge*& edge2 );
+  
+#ifdef BOYD15
+    int coedge_count();
+#endif
+    
+    bool modified()
+      { return modified_; }
+    
+    void modified( bool b )
+      { 
+        modified_ = b;
+        if( b ) update_plane_ = 1;
+      }
+      
+    void debug_draw( int color = 1, bool flush = true );
+    static void debug_draw_faces( DLIList<PST_Face*>& list, 
+                            int color, bool flush = true );
+  
+    int validate( CubitBoolean print = CUBIT_FALSE );
+    
+    void print();
+    
+    int mark;
+    
+    int sequence;
+    
+    int parent;
+    
+  private:
+  
+    PST_Face( PST_CoEdge* coedge )
+      : mark(0), sequence(0), parent(0),
+        coedge_(coedge), 
+        //boundary_(0),
+        modified_(0),
+        update_plane_(1),
+        private_mark_(false)
+        
+      { }
+      
+    PST_Face( PST_CoEdge* coedge, PST_Face* split_from )
+      : mark(0), sequence(0), parent(0),
+        coedge_(coedge),
+        //boundary_(split_from->boundary()),
+        modified_(0),
+        update_plane_(1),
+        private_mark_(false)
+      { split_from->modified(true); }
+  
+    ~PST_Face()
+      { assert( !coedge_ ); }
+  
+    bool calculate_plane();
+    
+    PST_CoEdge* coedge_;
+    CubitPlane  plane_;
+    
+    //cBit boundary_     : 1;
+    cBit modified_     : 1;
+    cBit update_plane_ : 1;
+    cBit private_mark_ : 1;
+};
+
+/*************************************************************************
+ *                               PST_Point
+ ************************************************************************/
+
+inline PST_Edge* PST_Point::next( PST_Edge* prev )
+{ 
+  return prev->next(this);
+}
+
+/*************************************************************************
+ *                               PST_CoEdge
+ ************************************************************************/
+
+inline CubitSense PST_CoEdge::sense()
+{
+  return edge_->sense(this);
+}
+
+inline PST_Point* PST_CoEdge::start_point()
+{
+  return sense() == CUBIT_FORWARD ? edge_->start_point() : edge_->end_point();
+}
+
+inline PST_Point* PST_CoEdge::end_point()
+{
+  return sense() == CUBIT_FORWARD ? edge_->end_point() : edge_->start_point();
+}
+
+inline PST_Point* PST_CoEdge::other( PST_Point* point )
+{
+  return edge_->other( point );
+}
+
+inline const CubitVector& PST_CoEdge::start_coord()
+{
+  return sense() == CUBIT_FORWARD ? edge_->start_coord() : edge_->end_coord();
+}
+
+inline const CubitVector& PST_CoEdge::end_coord()
+{
+  return sense() == CUBIT_FORWARD ? edge_->end_coord() : edge_->start_coord();
+}
+
+inline CubitVector PST_CoEdge::direction()
+{
+  return sense() == CUBIT_FORWARD                  ? 
+         edge_->end_coord() - edge_->start_coord() :
+         edge_->start_coord() - edge_->end_coord() ;
+}
+
+inline PST_CoEdge* PST_CoEdge::other()
+{
+  return edge_->other(this);
+}
+
+
+
+/*************************************************************************
+ *                               PST_Edge
+ ************************************************************************/
+
+inline PST_Point* PST_Edge::common_point( PST_Edge* edge )
+{
+  PST_Point* result = 0;
+  
+  if( (edge->start_ == start_) || 
+      (edge->end_   == start_)  )
+    result = start_;
+  
+  if( (edge->start_ == end_) || 
+      (edge->end_   == end_)  )
+    result = result ? 0 : end_;
+  
+  return result;
+}
+
+inline PST_CoEdge* PST_Edge::coedge( PST_Face* face )
+{
+  PST_CoEdge* result = 0;
+  
+  if( forward_.face_ == face )
+    result = &forward_;
+  
+  if( reverse_.face_ == face )
+    result = result ? 0 : &reverse_;
+  
+  return result;
+}
+
+inline CubitSense PST_Edge::sense( PST_Face* face )
+{
+  CubitSense result = CUBIT_UNKNOWN;
+  
+  if( forward_.face_ == face )
+    result = CUBIT_FORWARD;
+  
+  if( reverse_.face_ == face )
+    result = (result != CUBIT_UNKNOWN) ? CUBIT_UNKNOWN : CUBIT_REVERSED;
+  
+  return result;
+}
+
+inline PST_Entity::PST_Entity() : myOwner(0) { ; }
+
+inline PST_EntityOwner* PST_Entity::owner() const
+  { return myOwner; }
+
+inline void PST_Entity::owner( PST_EntityOwner* ent )
+  { myOwner = ent; }
+
+
+/*************************************************************************
+ *                               PST_Face
+ ************************************************************************/
+ 
+ // find the minimum edge length and use this for the bounding length
+inline double PST_Face::bounding_length()
+{
+  // The coedges appear to be stored in a circular list so 
+  // get the length of the first edge and then iterate
+  PST_CoEdge* coe = this->first_coedge();
+  CubitVector pos1 = coe->start_coord();
+  CubitVector pos2 = coe->end_coord();
+  CubitVector dist = pos1 - pos2;
+  double length = dist.length_squared();
+
+  // start the chain at the next coedge
+  coe = coe->next();
+
+  // walk through the coedges till we get back to the first 
+  // and find the minimum length edge
+  double l;
+  for ( ; coe != this->first_coedge(); coe = coe->next() )
+  {
+    pos1 = coe->start_coord();
+    pos2 = coe->end_coord();
+    dist = pos1 - pos2;
+    l = dist.length_squared();
+    if ( l < length)
+      length = l;
+  }
+
+  return sqrt(length);
+}
+
+#endif
+
Index: /cgm/geom/virtual/CollapseCurveTool.cpp
===================================================================
--- /cgm/geom/virtual/CollapseCurveTool.cpp (revision 1040)
+++ /cgm/geom/virtual/CollapseCurveTool.cpp (revision 1040)
@@ -0,0 +1,922 @@
+//-------------------------------------------------------------------------
+//- Filename:       CollapseCurveTool
+//- Purpose:  To collapse small curves for preparing for mesh
+//-      "collapse curve <id> vertex <id>\n",
+//-
+//- Creator:       Brett Clark
+//- Creation date: 01/10/2006
+//-------------------------------------------------------------------------
+
+// ********** BEGIN STANDARD INCLUDES         **********
+// ********** END STANDARD INCLUDES           **********
+                                                                                
+// ********** BEGIN MOTIF INCLUDES            **********
+// ********** END MOTIF INCLUDES              **********
+                                                                                
+// ********** BEGIN ACIS INCLUDES             **********
+// ********** END ACIS INCLUDES               **********
+                                                                                
+// ********** BEGIN CUBIT INCLUDES            **********
+#include "GMem.hpp"                                                           
+#include "RefVertex.hpp"
+#include "RefEdge.hpp"
+#include "DLIList.hpp"
+#include "CoEdge.hpp"
+#include "CoFace.hpp"
+#include "Shell.hpp"
+#include "Point.hpp"
+#include "Loop.hpp"
+#include "RefFace.hpp"
+#include "PartitionTool.hpp"
+#include "CompositeTool.hpp"
+#include "CollapseCurveTool.hpp"
+
+/*
+*/
+// ********** END CUBIT INCLUDES              **********
+
+CollapseCurveTool *CollapseCurveTool::instance_ = NULL;
+
+// ********** BEGIN PUBLIC FUNCTIONS          **********
+CollapseCurveTool *CollapseCurveTool::instance()
+{
+  if (instance_ == NULL) 
+    instance_ = new CollapseCurveTool();
+                                                                                
+  return instance_;
+}
+
+CubitStatus CollapseCurveTool::collapse_curve(DLIList <RefEdge*> ref_edge_list, 
+                                              DLIList<RefVertex*> ref_vertex_list,
+                                              int ignore_surfaces)
+{
+  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);
+
+  if(edge_to_collapse == NULL)
+  {
+    PRINT_ERROR("No curve was found to collapse.\n");
+    finished = 1;
+    result = CUBIT_FAILURE;
+  }
+
+  if(!finished)
+  {
+    // 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);
+          }
+        }
+      }
+    }
+  }
+
+  // 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();
+
+    // 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)
+    {
+      PRINT_ERROR("Cannot collapse a curve that bounds a face with only two edges.\n");
+      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");
+        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");
+        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.
+          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");
+          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);
+      RefFace *adjacent_face = NULL;
+      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();
+
+      // 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();
+
+      // Partition the curve adjacent to the collapse curve.
+      RefEdge *edge1, *edge2;
+      RefVertex *new_vertex = PartitionTool::instance()->
+        partition( curve_to_partition, position_on_curve, edge1, edge2 );
+
+      // Keep track of these in case we need to undo the partitioning.
+      if(new_vertex)
+      {
+        new_partition_vertices.append(new_vertex);
+      }
+
+      // Get the two new curves and classify them as close and far.
+      if(edge1 && edge2)
+      {
+        close_edge = edge1;
+        far_edge = edge2;
+        if(close_edge->start_vertex() != discard_vertex &&
+          close_edge->end_vertex() != discard_vertex)
+        {
+          RefEdge *tmp = close_edge;
+          close_edge = far_edge;
+          far_edge = tmp;
+        }
+      }
+      else
+      {
+        // If the partition didn't create a new vertex and two new curves
+        // (the case when the partition position lands on an existing
+        // vertex) just classify the curve as "close" and set the 
+        // "far" curve to NULL. 
+        close_edge = curve_to_partition;
+        far_edge = NULL;
+      }
+
+      RefFace *surface_to_partition = surfaces_to_partition.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;
+      PartitionTool::instance()->
+          insert_edge( surface_to_partition, positions, CUBIT_FALSE, new_edges,
+                        0, &arc_length);
+
+      // Keep for later in case we need to clean up.
+      if(new_edges.size() > 0)
+      {
+        new_partition_edges += new_edges;
+      }
+
+      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();
+      }
+
+      RefFace *new_small_face = edge_to_collapse->common_ref_face(close_edge);
+
+      if(!new_small_face)
+      {
+        PRINT_ERROR("Failed to do the partition surface operation of the collapse curve.\n");
+        result = CUBIT_FAILURE;
+        finished = 1;
+      }
+      else
+      {
+        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(adjacent_surfaces.get_and_step());
+
+        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.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);
+      }
+    }
+  }
+
+  if(result == CUBIT_FAILURE)
+  {
+    int i;
+    for(i=new_partition_edges.size(); i--;)
+    {
+      CompositeTool::instance()->remove_edge(new_partition_edges.get_and_step(), true);
+    }
+    for(i=new_partition_vertices.size(); i--;)
+    {
+      CompositeTool::instance()->remove_vertex(new_partition_vertices.get_and_step(), true);
+    }
+  }
+
+  return result;
+}
+
+CubitStatus CollapseCurveTool::position_from_length(RefEdge *edge,
+                                                  RefVertex *root_vertex,
+                                                  double  arc_length,
+                                                  CubitVector& v_new)
+{
+  CubitStatus result;
+  double sense = 1.0;
+  if (root_vertex != edge->start_vertex())
+    sense = -1.0;
+  CubitVector v_root = root_vertex->get_point_ptr()->coordinates();
+  result = edge->point_from_arc_length(v_root, arc_length*sense, v_new);
+  return result;
+}
+
+
+// ********** END PUBLIC FUNCTIONS            **********
+                                                                                
+// ********** BEGIN PROTECTED FUNCTIONS       **********
+// ********** END PROTECTED FUNCTIONS         **********
+                                                                                
+// ********** BEGIN PRIVATE FUNCTIONS         **********
+CollapseCurveTool::CollapseCurveTool()
+{
+}
+
+CollapseCurveTool::~CollapseCurveTool()
+{
+}
+
Index: /cgm/geom/virtual/PartitionEntity.cpp
===================================================================
--- /cgm/geom/virtual/PartitionEntity.cpp (revision 1040)
+++ /cgm/geom/virtual/PartitionEntity.cpp (revision 1040)
@@ -0,0 +1,75 @@
+//-------------------------------------------------------------------------
+// Filename      : PartitionEntity.cpp
+//
+// Purpose       : 
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 04/21/02
+//-------------------------------------------------------------------------
+
+#include "VGDefines.h"
+#include "PartitionEntity.hpp"
+#include "CubitMessage.hpp"
+#include "CubitPoint.hpp"
+
+PartitionEntity::~PartitionEntity()
+{
+  entitySet->remove(this);
+}
+
+PartitionEntity::PartitionEntity( )
+  : mark(0), entitySet(0), entitySetNext(0), entitySetId(0)
+{
+}
+
+void PartitionEntity::print_debug_info( const char* prefix, 
+                                        bool print_subent_set ) const
+{
+  if( !prefix ) prefix = "";
+  PRINT_INFO("%sPartitionEntity %p\n", prefix, this );
+  if( print_subent_set )
+    sub_entity_set().print_debug_info(prefix);
+  else
+    print_partitioned_entity( prefix );
+}
+
+void PartitionEntity::print_partitioned_entity( const char* prefix ) const
+{
+  if(!prefix) prefix = "";
+  PRINT_INFO("%sPartitioned Entity: %s %p\n",
+    prefix, 
+    partitioned_entity() ? 
+    fix_type_name(typeid(*partitioned_entity()).name()) : "TopologyBridge",
+    partitioned_entity() );
+}
+
+CubitStatus PartitionEntity::move_to_geometry( CubitVector& )
+  { return CUBIT_SUCCESS; }
+
+CubitStatus PartitionEntity::relax_to_geometry( CubitPoint* facet_point,
+                                                const CubitVector* input_pos )
+{
+  if (input_pos)
+  {
+    CubitVector closest(*input_pos);
+    if (move_to_geometry(closest) && 
+        facet_point->check_inverted_facets(closest))
+    {
+      facet_point->set(closest);
+      return CUBIT_SUCCESS;
+    }
+  }
+  
+  CubitVector facet_pos(facet_point->coordinates());
+  if (move_to_geometry(facet_pos) &&
+      facet_point->check_inverted_facets(facet_pos))
+  {
+    facet_point->set(facet_pos);
+    return CUBIT_SUCCESS;
+  }
+  
+  return CUBIT_FAILURE;
+}
Index: /cgm/geom/virtual/SubSurface.hpp
===================================================================
--- /cgm/geom/virtual/SubSurface.hpp (revision 1040)
+++ /cgm/geom/virtual/SubSurface.hpp (revision 1040)
@@ -0,0 +1,96 @@
+//-------------------------------------------------------------------------
+// Filename      : SubSurface.hpp
+//
+// Purpose       : Geoemtry for the split of a face.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 06/11/98
+//-------------------------------------------------------------------------
+
+#ifndef SUB_SURFACE_HPP
+#define SUB_SURFACE_HPP
+
+#include "PartitionSurface.hpp"
+
+class SubSurface : public PartitionSurface
+{
+public:
+		
+  SubSurface( Surface* real_surf );
+    //- Constructor
+    
+  CubitStatus combine( PartitionSurface* dead_surface );
+		 
+  virtual ~SubSurface();
+    //- destructor.
+		
+  inline Surface* partitioned_surface() const;
+  
+  virtual CubitStatus save(CubitSimpleAttrib&);
+  
+  //CubitBox bounding_box() const;
+  //Use facet-based version inherited from PartitionSurface
+
+  double measure();
+  GeometryType geometry_type();
+
+
+  CubitStatus get_point_normal( CubitVector& point, CubitVector& normal );
+
+  virtual CubitStatus closest_point_uv_guess(  
+      CubitVector const& location,
+      double& u, double& v,
+      CubitVector* closest_location = NULL,
+      CubitVector* unit_normal = NULL );
+
+  CubitStatus closest_point( CubitVector const& pos, 
+                             CubitVector* close = 0, CubitVector* norm = 0,
+                             CubitVector* curv1 = 0, CubitVector* curv2 = 0);
+  void closest_point_trimmed( CubitVector from, CubitVector& result );
+                            
+  CubitStatus principal_curvatures( CubitVector const& loc, 
+                                    double& curv1, double& curv2,
+                                    CubitVector* closest_location=0 );
+
+  CubitVector position_from_u_v( double u, double v );
+  CubitStatus u_v_from_position( CubitVector const& location,
+                                 double& u, double& v,
+                                 CubitVector* closest_location = NULL );
+
+  CubitBoolean is_periodic();
+  CubitBoolean is_periodic_in_U( double& period );
+  CubitBoolean is_periodic_in_V( double& period );
+  CubitBoolean is_singular_in_U( double u_param );
+  CubitBoolean is_singular_in_V( double v_param );
+  CubitBoolean is_closed_in_U();
+  CubitBoolean is_closed_in_V();
+
+  CubitStatus uv_derivitives( double u, double v,
+                              CubitVector &du, CubitVector &dv );
+  CubitBoolean is_parametric();
+  CubitBoolean get_param_range_U( double& lo, double& hi );
+  CubitBoolean get_param_range_V( double& lo, double& hi );
+ 
+  CubitBoolean is_position_on( CubitVector &test_position );
+
+  CubitSense get_geometry_sense();
+  void reverse_sense();
+
+protected:
+
+  virtual PartitionSurface* copy();
+  
+private:
+
+  SubSurface( SubSurface* split_from );
+};
+
+inline Surface* SubSurface::partitioned_surface() const 
+  { return dynamic_cast<Surface*>(partitioned_entity()); }
+
+
+#endif
+
Index: /cgm/geom/virtual/PartSurfFacetTool.cpp
===================================================================
--- /cgm/geom/virtual/PartSurfFacetTool.cpp (revision 1040)
+++ /cgm/geom/virtual/PartSurfFacetTool.cpp (revision 1040)
@@ -0,0 +1,2254 @@
+#include "PartSurfFacetTool.hpp"
+#include "CubitMessage.hpp"
+#include "DLIList.hpp"
+#include "GeometryQueryEngine.hpp"
+
+#include "PartitionSurface.hpp"
+#include "PartitionCurve.hpp"
+#include "PartitionPoint.hpp"
+#include "TDVGFacetOwner.hpp"
+
+#include "CubitFacetData.hpp"
+#include "CubitFacetEdgeData.hpp"
+#include "CubitPointData.hpp"
+
+#include "RefVertex.hpp"
+#include "RefEdge.hpp"
+#include "GfxDebug.hpp"
+#include "GMem.hpp"
+
+#undef PART_SURF_REFACET
+
+void PartSurfFacetTool::validate_facets( PartitionSurface* mySurface )
+{
+  int i, j, k;
+  DLIList<CubitFacetData*> facets;
+  DLIList<CubitFacet*> pt_facets, edge_facets;
+  DLIList<CubitFacetEdge*> pt_edges;
+  mySurface->get_facet_data(facets);
+  for( i = facets.size(); i--; )
+  {
+    CubitFacetData* facet = facets.get_and_step();
+    for ( j = 0; j < 3; j++ )
+    {
+      CubitFacetEdge* edge = facet->edge(j);
+      if ( !edge )
+      {
+        PRINT_ERROR("Facet with NULL edge.\n");
+        continue;
+      }
+      
+      if ( PartitionEntity* ent = TDVGFacetOwner::get(edge) )
+      {
+        PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent);
+        if (!curve)
+        {
+          PRINT_ERROR("Facet edge owned by non-curve %s %p\n",
+            typeid(*ent).name(), (void*)ent);
+          GfxDebug::draw_line( edge->point(0)->coordinates(),
+                               edge->point(1)->coordinates(),
+                               CUBIT_RED );
+          continue;
+        }
+        
+        int edge_use_count = 0;
+        for ( k = 0; k < edge->num_adj_facets(); k++ )
+          if ( (const PartitionEntity*)TDVGFacetOwner::get(edge->adj_facet(k)) == mySurface )
+            edge_use_count++;
+        assert(edge_use_count);
+        
+        int curve_use_count = 0;
+        int coedge_count = 0;
+        PartitionCoEdge* coedge = 0;
+        while (( coedge = curve->next_coedge(coedge) ))
+        {
+          if (coedge->get_loop())
+          {
+            coedge_count++;
+            if (coedge->get_loop()->get_surface() == mySurface)
+              curve_use_count++;
+          }
+        }
+          
+        RefEdge* curve_owner = dynamic_cast<RefEdge*>(curve->topology_entity());
+        if ( coedge_count != edge->num_adj_facets() )
+        {
+          PRINT_ERROR("Curve %p (RefEdge %d): Curve in %d partition surfaces "
+                      "has facet edge in %d facets.\n", (void*)curve,
+                      curve_owner ? curve_owner->id() : 0,
+                      coedge_count, edge->num_adj_facets() );
+          GfxDebug::draw_line( edge->point(0)->coordinates(),
+                               edge->point(1)->coordinates(),
+                               CUBIT_RED );
+        }
+        
+        if ( curve_use_count != edge_use_count )
+        {
+          PRINT_ERROR("Curve %p (RefEdge %d): Curve used in %d coedges of "
+                      "this surface exists in %d facets of this surface.\n", 
+                      (void*)curve,
+                      curve_owner ? curve_owner->id() : 0,
+                      curve_use_count, edge_use_count );
+           GfxDebug::draw_line( edge->point(0)->coordinates(),
+                                edge->point(1)->coordinates(),
+                                CUBIT_RED );
+        }
+      }
+      else  // FacetEdge has no owner
+      {
+        if (edge->num_adj_facets() != 2)
+        {
+          PRINT_ERROR("Interior facet edge is %d-valent.\n", edge->num_adj_facets());
+          GfxDebug::draw_line( edge->point(0)->coordinates(),
+                               edge->point(1)->coordinates(),
+                               CUBIT_RED );
+        }
+      }
+      
+      bool found = false;
+      for ( k = 0; k < edge->num_adj_facets(); k++ )
+      {
+        CubitFacet* edge_facet = edge->adj_facet(k);
+        if( edge_facet == facet )
+          found = true;
+        
+        int index = edge_facet->edge_index(edge);
+        if( index < 0 )
+        {
+          PRINT_ERROR("edge->facet link missing facet->edge link.\n");
+          continue;
+        }
+        CubitPoint* fp1 = edge_facet->point((index+1)%3);
+        CubitPoint* fp2 = edge_facet->point((index+2)%3);
+        int sense = 1;
+        if( fp1 == edge->point(1) && fp2 == edge->point(0) )
+          sense = -1;
+        else if( fp1 != edge->point(0) || fp2 != edge->point(1) )
+        {
+          PRINT_ERROR("Facet adjacent to edge does not contain edge end points.\n");
+          GfxDebug::draw_line( edge->point(0)->coordinates(),
+                               edge->point(1)->coordinates(),
+                               CUBIT_RED );
+          continue;
+        }
+        if ( sense != edge_facet->edge_use(index) )
+        {
+          //PRINT_ERROR("Facet has incorrect edge use\n");
+        }
+      }
+      
+      if( !found )
+        PRINT_ERROR("facet->edge link missing edge->facet link.\n");
+    }
+    
+    for ( j = 0; j < 3; j++ )
+    {
+      CubitPoint* point = facet->point(j);
+      pt_facets.clean_out();
+      point->facets(pt_facets);
+      bool found = false;
+      for ( k = pt_facets.size(); k--; )
+      {
+        CubitFacet* pt_facet = pt_facets.get_and_step();
+        if ( pt_facet == facet )
+          found = true;
+        else if( pt_facet->point_index(point) < 0 )
+          PRINT_ERROR("point->facet link missing facet->point link.\n");
+      }
+      if( ! found )
+        PRINT_ERROR("facet->point link missing point->facet link.\n");
+        
+      point->edges(pt_edges);
+      while (pt_edges.size())
+      {
+        CubitFacetEdge* edge = pt_edges.pop();
+        edge_facets.clean_out();
+        edge->facets(edge_facets);
+        int count = 0;
+        while (edge_facets.size())
+          if (TDVGFacetOwner::get(edge_facets.pop()) == mySurface)
+            count++;
+        
+        bool draw = false;
+        if (count == 0) // not in this face
+         ;
+        else if (PartitionEntity* ent = TDVGFacetOwner::get(edge))
+        {
+          PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent);
+          if (curve->is_nonmanifold(mySurface))
+          {
+            if (count != 2)
+            {
+              draw = true;
+              PRINT_ERROR("Edge on non-manifold curve contained in %d facets.\n", count);
+            }
+          } 
+          else if (count != 1)
+          {
+            draw = true; 
+            PRINT_ERROR("Boundary edge contained in %d facets.\n", count); 
+          }
+        }
+        else if (count != 2)
+        { 
+          draw = true; 
+          PRINT_ERROR("Interior edge contained in %d facets.\n", count); 
+        }
+      
+        if (draw) {
+          CubitVector start = edge->point(0)->coordinates();
+          CubitVector step = 0.05 * (edge->point(1)->coordinates() - start);
+          for (int k = 0; k < 20; k++)
+            GfxDebug::draw_point( start + k * step, CUBIT_RED );
+          GfxDebug::flush();
+        }
+      }
+    }
+  }
+  
+  
+    // Check loops for contiguous chains of facet edges.
+  DLIList<CubitFacetEdgeData*> curve_edges, loop_edges;
+  PartitionLoop* loop = 0;
+  while ((loop = mySurface->next_loop(loop)))
+  {
+    loop_edges.clean_out();
+    PartitionCoEdge* coedge = loop->first_coedge();
+    do {
+      PartitionCurve* curve = coedge->get_curve();
+      if (!curve->is_nonmanifold(mySurface))
+      {
+        curve_edges.clean_out();
+        curve->get_facet_data(curve_edges);
+        if (coedge->sense() == CUBIT_REVERSED)
+          curve_edges.reverse();
+        loop_edges += curve_edges;
+      }
+      coedge = loop->next_coedge(coedge);
+    } while (coedge != loop->first_coedge());
+  
+    loop_edges.last();
+    CubitFacetEdgeData* prev = loop_edges.get_and_step();
+    PartitionCurve* prev_curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(prev));
+    for (int i = 0; i < loop_edges.size(); i++)
+    {
+      CubitFacetEdgeData* edge = loop_edges.get_and_step();
+      CubitPoint* shared = edge->shared_point(prev);
+      PartitionCurve* curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge));
+      
+      if (!prev_curve || !curve)
+      {
+        PRINT_ERROR("Missing facet owner on boundary curve.\n");
+        prev_curve = curve;
+        prev = edge;
+        continue;
+      }
+      
+      if (!shared)
+      {
+        PRINT_ERROR("Broken facet-edge chain at curve %p (RefEdge %d):\n"
+                    "      start of segment (%f,%f,%f)->(%f,%f,%f)\n",
+                    curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
+                    dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0,
+                    edge->point(0)->coordinates().x(), 
+                    edge->point(0)->coordinates().y(),
+                    edge->point(0)->coordinates().z(),
+                    edge->point(1)->coordinates().x(), 
+                    edge->point(1)->coordinates().y(),
+                    edge->point(1)->coordinates().z());
+      }
+      else if(PartitionPoint *pt = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(shared)))
+      {
+        if( (prev_curve == curve) &&
+             !(pt == curve->start_point() && pt == curve->end_point()) )
+        {
+          PRINT_ERROR("Edges at point %p (vertex %d) (%f,%f,%f) owned\n"
+                      "      by the same curve: %p (RefEdge %d)\n",
+            pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ?
+            dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0,
+            pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z(),
+            curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
+            dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0);
+        } 
+        else if (!curve->other_point(pt))
+        {
+          PRINT_ERROR("Edge owner curve %p (RefEdge %d) at point %p \n"
+                      "      (vertex %d) (%f,%f,%f) doesn't match topology\n",
+            curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
+            dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0,
+            pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ?
+            dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0,
+            pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z());
+        }
+        else if(!prev_curve->other_point(pt))
+        {
+          PRINT_ERROR("Edge owner curve %p (RefEdge %d) at point %p \n"
+                      "      (vertex %d) (%f,%f,%f) doesn't match topology\n",
+            prev_curve, prev_curve && dynamic_cast<RefEdge*>(prev_curve->topology_entity())?
+            dynamic_cast<RefEdge*>(prev_curve->topology_entity())->id() : 0,
+            pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ?
+            dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0,
+            pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z());
+        }
+      }
+      else if (prev_curve != curve)
+      {
+        PRINT_ERROR("Missing point-owner at  transition between\n"
+                  "      curve %p (RefEdge %d) and curve %p (RefEdge %d):\n"
+                  "      at location (%f,%f,%f)\n",
+                  curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
+                  dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0,
+                  prev_curve, prev_curve && dynamic_cast<RefEdge*>(prev_curve->topology_entity())?
+                  dynamic_cast<RefEdge*>(prev_curve->topology_entity())->id() : 0,
+                  shared->coordinates().x(), 
+                  shared->coordinates().y(),
+                  shared->coordinates().z() );
+      } 
+      
+      prev = edge;
+      prev_curve = curve;
+    }
+  }
+}
+   
+
+//-------------------------------------------------------------------------
+// Purpose       : Find closest point on passed facet
+//
+// Special Notes : static
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/28/03
+//-------------------------------------------------------------------------
+void PartSurfFacetTool::closest_pt_on_facet( CubitFacet* facet,
+                                             const CubitVector& p,
+                                             CubitVector& result )
+{
+    // Get triangle vertices
+  CubitVector p0(facet->point(0)->coordinates());
+  CubitVector p1(facet->point(1)->coordinates());
+  CubitVector p2(facet->point(2)->coordinates());
+
+/*
+  Algorithm from:
+    "Distance Between Point and Triangle in 3D"
+    David Eberly
+    Magic Software, Inc.
+    Sept. 28, 1999
+
+  Use barycentric coordinates.  Coordinates are
+  calculated in the range [0,det] rather than [0,1]
+  to avoid the fp division entirely where it can
+  be avoided.
+
+    ^v*t                                 
+ \R2|                 
+  \ |                 
+   \|                 
+    *p2               
+    |\                
+    | \     R1        
+ R3 |  \              
+    |   \             
+    | R0 \            
+    |     \p1         
+ ---*------*--->u*s   
+    |p0     \  R6     
+ R4 |   R5   \        
+    |         \u+v=det  
+*/
+
+
+  CubitVector s(p1 - p0);  // the u (or s) axis in parameterized space
+  CubitVector t(p2 - p0);  // the v (or t) axis in parameterized space
+  CubitVector d(p0 - p);   // vector from input position to corner at (u,v) = (0,0)
+    // Pre-calculate all the dot products we need
+    // Name the dot product of vectors 'a' and 'b' as 'ab'
+  double ss = s.length_squared();
+  double st = s % t;
+  double tt = t.length_squared();
+  double sd = s % d;
+  double td = t % d;
+    // Calculate barycentric coordinates in the range [0,det]
+  double det = ss*tt - st*st;
+  double u = st*td - tt*sd;
+  double v = st*sd - ss*td;
+  
+    // Big tree of conditionals to determine which of the 
+    // regions in the above diagram the projection of
+    // the point into the plane lies in.
+  if ( u+v < det )
+  {
+    if ( u < 0 )
+    {
+      if( v < 0 )    // Region 4 
+      {
+        if ( sd < 0 )
+        {
+          if ( -sd > ss )
+            result = p1;
+          else
+            result = p0 + (-sd/ss) * s;
+        }
+        else if ( td < 0 )
+        {
+          if ( -td > tt )
+            result = p2;
+          else
+            result = p0 + (-td/tt) * t;
+        }
+        else
+        {
+          result = p0;
+        }
+      }
+      else           // Region 3 (Edge p2-p0, u->0)
+      {
+        if ( td > 0 )
+          result = p0;
+        else if ( -td > tt )
+          result = p2;
+        else
+          result = p0 + (-td/tt) * t;
+      }
+    }
+    else if ( v < 0) // Region 5 (Edge p0-p1, v->0)
+    {
+      if ( sd > 0 )
+        result = p0;
+      else if ( -sd > ss )
+        result = p1;
+      else 
+        result = p0 + (-sd/ss) * s;
+    }
+    else             // Region 0 (Interior)
+    {
+      result = p0 + (1.0/det) * (u*s + v*t);
+    }
+  }
+  else if ( u < 0 )  // Region 2 
+  {
+    double num = tt + td - st - sd;
+    if ( num > 0.0 )       
+    {
+      double den = ss - 2*st + tt;
+      if ( num >= den )    // (Point p1)
+        result = p1;
+      else                 // (Edge p1-p2)
+      {
+        u = num / den;
+        result = p0 + u*s + (1-u)*t;
+      }
+    } 
+    else if ( td >= 0 )    // (Point p0)
+      result = p0;
+    else if ( tt+td <= 0 ) // (Point p2)
+      result = p2;
+    else                   // (Edge p2-p0)
+      result = p0 + (-td/tt)*t;
+  }
+  else if ( v < 0 )  // Region 6 
+  {
+    double num = tt + td - st - sd;
+    double den = ss - 2*st + tt;
+    if (num < den)       
+    {
+      if ( num < 0 )    // (Point p1)
+        result = p2;
+      else                 // (Edge p1-p2)
+      {
+        u = num / den;
+        result = p0 + u*s + (1-u)*t;
+      }
+    } 
+    else if ( sd >= 0 )    // (Point p0)
+      result = p0;
+    else if ( ss+sd <= 0 ) // (Point p1)
+      result = p1;
+    else                   // (Edge p0-p1)
+      result = p0 + (-sd/ss)*s;
+  }
+  else               // Region 1 (Edge p1-p2, u+v->1)
+  {
+    double num = tt + td - st - sd;
+    if ( num <= 0 )
+      result = p2;
+    else
+    {
+      double den = ss - 2*st + tt;
+      if ( num >= den )
+        result = p1;
+      else
+      {
+        u = num/den;
+        result = p0 + u*s + (1-u)*t;
+      }
+    }
+  }
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Local method for debug output
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 12/02/03
+//-------------------------------------------------------------------------
+static void draw_edges( DLIList<CubitFacetEdge*>& edges, int edge_color = 0, 
+                 bool label_edges = false, bool draw_points = false,
+                 int point_color = 0, bool label_points = false )
+{
+  char buffer[2*sizeof(void*)+3];
+
+  if (edge_color == 0)
+    edge_color = CUBIT_WHITE;
+  if (point_color == 0)
+    point_color = CUBIT_WHITE;
+  
+  for (int i = edges.size(); i--; )
+  {
+    CubitFacetEdge* edge = edges.get_and_step();
+    CubitVector start = edge->point(0)->coordinates();
+    CubitVector end = edge->point(1)->coordinates();
+    GfxDebug::draw_line(start, end, edge_color );
+    
+    if (label_edges)
+    {
+      CubitVector mid = 0.5 * (start + end);
+      sprintf(buffer, "%p", edge);
+      float x = (float)mid.x();
+      float y = (float)mid.y();
+      float z = (float)mid.z();
+      GfxDebug::draw_label( buffer, x, y, z, edge_color );
+    }
+      
+    for ( int j = 0; j < 2; j++ )
+    {
+      CubitPoint* point = edge->point(j);
+      float x = (float)point->coordinates().x();
+      float y = (float)point->coordinates().y();
+      float z = (float)point->coordinates().z();
+      
+      if (draw_points)
+      {
+        GfxDebug::draw_point( x, y, z, point_color );
+      }
+      if (label_points)
+      {
+        sprintf(buffer, "%p", point);
+        GfxDebug::draw_label( buffer, x, y, z, point_color );
+      }
+    }
+  }
+  GfxDebug::flush();
+}
+
+    
+CubitStatus PartSurfFacetTool::init_facet_data( 
+                                 DLIList<CubitFacetData*>& facets )
+{
+  assert(!mySurface->has_facets());
+  
+  int i;
+  CubitStatus rval;
+  DLIList<CubitPoint*> boundary_points, interior_points;
+  DLIList<CubitFacetEdge*> boundary_edges, interior_edges;
+  DLIList<PartitionPoint*> geom_points, interior_geom_points;
+  
+    // Get facet data
+  rval = get_facet_points_and_edges( facets, boundary_points, 
+    interior_points, boundary_edges, interior_edges );
+  if (!rval)
+  {
+    PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
+    return CUBIT_FAILURE;
+  }
+
+    // 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);
+  geom_points.remove_all_with_value(0);
+  
+    // Group geometric points into boundary and interior sets
+  for (i = geom_points.size(); i--; )
+  {
+    PartitionPoint* point = geom_points.step_and_get();
+    bool boundary = false;
+    PartitionCurve* curve = 0;
+    while ( (curve = point->next_curve(curve)) )
+      if (curve->is_in_surface(mySurface,true))
+        boundary = true;
+    if (!boundary)
+    {
+      geom_points.change_to(0);
+      interior_geom_points.append(point);
+    }
+  }
+  geom_points.remove_all_with_value(0);
+  
+    // Associate each boundary geometry point with the closest
+    // boundary facet point.
+  if(boundary_points.size() == 0 && geom_points.size() != 0)
+    rval = CUBIT_FAILURE;
+  else
+    rval = associate_points( boundary_points, geom_points );
+
+  if (!rval)
+    return CUBIT_FAILURE;
+ 
+    // Associate each interior geometry point with the closest 
+    // interior facet point.
+  rval = associate_points( interior_points, interior_geom_points );
+  if (!rval)
+    return CUBIT_FAILURE;
+
+  if (DEBUG_FLAG(145))
+  {
+    draw_edges( boundary_edges, CUBIT_ORANGE, true, false, CUBIT_WHITE, true );
+    draw_edges( interior_edges, CUBIT_WHITE );
+  }
+  
+  
+    // Populate sets
+  boundary_set.clear();
+  interior_set.clear();
+  for (i = boundary_edges.size(); i--; )
+    boundary_set.insert(boundary_edges.step_and_get());
+  for (i = interior_edges.size(); i--; )
+    interior_set.insert(interior_edges.step_and_get());
+ 
+    // For each loop on the surface...
+  PartitionLoop* loop = 0;
+  DLIList<PartitionCurve*> curve_set;
+  DLIList<CubitFacetEdge*> point_edges, edge_set_1, edge_set_2;
+  DLIList<PartitionCurve*> nonmanifold_stack;
+  while ( (loop = mySurface->next_loop(loop)) )
+  {
+      // Find coedge beginning at real vertex (must be at least one)
+    PartitionCoEdge* coedge = loop->first_coedge();
+    while (!coedge->start_point()->real_point())
+    { 
+      coedge = coedge->next();
+      assert(coedge != loop->first_coedge());
+    }
+    
+    PartitionCoEdge* first_coedge = coedge; // so we know when to stop
+    
+     
+    do // Loop until all curves in loop have been handled (back to first_coedge)
+    {
+        // Keep track of start and end
+      PartitionCurve* first_curve = coedge->get_curve();
+      PartitionPoint* start_point = coedge->start_point();
+      PartitionPoint* end_point = coedge->end_point();
+
+        // Get list of curves until next real vertex
+      curve_set.clean_out();
+      curve_set.append(first_curve);
+      while (!coedge->end_point()->real_point())
+      {
+        coedge = coedge->next();
+        curve_set.append(coedge->get_curve());
+        end_point = coedge->end_point();
+        assert(&first_curve->sub_entity_set() == &coedge->get_curve()->sub_entity_set());
+      }
+      
+      if (DEBUG_FLAG(145))
+      {
+        curve_set.reset();
+        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 );
+          GfxDebug::draw_polyline(gmem.point_list(), gmem.pointListCount, CUBIT_RED );
+        }
+        GfxDebug::flush();
+      }
+
+        // Special case for non-manifold curves
+      if (first_curve->is_nonmanifold(mySurface))
+      {
+          // Don't do the same non-manifold curve twice
+        curve_set.reset();
+        nonmanifold_stack.last();
+        if (nonmanifold_stack.size() &&
+            curve_set.get() == nonmanifold_stack.get())
+        {
+          for (i = curve_set.size(); i--; )
+          {
+            PartitionCurve* curv1 = curve_set.get_and_step();
+            PartitionCurve* curv2 = nonmanifold_stack.pop();
+            assert(curv1 == curv2);
+          }
+        }
+        else
+        {
+          for (i = curve_set.size(); i--; )
+            nonmanifold_stack.append(curve_set.get_and_step());
+        
+          if (!seam_nonmanifold_curves(curve_set, facets))
+          {
+            return CUBIT_FAILURE;
+          }
+        }
+        coedge = coedge->next();
+        if (coedge != first_coedge)
+          continue;
+        else
+          break;
+      }
+
+        // Get facet edges adjacent to first point
+      point_edges.clean_out();
+      start_point->facet_point()->edges(point_edges);
+
+        // For each boundary edge on the point, look for a chain
+        // of connected boundary edges.
+      edge_set_1.clean_out();
+      edge_set_2.clean_out();
+      while(point_edges.size())
+      {
+        CubitFacetEdge* edge = point_edges.pop();
+        if (boundary_set.count(edge) == 0)  // skip non-boundary edges
+          continue;
+
+        edge_set_2.clean_out();
+        if (!get_boundary_chain(start_point->facet_point(), edge, 
+                                  end_point->facet_point(), edge_set_2))
+          continue; // skip edges that don't begin a chain that reaches the end vertex
+
+          // If only one chain found so far, store the chain and 
+          // continue to the next edge around the point
+        if (!edge_set_1.size())
+        {
+          edge_set_1 = edge_set_2;
+          edge_set_2.clean_out();
+          continue;
+        }
+
+          // If we reached this point, handle special case where
+          // loop is composed of two real curves and we need a 
+          // geometric check to determine which half of the facet edge
+          // loop goes with which curve.
+        edge_set_1.reset();
+        edge_set_2.reset();
+        CubitVector set_1_mid = edge_set_1.get()->center();
+        CubitVector set_2_mid = edge_set_2.get()->center();
+        CubitVector set_1_closest, set_2_closest;
+        first_curve->closest_point_trimmed(set_1_mid, set_1_closest);
+        first_curve->closest_point_trimmed(set_2_mid, set_2_closest);
+
+        set_1_closest -= set_1_mid;
+        set_2_closest -= set_2_mid;
+        if (set_2_closest.length_squared() < set_1_closest.length_squared())
+          edge_set_1 = edge_set_2;
+      } // while(point_edges.size())
+
+        // We have the chain of edges to associate with the curve
+        // set.  Seam with adjacent surface facettings (if any)
+      if (DEBUG_FLAG(145))
+        draw_edges( edge_set_1, CUBIT_RED, true );
+      
+      if (!seam_curves( curve_set, edge_set_1, facets ))
+        return CUBIT_FAILURE;
+      
+      coedge = coedge->next();
+    } while (coedge != first_coedge);
+    
+  } // while (loop)
+  
+    // attach facets to surface
+  mySurface->set_facet_data(facets);
+  
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Helper function for curve seaming functions.
+//                 Check that input curve list are partitions of the
+//                 same real curve and are all the partitions of that curve.
+//                 Returns the real curve and the PartitionPoints that
+//                 are the start and end of the real curve.
+//
+// Special Notes : Assumes the passed curves are either in order or in
+//                 the reverse order.  If the reverse order, the passed
+//                 list will be reversed.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 09/08/03
+//-------------------------------------------------------------------------
+Curve* PartSurfFacetTool::get_real_curve( DLIList<PartitionCurve*>& curve_list,
+                                          PartitionPoint*& start_point,
+                                          PartitionPoint*& end_point )
+{
+  SubEntitySet* set = &(curve_list.get()->sub_entity_set());
+  DLIList<PartitionEntity*> tmp_set(curve_list.size());
+  set->get_sub_entities(tmp_set);
+  if (tmp_set.size() != curve_list.size())
+    return 0;
+  
+  tmp_set.reset();
+  curve_list.reset();
+  if (tmp_set.get() != curve_list.get())
+  {
+    curve_list.reverse();
+    curve_list.reset();
+  }
+  
+  for (int i = curve_list.size(); i--; )
+    if (curve_list.get_and_step() != tmp_set.get_and_step())
+      return 0;
+   
+    // Get real curve
+  Curve* real_curve = dynamic_cast<Curve*>(set->get_entity());
+  assert(!!real_curve);
+  
+  DLIList<TopologyBridge*> point_bridges(2);
+  real_curve->get_children(point_bridges, false, set->get_owner_layer());
+  point_bridges.reset();
+  start_point = dynamic_cast<PartitionPoint*>(point_bridges.get());
+  end_point = dynamic_cast<PartitionPoint*>(point_bridges.next());
+  assert(start_point && end_point);
+  
+  return real_curve;
+}
+
+CubitStatus PartSurfFacetTool::get_boundary_chain( 
+                                      CubitPoint* start_point,
+                                      CubitFacetEdge* start_edge,
+                                      CubitPoint* end_point,
+                                      DLIList<CubitFacetEdge*>& result_list )
+{
+  DLIList<CubitFacetEdge*> point_edges;
+  
+  //assert(start_edge->marked());
+  assert(result_list.size() == 0);
+  CubitPoint* point = start_point;
+  CubitFacetEdge* edge = start_edge;
+  while (true)
+  {
+    result_list.append(edge);
+    point = edge->other_point(point);
+    if (TDVGFacetOwner::get(point))
+      return point == end_point ? CUBIT_SUCCESS : CUBIT_FAILURE;
+    
+    point->edges(point_edges);
+    for (int i = point_edges.size(); i--; )
+    {
+      CubitFacetEdge* point_edge = point_edges.step_and_get();
+      //if (point_edge->marked() != 1 || point_edge == edge)
+      if (boundary_set.count(point_edge) == 0 || point_edge == edge)
+        point_edges.change_to(0);
+    }
+    point_edges.remove_all_with_value(0);
+    
+    if (point_edges.size() != 1)
+      return CUBIT_FAILURE;
+    
+    edge = point_edges.remove();
+  }
+  
+    // unreachable
+  return CUBIT_SUCCESS;
+}
+      
+//-------------------------------------------------------------------------
+// Purpose       : Associate facet edges in the interior of a surface
+//                 facetting with the set of curve partitions of some
+//                 real, non-manifold curve in the surface.
+//
+// Special Notes : Assumes edges internal to the surface facetting
+//                 have been marked with a '2' by the caller.  Clears
+//                 marks on consumed edges.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 09/08/03
+//-------------------------------------------------------------------------
+CubitStatus PartSurfFacetTool::seam_nonmanifold_curves(
+                                        DLIList<PartitionCurve*>& curve_list,
+                                        DLIList<CubitFacetData*>& facet_list )
+{
+    // All the curves in the attached coedge_list should belong
+    // to the same real curve and thus have a single continuous 
+    // parameterization over the entire set of curves.  Verify
+    // this now.
+  PartitionPoint *start_point, *end_point;
+  Curve* real_curve = get_real_curve(curve_list, start_point, end_point);
+  if (!real_curve)
+  {
+    PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
+    assert(false);
+    return CUBIT_FAILURE;
+  }
+  
+    // Assume caller has marked all interior edges with a '2'.
+    // Clear marks as we go to ensure we don't loop forever.
+    // Find chain of curves closest to real curve and ending
+    // at the end facet point.
+  CubitPoint* const start_vtx = start_point->facet_point();
+  CubitPoint* const   end_vtx =   end_point->facet_point();
+  assert(start_vtx&&end_vtx);
+  DLIList<CubitFacetEdge*> vtx_edges, seam_list;
+  CubitPoint* vtx = start_vtx;
+  do
+  {
+    vtx->edges(vtx_edges);
+    CubitFacetEdge* edge = 0;
+    double shortest_dist_sqr = CUBIT_DBL_MAX;
+    while( vtx_edges.size() )
+    {
+      CubitFacetEdge* curr = vtx_edges.pop();
+      //if (curr->marked() != 2 )
+      if (interior_set.count(curr) == 0)
+        continue;
+      
+      if (curr->other_point(vtx) == end_vtx)
+      { 
+        edge = curr;
+        break;
+      }
+      
+      CubitVector closest, tangent;
+      CubitVector start(vtx->coordinates());
+      CubitVector end(curr->other_point(vtx)->coordinates());
+      real_curve->closest_point(0.5*(start+end), closest, &tangent);
+      if (tangent % (end-start) < 0.0)
+        continue;
+      
+      real_curve->closest_point(end, closest);
+      closest -= end;
+      double dist_sqr = closest.length_squared();
+      if (dist_sqr < shortest_dist_sqr)
+      {
+        edge = curr;
+        shortest_dist_sqr = dist_sqr;
+      }
+    }
+    
+    if (!edge)
+    {
+      PRINT_ERROR("Internal error at %s:%d:\n"
+                  "Failed to associate facet edges with non-manofold curves.\n",
+                  __FILE__, __LINE__ );
+      return CUBIT_FAILURE;
+    }
+    if (DEBUG_FLAG(145))
+    {
+      GfxDebug::draw_facet_edge( edge, CUBIT_MAGENTA );
+      GfxDebug::flush();
+    }
+    
+    seam_list.append(edge);
+    //edge->marked(0);
+    vtx = edge->other_point(vtx);
+  } while (vtx != end_vtx);
+  
+  return seam_curves( curve_list, seam_list, facet_list );
+}
+
+
+CubitStatus PartSurfFacetTool::split_edge( CubitFacetEdge* old_edge,
+                                          const CubitVector& position,
+                                          CubitFacet* edge_facet,
+                                          CubitPoint*& new_point,
+                                          CubitFacetEdge*& new_edge,
+                                          CubitFacet*& new_facet )
+{
+  CubitVector v1, v2;
+  int i = 0, junk;
+  new_point = 0;
+  new_edge = 0;
+  new_facet = 0;
+
+  CubitFacet* split_facet = edge_facet;
+  if( !split_facet )
+    split_facet = old_edge->adj_facet(0);
+  else if( edge_facet->edge_index(old_edge) < 0 )
+    { assert(0); return CUBIT_FAILURE; }
+
+  CubitPoint* pt1 = old_edge->point(0);
+  CubitPoint* pt2 = old_edge->point(1);
+
+  v1 = position - pt1->coordinates();
+  v2 = pt2->coordinates() - position;
+  assert( v1.length_squared() > GEOMETRY_RESABS*GEOMETRY_RESABS );
+  assert( v2.length_squared() > GEOMETRY_RESABS*GEOMETRY_RESABS );
+  double dot = v1 % v2;
+  assert( dot > 0 ); // projection of new point onto line lies outside edge.
+//  double cos_sqr = (dot * dot) / (v1.length_squared() * v2.length_squared());
+//  assert( cos_sqr > 0.99240387650610407 ); // angle less than 5 degrees
+
+
+  CubitPoint* new_pt = split_facet->split_edge( pt1, pt2, position );
+  new_edge = new_pt->shared_edge(pt2);
+  if( !new_edge ) { assert(0); return CUBIT_FAILURE; }
+
+    // find new facet and update for other split facets
+  CubitFacet *facet, *other_facet;
+  PartitionEntity* facet_owner;
+  while ( (facet = old_edge->adj_facet(i++)) ) {
+    CubitPoint* pt3 = facet->point( facet->edge_index(pt1,new_pt,junk) );
+    if( !pt3->shared_edge( new_pt ) )
+      new CubitFacetEdgeData( pt3, new_pt );
+      
+    other_facet = facet->shared_facet( new_pt, pt3 );
+    if( !other_facet ) { assert(0); continue; }
+    if ( facet == edge_facet )
+      new_facet = other_facet;
+    else if( (facet_owner = TDVGFacetOwner::get(facet)) )
+      facet_owner->notify_split( facet, other_facet );
+  }
+  if( (facet_owner = TDVGFacetOwner::get( old_edge )) )
+      facet_owner->notify_split( old_edge, new_edge );
+
+  if( edge_facet )
+    assert(!!new_facet);
+  else 
+    new_facet = 0;
+    
+  new_point = new_pt;
+  return CUBIT_SUCCESS;
+}
+
+CubitStatus PartSurfFacetTool::collapse_edge( CubitPoint* keep,
+                                             CubitPoint* dead,
+                                             DLIList<CubitFacetData*>* unowned )
+{
+  int i;
+  
+  CubitPointData* keep_pt = dynamic_cast<CubitPointData*>(keep);
+  CubitPointData* dead_pt = dynamic_cast<CubitPointData*>(dead);
+  CubitFacetEdge* dead_edge;
+  assert(keep_pt&&dead_pt);
+  
+    // Cannot proceed if dead_pt is owned by a PartitionPoint.
+  if ( TDVGFacetOwner::get(dead_pt) )
+    return CUBIT_FAILURE;
+  
+    // Get list of facets to be destroyed when edge is collapsed
+  DLIList<CubitFacet*> dead_facets;
+  keep->shared_facets(dead_pt,dead_facets);
+  DLIList<PartitionSurface*> dead_facet_owners(dead_facets.size());
+  DLIList<CubitFacetData*> dead_facet_ds(dead_facets.size());
+  CAST_LIST(dead_facets, dead_facet_ds, CubitFacetData);
+  
+    // Find other edges to be destroyed when edge is collapsed.
+    // cannot proceed if any of them belong to a PartitionCurve.
+    // Also, find owners of each facet to be destroyed.
+  dead_facets.reset();
+  for ( i = dead_facets.size(); i--; )
+  {
+    CubitFacet* facet = dead_facets.get_and_step();
+    int keep_index = facet->point_index(keep);
+    int dead_index = facet->point_index(dead);
+    int othr_index = (keep_index + 1) % 3;
+    if ( othr_index == dead_index )
+      othr_index = (keep_index + 2) % 3;
+    assert( keep_index >= 0 && dead_index >= 0 );
+    dead_edge = dead_pt->shared_edge(facet->point(othr_index));
+    if ( TDVGFacetOwner::get(dead_edge) )
+      return CUBIT_FAILURE;
+      
+    PartitionSurface* surf = dynamic_cast<PartitionSurface*>(TDVGFacetOwner::get(facet));
+    dead_facet_owners.append( surf );
+  }
+
+PRINT_INFO("Collapsing edge (%f,%f,%f)->(%f,%f,%f) (%f)\n",
+  keep_pt->coordinates().x(), keep_pt->coordinates().y(), keep_pt->coordinates().z(),
+  dead_pt->coordinates().x(), dead_pt->coordinates().y(), dead_pt->coordinates().z(),
+  (keep_pt->coordinates()-dead_pt->coordinates()).length());
+  
+    // Get PartitionCurve to update for collapsed edge.
+  PartitionCurve* dead_edge_owner = 0;
+  dead_edge = dead_pt->shared_edge(keep_pt);
+  if (dead_edge)
+    dead_edge_owner = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(dead_edge));
+  
+    // Collapse the edge
+  if ( !keep_pt->collapse_edge(dead_pt) )
+    return CUBIT_FAILURE;
+  
+    // Update owning curve
+  if (dead_edge_owner)
+    dead_edge_owner->remove_dead_facet( (CubitFacetEdgeData*)dead_edge );
+  
+    // Update facet owners for dead facets.
+  dead_facet_ds.reset();
+  dead_facet_owners.reset();
+  for ( i = dead_facet_ds.size(); i--; )
+  {
+    CubitFacetData* facet = dead_facet_ds.get_and_step();
+    PartitionSurface* facet_owner = dead_facet_owners.get_and_step();
+    if (!facet_owner)
+      unowned->append(facet);
+    else 
+      facet_owner->notify_destroyed(facet);
+ }
+  
+  return CUBIT_SUCCESS;
+}
+
+
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Seam a list of facet edges from the boundary of a
+//                 surface facetting with all the curves that are 
+//                 partitions of the same real curve on the boundary of
+//                 that surface.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 09/08/03
+//-------------------------------------------------------------------------
+CubitStatus PartSurfFacetTool::seam_curves( DLIList<PartitionCurve*>& curve_list,
+                                            DLIList<CubitFacetEdge*>& edge_list,
+                                            DLIList<CubitFacetData*>& facets )
+{
+  int i;
+  if (!curve_list.size() || !edge_list.size())
+    return CUBIT_FAILURE;
+  
+  if (DEBUG_FLAG(145))
+    draw_edges( edge_list, CUBIT_WHITE, true, true, CUBIT_WHITE, false );
+  
+  DLIList<CubitFacetData*> old_facets, new_facets;
+  DLIList<CubitFacetEdgeData*> dead_edge_ptrs;
+  PartitionCurve* curve = 0;
+  
+    // All the curves in the attached coedge_list should belong
+    // to the same real curve and thus have a single continuous 
+    // parameterization over the entire set of curves.  Verify
+    // this now.
+  PartitionPoint *start_point, *end_point;
+  Curve* real_curve = get_real_curve(curve_list, start_point, end_point);
+  if (!real_curve)
+  {
+    PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
+    assert(false);
+    return CUBIT_FAILURE;
+  }
+  
+  double period;
+  const bool periodic = real_curve->is_periodic(period);
+  const bool fwdparam = (periodic ?  period > 0.0 : real_curve->start_param() < real_curve->end_param());
+  
+  edge_list.reset();
+  CubitPoint *next_vtx, *curr_vtx;
+  if (edge_list.size() == 1)
+  {
+    next_vtx = edge_list.get()->point(1);
+    curr_vtx = edge_list.get()->point(0);
+  }
+  else
+  {
+    next_vtx = edge_list.get()->shared_point(edge_list.next());
+    curr_vtx = edge_list.get()->other_point(next_vtx);
+  }
+  assert(curr_vtx&&next_vtx);
+    // Special case:  If curve_list is a closed loop of curves,
+    // a geometric check is required to determine if the passed
+    // list of facet edges is reversed wrt the curve list.
+  if (start_point == end_point)
+  {
+    CubitVector tangent, closest, start(curr_vtx->coordinates()), end(next_vtx->coordinates());
+    real_curve->closest_point( 0.5*(start+end), closest, &tangent );
+    if ((end - start) % tangent < 0.0)
+      edge_list.reverse();    
+  }
+    // Otherwise just compare end coordinates
+  else
+  {
+    if ((start_point->coordinates() - curr_vtx->coordinates()).length_squared() >
+        (end_point->coordinates() - curr_vtx->coordinates()).length_squared())
+    {
+      if (edge_list.size() == 1)
+      {
+        next_vtx = curr_vtx;
+        curr_vtx = edge_list.get()->other_point(next_vtx);
+      }
+      else
+      {
+        edge_list.reverse();
+        edge_list.reset();
+        next_vtx = edge_list.get()->shared_point(edge_list.next());
+        curr_vtx = edge_list.get()->other_point(next_vtx);
+      }
+      assert(next_vtx&&curr_vtx);
+    }
+  }
+
+  DLIList<CubitFacetEdgeData*> edge_data_list;
+  CAST_LIST(edge_list, edge_data_list, CubitFacetEdgeData);
+  assert(edge_list.size() == edge_data_list.size());
+  
+    // Find the subset of edges which belong on each curve.
+    // Begin with the first edge in the list, and the point
+    // at the end (opposite the curve start point) of the edge.
+  DLIList<CubitFacetEdgeData*> curve_edge_list;  // edges for current curve
+  PartitionPoint* vertex = start_point;      // end point of current curve
+  curve_list.reset(); 
+  edge_data_list.reset();
+  edge_data_list.reverse();
+  CubitFacetEdgeData* edge = edge_data_list.pop();
+  CubitPoint* point = start_point->facet_point(); // edge end point
+  point = edge->other_point(point);
+  if (!point)
+  {
+    PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__);
+    assert(0);
+    return CUBIT_FAILURE;
+  }
+  
+    // Iterate over all but the last curve
+  double prev_vtx_param = real_curve->start_param();
+  double prev_pt_param = real_curve->start_param();
+  for (i = curve_list.size() - 1; i--; )
+  {
+    curve_edge_list.clean_out();
+    
+    curve = curve_list.get_and_step();
+    vertex = curve->other_point(vertex);
+    const CubitVector vtx_pos(vertex->coordinates());
+    double vtx_param = real_curve->u_from_position(vtx_pos);
+    double point_param = real_curve->u_from_position(point->coordinates());
+    if (periodic)
+    {
+      if ((vtx_param < prev_vtx_param) == fwdparam)
+        vtx_param += period;
+      if ((point_param < prev_pt_param) == fwdparam)
+        point_param += period;
+      prev_vtx_param = vtx_param;
+      prev_pt_param = point_param;
+    }
+    
+      // Iterate until the edge "containing" the vertex
+    while ((vtx_param > point_param) == fwdparam)
+    {
+        // decrement edge count each time we add one of the
+        // original, input edges to the cuve edge list.
+      curve_edge_list.append(edge);
+      
+      if (!edge_data_list.size()) { assert(0); return CUBIT_FAILURE; }
+
+        // Get the next edge and facet point
+      edge = edge_data_list.pop();
+      point = edge->other_point(point);
+      point_param = real_curve->u_from_position(point->coordinates());
+      if (periodic)
+      {
+        if ((point_param < prev_pt_param) == fwdparam)
+          point_param += period;
+        prev_pt_param = point_param;
+      }
+    }
+  
+    CubitVector edge_pos;
+    edge->closest_point(vtx_pos, edge_pos);
+  
+    CubitFacetEdgeData* new_edge;
+    CubitPoint* new_point = split_edge_closest( edge, edge_pos, 0.1*edge->length(), new_edge, facets );
+    if (!new_point)
+      return CUBIT_FAILURE;
+    
+      // If the edge was split...
+    if (new_edge)
+    {
+        // If new_edge ends at the "end" point
+        // swap the edges.
+      if (new_edge->other_point(point))
+        std::swap(edge, new_edge);
+        // Put the earlier peice of the edge in the curve
+        // list.  Keep the latter peice for the next curve
+        // iteration.
+      curve_edge_list.append(new_edge);
+    }
+      // If the input position was the same as the edge end point...
+    else if (new_point == point)
+    {
+        // Add edge to list for current curve and decrement count.
+      curve_edge_list.append(edge);
+      if (!edge_data_list.size()) { assert(0); return CUBIT_FAILURE; }
+      
+        // Get the next edge and facet point for the next iteration.
+      edge = edge_data_list.pop();
+      point = edge->other_point(point);
+    }
+    
+      // Move edge split point to location of vertex
+#ifdef PART_SURF_REFACET
+    double d_sqr = (vtx_pos - edge_pos).length_squared();
+    bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS);
+    old_facets.clean_out();
+    new_facets.clean_out();
+    if (close)
+      dynamic_cast<CubitPointData*>(new_point)->set(vtx_pos);
+    else if (!fix_move_point( new_point, vtx_pos, facets, old_facets, new_facets ))
+      return CUBIT_FAILURE;
+    assert(!old_facets.size() == !new_facets.size());
+    facets -= old_facets;
+    facets += new_facets;
+#else
+    dynamic_cast<CubitPointData*>(new_point)->set(vtx_pos); 
+#endif
+      // Merge the points
+    CubitPointData* vtx_pointd = vertex->facet_point();
+    CubitPointData* new_pointd = dynamic_cast<CubitPointData*>(new_point);
+    if (vtx_pointd)
+      vtx_pointd->merge_points(new_pointd);
+    else
+      vertex->facet_point(new_pointd);
+    
+    if (!curve->has_facet_data())
+      curve->set_facet_data(curve_edge_list);
+    else if(!seam_curve( curve_edge_list, curve, facets, &dead_edge_ptrs ))
+      return CUBIT_FAILURE;
+      
+    while (dead_edge_ptrs.size())
+    {
+      CubitFacetEdgeData* edge = dead_edge_ptrs.pop();
+      boundary_set.erase(edge);
+      interior_set.erase(edge);
+    }
+
+  } // for(curve_list)
+  
+    // Do last curve
+
+  curve = curve_list.get();
+  curve_edge_list.clean_out();
+  if (edge)
+    curve_edge_list.append(edge);
+  while (edge_data_list.size())
+    curve_edge_list.append(edge_data_list.pop());
+  
+  if(!curve_edge_list.size()) { assert(0); return CUBIT_FAILURE; }
+  
+  if (!curve->has_facet_data())
+    curve->set_facet_data(curve_edge_list);
+  else if(!seam_curve( curve_edge_list, curve, facets, &dead_edge_ptrs ))
+    return CUBIT_FAILURE;
+      
+  while (dead_edge_ptrs.size())
+  {
+    CubitFacetEdgeData* edge = dead_edge_ptrs.pop();
+    boundary_set.erase(edge);
+    interior_set.erase(edge);
+  }
+    
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Seam a new list of facet edges with the list of facet
+//                 edges on a curve.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 12/02/03
+//-------------------------------------------------------------------------
+CubitStatus PartSurfFacetTool::seam_curve( DLIList<CubitFacetEdgeData*>& edge_list,
+                                           PartitionCurve* curve,
+                                           DLIList<CubitFacetData*>& facets,
+                                           DLIList<CubitFacetEdgeData*>* dead_ptrs )
+{
+  DLIList<CubitFacetData*> old_facets, new_facets;
+  const double FRACT_TOL = 0.1;
+
+  int curve_color = CUBIT_GREEN;
+  if (DEBUG_FLAG(145))
+  {
+    RefEntity* ent = dynamic_cast<RefEntity*>(curve->topology_entity());
+    while (ent && ent->color() < 0)
+    {
+      DLIList<RefEntity*> list;
+      ent->get_parent_ref_entities(list);
+      list.reset();
+      if (!list.size()) break;
+      ent = list.get();
+    }
+    if (ent)
+      curve_color = ent->color();
+  }
+  
+    // Vertices should already be "seamed".  Verify...
+    
+  PartitionPoint* start_vtx = curve->start_point();
+  PartitionPoint* end_vtx = curve->end_point();
+  CubitPointData* start_point = start_vtx->facet_point();
+  CubitPointData* end_point = end_vtx->facet_point();
+  
+  edge_list.last();
+  CubitFacetEdgeData* last_edge = edge_list.get();
+  edge_list.reset();
+  CubitFacetEdgeData* first_edge = edge_list.get();
+  if (!first_edge->other_point(start_point) || 
+      !last_edge->other_point(end_point))
+  {
+    PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__);
+    assert(0);
+    return CUBIT_FAILURE;
+  }
+  
+    // Get direction of parameter (probably always increasing...)
+  double period;
+  const bool fwdparam = curve->is_periodic(period) ? period > 0.0 :
+                        curve->start_param() < curve->end_param();
+  
+    // Get list of facet edges on curve.
+  DLIList<CubitFacetEdgeData*> curve_edges;
+  curve->get_facet_data(curve_edges);
+  if (!curve_edges.size())
+  {
+    curve->set_facet_data( edge_list );
+    return CUBIT_SUCCESS;
+  }
+  
+    // Seam edge lists
+  double curve_param = curve->start_param();
+  double new_param = curve->start_param();
+  curve_edges.reset();
+  edge_list.reset();
+  CubitFacetEdgeData* curve_edge = curve_edges.get_and_step();
+  CubitFacetEdgeData* new_edge = edge_list.get_and_step();
+  CubitPoint* prev_point = start_point;
+  double orig_crv_len = curve_edge->length();
+  double orig_new_len = new_edge->length();
+  double split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+  while (curve_edge || new_edge)
+  {
+    if (!curve_edge || !new_edge)
+    {
+      PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
+      assert(0);
+      return CUBIT_FAILURE;
+    }
+  
+    CubitPoint* curve_point = curve_edge->other_point(prev_point);
+    CubitPoint* new_point = new_edge->other_point(prev_point);
+    if (DEBUG_FLAG(145)) {
+      GfxDebug::draw_point(curve_point->coordinates(), curve_color);
+      GfxDebug::draw_facet_edge(curve_edge, curve_color);
+      GfxDebug::draw_point(new_point->coordinates(), curve_color + 1);
+      GfxDebug::draw_facet_edge(new_edge, curve_color + 1);
+      GfxDebug::flush();
+    }
+    
+    double prev_curve_param = curve_param;
+    double prev_new_param = new_param;
+    curve_param = curve->u_from_position(curve_point->coordinates());
+    new_param = curve->u_from_position(new_point->coordinates());
+    if (curve->is_periodic(period))
+    {
+      if ((prev_curve_param > curve_param) == fwdparam)
+        curve_param += period;
+      if ((prev_new_param > new_param) == fwdparam)
+        new_param += period;
+    }
+    
+    if ((curve_param > new_param) == fwdparam)
+    {
+      CubitFacetEdgeData* split_edge = 0;
+      CubitVector edge_pos;
+      curve_edge->closest_point( new_point->coordinates(), edge_pos );
+      CubitPoint* split = split_edge_closest( curve_edge, 
+                                              edge_pos, 
+                                              split_tol,
+                                              split_edge, 
+                                              facets );
+      if(!split)
+        return CUBIT_FAILURE;
+      
+      if (split == prev_point)
+      {
+          // new_edge is very small compared to split_edge
+        assert(!split_edge);
+        old_facets.clean_out();
+        if (!collapse_edge(prev_point, new_point, &old_facets))
+        {
+          if (!collapse_edge(new_point, prev_point, &old_facets))
+          {
+            assert(0);
+            return CUBIT_FAILURE;
+          }
+          std::swap(prev_point, new_point);
+        }
+        if (dead_ptrs)
+          dead_ptrs->append( new_edge );
+        facets -= old_facets;
+      
+        if (edge_list.is_at_beginning())
+          new_edge = 0;
+        else
+        {
+          new_edge = edge_list.get_and_step();
+          orig_new_len = new_edge->length();
+          split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+        }
+         
+        continue;
+      }
+      
+      if (split_edge)
+      {
+        if (curve_edge->other_point(prev_point))
+          std::swap(split_edge, curve_edge);
+      }
+      else
+      {
+        assert(split == curve_point);
+        split_edge = curve_edge;
+        if (curve_edges.is_at_beginning())
+          curve_edge = 0;
+        else
+        {
+          curve_edge = curve_edges.get_and_step();
+          orig_crv_len = curve_edge->length();
+          split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+        }
+      }
+      
+        // Move split point to position of other point (safely)
+#ifdef PART_SURF_REFACET
+      double d_sqr = (edge_pos - new_point->coordinates()).length_squared();
+      bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS);
+      old_facets.clean_out();
+      new_facets.clean_out();
+      if (close)
+        dynamic_cast<CubitPointData*>(split)->set(new_point->coordinates());
+      else if (!fix_move_point( split, new_point->coordinates(), facets, old_facets, new_facets ))
+        return CUBIT_FAILURE;
+      facets -= old_facets;
+      facets += new_facets;
+#else
+      dynamic_cast<CubitPointData*>(split)->set(new_point->coordinates());
+#endif
+      
+      CubitStatus s1 = split->merge_points(new_point);
+      CubitStatus s2 = split_edge->merge_edges(new_edge);
+      if (dead_ptrs)
+        dead_ptrs->append(new_edge);
+      assert(s1 && s2);
+      prev_point = split;
+      
+      if (edge_list.is_at_beginning())
+        new_edge = 0;
+      else
+      {
+        new_edge = edge_list.get_and_step();
+        orig_new_len = new_edge->length();
+        split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+      }  
+    }
+    else
+    {
+      CubitFacetEdgeData* split_edge = 0;
+      CubitVector edge_pos;
+      new_edge->closest_point( curve_point->coordinates(), edge_pos );
+      CubitPoint* split = split_edge_closest( new_edge, 
+                                              edge_pos, 
+                                              split_tol,
+                                              split_edge,
+                                              facets );
+      if(!split)
+        return CUBIT_FAILURE;
+      
+      if (split == prev_point)
+      {
+          // curve_edge is very small compared to split_edge
+        assert(!split_edge);
+        old_facets.clean_out();
+        if (!collapse_edge(prev_point,curve_point,&old_facets))
+        {
+          if (!collapse_edge(curve_point, prev_point, &old_facets))
+          {
+            assert(0);
+            return CUBIT_FAILURE;
+          }
+          std::swap(curve_point, prev_point);
+        }
+        facets -= old_facets;
+        if (dead_ptrs)
+          dead_ptrs->append(curve_edge);
+      
+        if (curve_edges.is_at_beginning())
+          curve_edge = 0;
+        else
+        {
+          curve_edge = curve_edges.get_and_step();
+          orig_crv_len = curve_edge->length();
+          split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+        }  
+        continue;
+      }
+        
+      if (split_edge)
+      {
+        if (new_edge->other_point(prev_point))
+          std::swap(split_edge, new_edge);
+      }
+      else
+      {
+        assert(split == new_point);
+        split_edge = new_edge;
+        if (edge_list.is_at_beginning())
+          new_edge = 0;
+        else
+        {
+          new_edge = edge_list.get_and_step();
+          orig_new_len = new_edge->length();
+          split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+        }  
+      }    
+      
+        // Move split point to position of other point (safely)
+#ifdef PART_SURF_REFACET
+      double d_sqr = (edge_pos - curve_point->coordinates()).length_squared();
+      bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS);
+      old_facets.clean_out();
+      new_facets.clean_out();
+      if (close)
+        dynamic_cast<CubitPointData*>(split)->set(curve_point->coordinates());
+      else if (!fix_move_point( split, curve_point->coordinates(), facets, old_facets, new_facets ))
+        return CUBIT_FAILURE;
+      facets -= old_facets;
+      facets += new_facets;
+#else
+      dynamic_cast<CubitPointData*>(split)->set(curve_point->coordinates());
+#endif
+      
+      CubitStatus s2, s1 = CUBIT_SUCCESS;
+      if (curve_point != split)
+        s1 = curve_point->merge_points(split);
+      s2 = curve_edge->merge_edges(split_edge);
+      if (dead_ptrs)
+        dead_ptrs->append(split_edge);
+      assert(s1 && s2);
+      prev_point = curve_point;
+      
+      if (curve_edges.is_at_beginning())
+        curve_edge = 0;
+      else
+      {
+        curve_edge = curve_edges.get_and_step();
+        orig_crv_len = curve_edge->length();
+        split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
+      }  
+    }
+  }
+  
+  return CUBIT_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Retriangulate if necessary for moving a boundary point
+//                 into the interior of a facet patch.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 12/07/03
+//-------------------------------------------------------------------------
+CubitStatus PartSurfFacetTool::fix_move_point( 
+                                      CubitPoint* point,
+                                      const CubitVector& new_pos,
+                                      const DLIList<CubitFacetData*>& facetds,
+                                      DLIList<CubitFacetData*>& old_facets,
+                                      DLIList<CubitFacetData*>& new_facets,
+                                      PartitionSurface* surface )
+{
+  int i;
+  DLIList<CubitFacet*> facets(facetds.size());
+  for (i = 0; i < facetds.size(); i++)
+    facets.append(facetds.next(i));
+  
+    // Look for a triangle containing the passed point.
+  CubitVector closest_pos, vect;
+  CubitFacet* facet = closest_facet(new_pos, facetds, closest_pos );
+  if ( facet == NULL)
+    return CUBIT_FAILURE;
+
+  if (facet->point_index(point) >= 0)
+  {
+    dynamic_cast<CubitPointData*>(point)->set(new_pos);
+    return CUBIT_SUCCESS;
+  }
+
+  PRINT_WARNING("Refacetting surface near (%f,%f,%f)\n",
+    new_pos.x(), new_pos.y(), new_pos.z());
+
+    // Line direction
+  const CubitVector dir(point->coordinates() - new_pos);
+
+  if (DEBUG_FLAG(145)) 
+  { 
+    GfxDebug::draw_facet(facet, CUBIT_BLUE); 
+    GfxDebug::draw_point(point->coordinates(), CUBIT_BLUE);
+    GfxDebug::draw_point(new_pos, CUBIT_CYAN);
+    GfxDebug::draw_line(point->coordinates(), new_pos, CUBIT_BLUE);
+    GfxDebug::flush(); 
+  }
+  
+    // Find where line exits first triangle
+  CubitFacetEdge* edge = 0;
+  bool leftofpoint[3];
+  for ( i = 0; i < 3; i++)
+  {
+    CubitVector vect = facet->point(i)->coordinates() - new_pos;
+    vect *= dir;
+    leftofpoint[i] = (vect % facet->normal()) >= 0.0;
+  }
+  
+  for ( i = 0; i < 3; ++i)
+    if (leftofpoint[i] && !leftofpoint[(i+1)%3])
+    {
+      edge = facet->edge((i+2)%3);
+      break;
+    }
+  
+  if (!edge)
+    return CUBIT_FAILURE;
+  
+    // Find the set of triangles the line from the old 
+    // position to the new position crosses.
+  DLIList<CubitFacet*> intersect_list, edge_facets;
+  while (facet->point_index(point) < 0)
+  {
+    intersect_list.append(facet);
+
+    if (DEBUG_FLAG(145)) 
+    { 
+      GfxDebug::draw_facet_edge(edge, CUBIT_WHITE); 
+      GfxDebug::draw_facet(facet, CUBIT_BLUE); 
+      GfxDebug::flush(); 
+    }
+      
+      // Find the facet on the other side of the edge
+    edge_facets.clean_out();
+    if (surface)
+      PartSurfFacetTool::edge_facets(surface, edge, edge_facets);
+    else
+      PartSurfFacetTool::edge_facets( edge, facets, edge_facets );
+    edge_facets.move_to(facet);
+    assert(edge_facets.get() == facet);
+
+    if(edge_facets.size() != 2)
+      break;
+    
+    facet = edge_facets.step_and_get();
+    
+      // Find the edge that the line intersects exiting the facet
+    i = facet->edge_index(edge);
+    vect = facet->point(i)->coordinates() - new_pos;
+    vect *= dir;
+    if (vect % facet->normal() >= 0.0)
+      edge = facet->edge((i+1)%3);
+    else
+      edge = facet->edge((i+2)%3);
+  }
+  
+  if (facet)
+  {
+    if (DEBUG_FLAG(145)) 
+    { 
+      GfxDebug::draw_facet_edge(edge, CUBIT_WHITE); 
+      GfxDebug::flush(); 
+    }
+    intersect_list.append_unique(facet);
+  }
+  
+    // Get ordered boundary
+  DLIList<CubitPoint*> boundary_list;
+  DLIList<CubitFacetEdge*> point_edges;
+  CubitFacetEdge* prev_edge = 0;
+  CubitFacet* prev_facet = 0;
+    // Find one boundary edge to start with
+  for (i = intersect_list.size(); !prev_edge && i--; )
+  {
+    CubitFacet* facet = intersect_list.get_and_step();
+    for (int j = 0; j < 3; j++)
+    {
+      CubitFacetEdge* edge = facet->edge(j);
+      edge_facets.clean_out();
+     if (surface)
+       PartSurfFacetTool::edge_facets( surface, edge, edge_facets);
+     else
+       PartSurfFacetTool::edge_facets( edge, facets, edge_facets );
+      edge_facets.intersect(intersect_list);
+      if (edge_facets.size() == 1)
+      {
+        prev_edge = edge;
+        prev_facet = facet;
+        break;
+      }
+    }
+  }
+  CubitFacetEdge* first_edge = prev_edge;
+    // Traverse boundary edges in order
+  do 
+  {
+    int direction = prev_facet->edge_use( prev_facet->edge_index(prev_edge) );
+    CubitPoint* pt = prev_edge->point( direction == -1 ? 0 : 1 );
+    point_edges.clean_out();
+    pt->edges( point_edges );
+    
+    if (DEBUG_FLAG(145))
+    {
+      GfxDebug::draw_facet_edge( prev_edge, CUBIT_LIGHTBLUE );
+      GfxDebug::flush();
+    }
+    boundary_list.append(pt);
+    
+    point_edges.move_to(prev_edge);
+    assert(point_edges.get() == prev_edge);
+    point_edges.extract();
+    prev_edge = 0;
+
+    while (point_edges.size())
+    {
+      CubitFacetEdge* edge = point_edges.pop();
+      edge_facets.clean_out();
+      if (surface)
+        PartSurfFacetTool::edge_facets( surface, edge, edge_facets);
+      else
+        PartSurfFacetTool::edge_facets( edge, facets, edge_facets );
+      edge_facets.intersect(intersect_list);
+      if (edge_facets.size() == 1)
+      {
+        if (prev_edge) {
+          prev_edge = 0;
+          break;
+        }
+        prev_edge = edge;
+        prev_facet = edge_facets.get();
+      }
+    }
+  
+    if (!prev_edge)
+    {
+      PRINT_ERROR("Problems finding boundary to re-facet around split point.\n");
+      return CUBIT_FAILURE;
+    }
+  } while (prev_edge != first_edge);
+
+ 
+    // Construct new facets in affected region by connecting 
+    // the split point to each boundary point
+  int junk = 0;
+  //DLIList<CubitFacetData*> new_facets, old_facets(intersect_list.size());
+  if (!boundary_list.move_to(point))
+  {
+    PRINT_ERROR("Problems finding region around split point for re-facetting.\n");
+    return CUBIT_FAILURE;
+  }
+  boundary_list.step();
+  CubitPoint* prev_pt = boundary_list.get_and_step();
+  for (i = boundary_list.size(); i > 2; i--)
+  {
+    CubitPoint* next_pt = boundary_list.get_and_step();
+    CubitFacetData* new_facet = new CubitFacetData( point, prev_pt, next_pt, &junk);
+    new_facets.append(new_facet);
+    prev_pt = next_pt;
+    
+    if (DEBUG_FLAG(145))
+    {
+      GfxDebug::draw_facet( new_facet, CUBIT_YELLOW );
+      GfxDebug::flush();
+    }
+  }
+  
+  CAST_LIST( intersect_list, old_facets, CubitFacetData );
+  assert(intersect_list.size() == old_facets.size());
+  dynamic_cast<CubitPointData*>(point)->set(new_pos);
+  //replace_facets( old_facets, new_facets );
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Find closest facet and point on facet
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/28/03
+//-------------------------------------------------------------------------
+CubitFacet* PartSurfFacetTool::closest_facet(
+                                   const CubitVector& input_position,
+                                   const DLIList<CubitFacetData*>& facet_list,
+                                   CubitVector& result_position )
+{
+  CubitFacet* return_val = 0;
+  double closest_dist_sqr = CUBIT_DBL_MAX;
+  CubitVector facet_position;
+  
+  const int size = facet_list.size();
+  for ( int i = 0; i < size; i++ ) {
+    CubitFacet* facet = facet_list.next(i);
+    closest_pt_on_facet( facet, input_position, facet_position );
+    double dist_sqr = (input_position - facet_position).length_squared();
+    if ( dist_sqr < closest_dist_sqr ) {
+      closest_dist_sqr = dist_sqr;
+      result_position = facet_position;
+      return_val = facet;
+    }
+  }
+  
+  return return_val;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Return edge start/end if input position is sufficiently
+//                 close.  Otherwise split the edge and return the new
+//                 point.
+//
+// Special Notes : For all facets modified by this operation, owning surfaces
+//                 will be notified of the change.  For any un-owned facets,
+//                 new facets will be appended to the passed list.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 12/01/03
+//-------------------------------------------------------------------------
+CubitPoint* PartSurfFacetTool::split_edge_closest( 
+                                     CubitFacetEdgeData* old_edge,
+                                     const CubitVector& pos,
+                                     double tolerance,
+                                     CubitFacetEdgeData*& new_edge,
+                                     DLIList<CubitFacetData*>& new_facets )
+{
+    // square of absolute tolerance
+  const double GEOM_TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS; 
+    // tolerance as fraction of edge length.
+  const double TOL_SQR = tolerance < GEOM_TOL_SQR ? GEOM_TOL_SQR : tolerance * tolerance;
+  
+  new_edge = 0;
+
+  const CubitVector start(old_edge->point(0)->coordinates());
+  const CubitVector end(old_edge->point(1)->coordinates());
+//   const CubitVector dir(end - start);
+  //const double fract = (dir % (pos - start)) / dir.length_squared();
+
+    // If near the start/end of the edge and start/end point is
+    // not already owned by some other vertex
+  const double start_sqr = (start - pos).length_squared();
+  const double end_sqr   = (end   - pos).length_squared();
+  if (start_sqr < TOL_SQR && !TDVGFacetOwner::get(old_edge->point(0)))
+    return old_edge->point(0);
+  else if (end_sqr < TOL_SQR && !TDVGFacetOwner::get(old_edge->point(1)))
+    return old_edge->point(1);
+
+    // Else if start/end of edge are same position as vertex
+  else if(start_sqr < GEOM_TOL_SQR)
+    return old_edge->point(0);
+  else if(end_sqr < GEOM_TOL_SQR)
+    return old_edge->point(1);
+
+    // Otherwise split the edge
+  CubitFacet* a_face = old_edge->adj_facet(0);
+  CubitFacetData* facet = dynamic_cast<CubitFacetData*>(a_face);
+  if (!facet)
+    return 0;
+
+  //CubitVector edge_pos((1.0-edge_param)*edge_start + edge_param*edge_end);
+  CubitPoint* start_pt = old_edge->point(0);
+  CubitPoint*   end_pt = old_edge->point(1);
+  CubitPoint*   new_pt = facet->split_edge( start_pt, end_pt, pos );
+  CubitFacetEdge* temp_edge = new_pt->shared_edge(end_pt);
+  new_edge = dynamic_cast<CubitFacetEdgeData*>(temp_edge);
+  if (!new_edge)
+    return 0;
+  
+    // Update partition curve facetting
+  PartitionCurve* edge_owner = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(old_edge));
+  if (edge_owner)
+    edge_owner->notify_split(old_edge, new_edge);
+
+    // Update partition surfaces for split of adjacent facets
+  int i, junk = -1;
+  DLIList<CubitFacet*> facets(old_edge->num_adj_facets());
+  old_edge->facets(facets);
+  
+  for ( i = facets.size(); i--;  )
+  {
+    a_face = facets.get_and_step();
+    facet = dynamic_cast<CubitFacetData*>(a_face);
+    assert(!!facet);
+    int edge_index = facet->edge_index( start_pt, new_pt, junk );
+    CubitPoint* other_pt = facet->point( edge_index );
+    if (!other_pt->shared_edge( new_pt ))
+      new CubitFacetEdgeData( other_pt, new_pt );
+
+    CubitFacet* a_face = facet->shared_facet( new_pt, other_pt );
+    CubitFacetData* other_facet = dynamic_cast<CubitFacetData*>(a_face);
+    if (!other_facet) { assert(0); continue; }
+
+    PartitionEntity* owner = TDVGFacetOwner::get(facet);
+    PartitionSurface* surf = dynamic_cast<PartitionSurface*>(owner);
+    assert(!owner || surf);
+    
+    if (owner)
+      owner->notify_split( facet, other_facet );
+    else
+      new_facets.append(other_facet);
+  }
+  
+  return new_pt;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Spatially match a set of geometric points one-to-one
+//                 with a subset of a set of facet vertices.
+//
+// Special Notes : If the geometric point already has an attached facet
+//                 point, the points will be merged such that the facet
+//                 point originally on the geometric point survives the
+//                 merge.  If the geometric point does not already have
+//                 a facet point, the input facet point will be attached
+//                 to the geometric point.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 09/08/03
+//-------------------------------------------------------------------------
+CubitStatus PartSurfFacetTool::associate_points( 
+                                     DLIList<CubitPoint*>& facet_points,
+                                     DLIList<PartitionPoint*>& geom_points )
+{
+  int i;
+  DLIList<int> geom_indices(geom_points.size());
+  
+  for (i = 0; i < geom_points.size(); i++ )
+    geom_indices.append(i);
+
+  for (i = facet_points.size(); i--; )
+    facet_points.step_and_get()->marked(-1);
+
+  geom_points.reset();
+  facet_points.reset();
+  while (geom_indices.size())
+  {
+    int index = geom_indices.pop();
+    PartitionPoint* geom_pt = geom_points.next(index);
+    const CubitVector pos(geom_pt->coordinates());
+    double shortest_dist_sqr = CUBIT_DBL_MAX;
+    int closest_index = -1;
+    for (i = 0; i < facet_points.size(); i++ )
+    {
+      CubitPoint* facet_pt = facet_points.next(i);
+      double dist_sqr = (pos - facet_pt->coordinates()).length_squared();
+      if (dist_sqr < shortest_dist_sqr)
+      {
+        if (facet_pt->marked() == -1)
+        {
+          shortest_dist_sqr = dist_sqr;
+          closest_index = i;
+        }
+        else 
+        {
+          int j = facet_pt->marked();
+          CubitPoint* other_point = facet_points.next(j);
+          double other_dist_sqr = (pos - other_point->coordinates()).length_squared();
+          if (other_dist_sqr > dist_sqr)
+          {
+            shortest_dist_sqr = dist_sqr;
+            closest_index = i;
+            facet_pt->marked(-1);
+            geom_indices.append(j);
+          }
+        }
+      }
+    }
+    
+    if (closest_index < 0)
+    {
+      assert(false);
+      for (i = facet_points.size(); i--; )
+        facet_points.step_and_get()->marked(0);
+      for (i = geom_points.size(); i--; )
+        geom_points.step_and_get()->mark = 0;
+      return CUBIT_FAILURE;
+    }
+    geom_pt->mark = closest_index;
+    facet_points.next(closest_index)->marked(index);
+  }
+  
+  for (i = facet_points.size(); i--; )
+    facet_points.step_and_get()->marked(0);
+  
+  facet_points.reset();
+  for (i = geom_points.size(); i--; )
+  {
+    PartitionPoint* geom_pt = geom_points.step_and_get();
+    CubitPoint* facet_pt = facet_points.next(geom_pt->mark);
+    geom_pt->mark = 0;
+    
+    assert(!TDVGFacetOwner::get(facet_pt));
+    facet_pt->set(geom_pt->coordinates());
+    
+    CubitPointData* point_data = dynamic_cast<CubitPointData*>(facet_pt);
+    assert(!!point_data);
+    
+    if (geom_pt->facet_point())
+      geom_pt->facet_point()->merge_points( point_data );
+    else
+      geom_pt->facet_point(point_data);
+  }
+  
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Get points and edges in facet patch, separated into
+//                 boundary and internal sets where a boundary point is
+//                 a point for which one or more adjacent edges is on the
+//                 boundary of the patch.
+//
+// Special Notes : Aborts and returns failure if the input facets are not
+//                 a manifold patch.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 09/08/03
+//-------------------------------------------------------------------------
+CubitStatus PartSurfFacetTool::get_facet_points_and_edges(
+                                   const DLIList<CubitFacetData*>& facets,
+                                   DLIList<CubitPoint*>& boundary_points,
+                                   DLIList<CubitPoint*>& interior_points,
+                                   DLIList<CubitFacetEdge*>& boundary_edges,
+                                   DLIList<CubitFacetEdge*>& interior_edges )
+{
+  int i, j;
+  CubitStatus result = CUBIT_SUCCESS;
+  CubitFacetData* facet;
+  DLIList<CubitFacetEdge*> edge_list;
+  const int count = facets.size();
+  
+    // Initialize marks
+  for (i = 0; i < count; i++ )
+  {
+    facet = facets.next(i);
+    for (j = 0; j < 3; j++)
+    {
+      facet->edge(j)->marked(0);
+      facet->point(j)->marked(1);
+    }
+  }
+  
+    // Mark each edge with a count of the number of
+    // adjcent facets.
+  for (i = 0; i < count; i++ )
+  {
+    facet = facets.next(i);
+    for (j = 0; j < 3; j++)
+      facet->edge(j)->marked(facet->edge(j)->marked() + 1);
+  }
+  
+    // Collect points and clear point marks
+  for (i = 0; i < count; i++ )
+  {
+    facet = facets.next(i);
+    for (j = 0; j < 3; j++)
+    {
+      CubitPoint* point = facet->point(j);
+      if (!point->marked())
+        continue;
+      point->marked(0);
+      
+      point->edges(edge_list);
+      bool boundary = false;
+      while (edge_list.size())
+        if (edge_list.pop()->marked() == 1)
+          boundary = true;
+      if (boundary)
+        boundary_points.append(point);
+      else 
+        interior_points.append(point);
+    }
+  }
+  
+    // Collect edges and clear edge marks   
+  for (i = 0; i < count; i++ )
+  {
+    facet = facets.next(i);
+    for (j = 0; j < 3; j++)
+    {
+      CubitFacetEdge* edge = facet->edge(j);
+      switch (edge->marked())
+      {
+        case 0:
+          continue;
+        case 1:
+          boundary_edges.append(edge);
+          break;
+        case 2:
+          interior_edges.append(edge);
+          break;
+        default:
+          result = CUBIT_FAILURE;
+          assert(false);
+      }
+      edge->marked(0);
+    }
+  }
+  
+  return result;
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Get facets adjacent to edge and owned by this surface.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 12/07/03
+//-------------------------------------------------------------------------
+void PartSurfFacetTool::edge_facets( PartitionSurface* surf,
+                                     CubitFacetEdge* edge,
+                                     DLIList<CubitFacet*>& facets )
+{
+  edge->facets(facets);
+
+  for (int i = facets.size(); i--; )
+    if (TDVGFacetOwner::get(facets.step_and_get()) != surf)
+      facets.change_to(0);
+  
+  facets.remove_all_with_value(0);
+}
+
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Get facets in passed list adjacent to passed edge
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 12/07/03
+//-------------------------------------------------------------------------
+void PartSurfFacetTool::edge_facets( CubitFacetEdge* edge,
+                                    const DLIList<CubitFacet*>& input_facets,
+                                    DLIList<CubitFacet*>& output_facets )
+{
+  edge->facets(output_facets);
+  output_facets.intersect( input_facets );
+}
Index: /cgm/geom/virtual/VGLoopTool.hpp
===================================================================
--- /cgm/geom/virtual/VGLoopTool.hpp (revision 1040)
+++ /cgm/geom/virtual/VGLoopTool.hpp (revision 1040)
@@ -0,0 +1,139 @@
+//-------------------------------------------------------------------------
+// Filename      : VGLoopTool.hpp
+//
+// Purpose       : Loop Modification Code
+//
+// Special Notes : Provides common functionality for composite and 
+//                 partition geometry.
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 08/08/02
+//-------------------------------------------------------------------------
+
+#ifndef VG_LOOP_TOOL
+#define VG_LOOP_TOOL
+
+ 
+#include "CubitDefines.h"
+#include "DLIList.hpp"
+#include <vector>
+
+class CubitVector;
+
+template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
+class VGLoopTool 
+{
+public:
+/*  
+  static CubitStatus remove_curve( COEDGE* coedge1, 
+                                   COEDGE* coedge2,
+                                   DLIList<COEDGE*>& new_loop_coedges );
+    //- Remove a curve from loop topology
+    //- coedge1/2:  The two coedges of a curve
+    //- If the passed coedges are in different loops, the loops
+    //- will be combined into a single loop and new_loop_coedges will
+    //- be empty.  
+    //- If the passed coedges are in the same loop, unless the coedges
+    //- are adjacent in that loop, the loop will be split into two
+    //- loops and the coedges for the new loop passed back in 
+    //- new_loop_coedges.
+
+  static CubitStatus insert_curve( COEDGE* new_coedge1, 
+                                   COEDGE* new_coedge2,
+                                   SURFACE* surface,
+                                   LOOP*& new_loop1,
+                                   LOOP*& new_loop2 );
+    //- Insert a curve into the loop topology
+    //- new_coedge1/2:  The two new coedges of the curve to be inserted
+    //- loop1/2_coedge: Any coedges of the existing loops in which the
+    //-                 new coedges are to be inserted.  (May be NULL).
+    //- new_loop_coedges: The ordered list of coedges from which the
+    //-                   caller should create a new loop.  The loops
+    //-                   are specified with a coedge to avoid the need
+    //-                   for this class to also be a template of the
+    //-                   loop type.
+    //- Note:  In the comments below, when it is stated that a new loop
+    //-        is created, this means that the coedges for the new loop
+    //-        are passed back in new_loop_coedges.  This function does
+    //-        not do the actual loop creation.
+    //-
+    //- If both loop1_coedge and loop2_coedge are null, both coedges
+    //- are passed back in new_loop_coedges without any topology
+    //- modification.  The caller should create either one or two
+    //- new loops (a curve imprinted on the interior of the surface
+    //- or a hole in the surface and a new surface in the hole)
+    //- depending on the curve having the same start and end vertices.
+    //-
+    //- If one of loop1_coedge and loop2_coedge is NULL, or both
+    //- are part of the same loop, both new coedges are inserted in 
+    //- the same loop.  This will result in either a sipe or the 
+    //- loop being split into two loops.  If the loop is split, the 
+    //- coedges for the new loop are passed back in new_loop_coedges.
+    //-
+    //- If both loop1_coedge and loop2_coedge are non-null and part
+    //- of different loops, the loops are joined using the new 
+    //- coedges as a bridge.
+*/
+  static double loop_angle_metric( COEDGE* first_coedge );
+/*  
+  static bool is_position_within_loop( const CubitVector& position,
+                                       COEDGE* first_coedge,
+                                       CubitVector* closest_on_loop = 0,
+                                       CubitVector* normal = 0 );
+                                       
+  static double loop_area( COEDGE* first_coedge );
+
+  static CubitStatus closest_point_trimmed( 
+                                      DLIList<COEDGE*>& surface_coedges,
+                                      const CubitVector& from_pt,
+                                      CubitVector& result_pt,
+                                      CubitPointContainment* cont = 0 );
+*/
+  static void get_loop_polyline( COEDGE* first_coedge,
+                                 std::vector<CubitVector>& result_set );
+
+private:
+/*  
+  static CubitStatus previous_coedge( COEDGE* coedge, SURFACE* surface,
+                                      COEDGE*& result );
+    //- Find the coedge in the passed surface after which the passed
+    //- coedge will be inserted.  The returned coedge will share its
+    //- start point (end point of the curve if the coedge sense is 
+    //- reversed) with the end point (start point of the curve if the
+    //- coedge sense is reversed) of the passed coedge.  If the coedge
+    //- has no points in common with any loops in the passed surface,
+    //- the result is NULL and CUBIT_SUCCESS is returned.  CUBIT_FAILURE
+    //- is returned if something is wrong with the topology.
+  
+  static COEDGE* closest_loop_coedge( const CubitVector& from_pt,
+                                      COEDGE* first_coedge,
+                                      COEDGE*& other_coedge,
+                                      CubitVector* closest_pt = 0 );
+
+  static CubitStatus closest_surface_coedge( SURFACE* surface,
+                                         const CubitVector& from_pt,
+                                         COEDGE*& coedge1,
+                                         COEDGE*& coedge2,
+                                         CubitVector* pt_on_curve = 0 );
+
+  static bool inside_of_curve( const CubitVector& curve_tangent,
+                               const CubitVector& curve_position,
+                               const CubitVector& surface_position,
+                               const CubitVector& surface_normal );                                     
+
+  static bool odd_coedge_count( COEDGE* coedge );
+*/  
+  static CubitStatus get_loop_polygon( COEDGE* first_coedge,
+                                       DLIList<CubitVector*>& polygon_points );
+                                       
+};
+
+#ifdef TEMPLATE_DEFS_INCLUDED
+#  define INCLUDED_FROM_VG_LOOP_TOOL_HPP
+#  include "VGLoopTool.cpp"
+#  undef INCLUDED_FROM_VG_LOOP_TOOL_HPP
+#endif
+
+#endif
+
Index: /cgm/geom/virtual/CompositeSurface.cpp
===================================================================
--- /cgm/geom/virtual/CompositeSurface.cpp (revision 1040)
+++ /cgm/geom/virtual/CompositeSurface.cpp (revision 1040)
@@ -0,0 +1,1910 @@
+//-------------------------------------------------------------------------
+// Filename      : CompositeSurface.cc
+//
+// Purpose       : Implementation of the CompositeSurface class.
+//
+// Special Notes : 
+// 
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//
+// Owner         : Jason Kraftcheck
+//-------------------------------------------------------------------------
+
+#include <assert.h>
+
+#include "VirtualQueryEngine.hpp"
+
+#include "Surface.hpp"
+
+#include "CompositeSurface.hpp"
+#include "CompositeLoop.hpp"
+#include "CompositeCurve.hpp"
+#include "CompositePoint.hpp"
+#include "CompositeShell.hpp"
+#include "CompositeLump.hpp"
+
+#include "CompositeEngine.hpp"
+#include "CompSurfFacets.hpp"
+#include "GfxDebug.hpp"
+
+/*
+#include "CpuTimer.hpp"
+static double trimmed_time = 0.0;
+static double contain_time = 0.0;
+static double closest_time = 0.0;
+static int total_calls = 0;
+static int contain_trim_count = 0;
+static int error_count = 0;
+static CpuTimer timer;
+*/
+
+CompositeSurface::CompositeSurface( Surface* surface )
+  : stitchPartner(0), firstCoSurf(0), firstLoop(0), hiddenSet(0), facetTool(0),
+  HadBridgeRemoved(0)
+{
+  assert( surface != NULL );
+  compGeom = new CompositeGeom(1);
+  compGeom->append( surface, CUBIT_FORWARD );
+  if( surface->owner() )
+    surface->owner()->swap_bridge( surface, this, false );
+  surface->owner(this);
+}
+
+CompositeSurface::CompositeSurface( CompositeGeom* geometry )
+  : compGeom( geometry ),
+    stitchPartner(0),
+    firstCoSurf(0),
+    firstLoop(0),
+    hiddenSet(0),
+    facetTool(0),
+    HadBridgeRemoved(0)
+{
+  assert( geometry != NULL );
+  for( int i = 0; i < compGeom->num_entities(); i++ )
+  {
+    GeometryEntity* entity = compGeom->entity(i);
+    assert( !entity->owner() );
+    entity->owner(this);
+  }
+}
+
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Desctructor
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 
+//-------------------------------------------------------------------------
+CompositeSurface::~CompositeSurface()
+{
+  while( firstCoSurf )
+  {
+    CompositeCoSurf* cosurf = firstCoSurf;
+    remove( cosurf );
+    if( cosurf->get_shell() )
+      cosurf->get_shell()->remove( cosurf );
+    delete cosurf;
+  }
+  
+  while( firstLoop )
+    remove( firstLoop );
+  
+  for( int j = 0; j < num_surfs(); j++ )
+    if( get_surface(j)->owner() == this )
+      get_surface(j)->owner(0);
+  
+  if( stitchPartner )
+  {
+    stitchPartner->stitchPartner = 0;
+    stitchPartner = 0;
+  }
+  
+  delete hiddenSet;
+  delete compGeom;
+  delete facetTool;
+  hiddenSet = (HiddenEntitySet*)0xbdbdbdbd;
+  compGeom = (CompositeGeom*)0xbdbdbdbd;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Add a CompositeLoop to child list
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/06/02
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::add( CompositeLoop* loop )
+{
+  if( loop->mySurface )
+  {
+    assert(0);
+    return CUBIT_FAILURE;
+  }
+  
+  loop->mySurface = this;
+  loop->loopNext = firstLoop;
+  firstLoop = loop;
+  
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Remove a child loop
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/06/02
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::remove( CompositeLoop* loop )
+{
+  if( loop->mySurface != this )
+    return CUBIT_FAILURE;
+ 
+  if( firstLoop == loop )
+  {
+    firstLoop = loop->loopNext;
+  }
+  else
+  {
+    CompositeLoop *prev = firstLoop,
+                  *next = firstLoop->loopNext;
+    
+    while( next != loop )
+    {
+      assert( next != NULL );
+      prev = next;
+      next = next->loopNext;
+    }
+    
+    prev->loopNext = next->loopNext;
+  }
+  
+  loop->loopNext = 0;
+  loop->mySurface = 0;
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Add a CoSurface to this Surface
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 08/07/02
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::add( CompositeCoSurf* cosurf )
+{
+  if( cosurf->mySurface )
+    return CUBIT_FAILURE;
+  
+  cosurf->mySurface = this;
+  cosurf->surfaceNext = firstCoSurf;
+  firstCoSurf = cosurf;
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Remove a CoSurface
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 08/07/02
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::remove( CompositeCoSurf* cosurf )
+{
+  if( cosurf->mySurface != this )
+    return CUBIT_FAILURE;
+  
+  if( cosurf == firstCoSurf )
+    firstCoSurf = cosurf->surfaceNext;
+  else
+  {
+    CompositeCoSurf* prev = firstCoSurf;
+    while( prev && prev->surfaceNext != cosurf )
+      prev = prev->surfaceNext;
+    assert( prev != NULL );
+    prev->surfaceNext = cosurf->surfaceNext;
+  }
+  
+  cosurf->mySurface = 0;
+  cosurf->surfaceNext = 0;
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Get a CoSurface attaching this surface to the passed 
+//                 Shell or Lump
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 08/07/02
+//-------------------------------------------------------------------------
+CompositeCoSurf* CompositeSurface::find_first( CompositeShell* shell ) const
+{
+  CompositeCoSurf* cos = firstCoSurf;
+  while( cos && cos->get_shell() != shell )
+    cos = cos->next_in_surface();
+  return cos;
+}
+CompositeCoSurf* CompositeSurface::find_first( CompositeLump* lump ) const
+{
+  CompositeCoSurf* cos = firstCoSurf;
+  while( cos && (!cos->get_shell() || cos->get_shell()->get_lump() != lump ) )
+    cos = cos->next_in_surface();
+  return cos;
+}
+CompositeCoSurf* CompositeSurface::find_next( CompositeCoSurf* cosurf ) const
+{
+  CompositeCoSurf* cos = cosurf;
+  while( cos && cos->get_shell() != cosurf->get_shell() )
+    cos = cos->next_in_surface();
+  return cos;
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Split this CompositeSurface into two.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/06/02
+//-------------------------------------------------------------------------
+CompositeSurface* CompositeSurface::split( VGArray<int>& indices_to_move )
+{
+  int i;
+  
+  for( i = 0; i < indices_to_move.size(); i++ )
+    if( indices_to_move[i] < 0 || indices_to_move[i] >= num_surfs() )
+      return 0;
+  
+  CompositeGeom* new_geom = compGeom->split( indices_to_move );
+  if( !new_geom )
+    return 0;
+  
+  for( i = 0; i < new_geom->num_entities(); i++ )
+    new_geom->entity(i)->owner( 0 );
+    
+  delete facetTool;
+  facetTool = 0;
+  
+  return new CompositeSurface( new_geom );
+}
+
+  
+//-------------------------------------------------------------------------
+// Purpose       : Combine composite surfaces
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/06/02
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::combine( CompositeSurface* dead_surf )
+{
+  int old_size = compGeom->num_entities();
+
+  // Merge the "surfaces_to_ignore" list.
+  surfacesToIgnore.merge_unique(dead_surf->surfacesToIgnore);
+
+  compGeom->merge( *(dead_surf->compGeom) );
+  if( dead_surf->hiddenSet != 0 )
+    hidden_entities().merge( dead_surf->hiddenSet );
+  for( int i = old_size; i < compGeom->num_entities(); i++ )
+  {
+    TopologyBridge* bridge = compGeom->entity(i);
+    assert( bridge->owner() == dead_surf );
+    bridge->owner( this );
+  }
+  
+  delete facetTool;
+  facetTool = 0;
+  
+  return CUBIT_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Return the bounding box
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 05/28/99
+//-------------------------------------------------------------------------
+CubitBox CompositeSurface::bounding_box() const
+{
+  return compGeom->bounding_box();
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : TB Queries
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/06/02
+//-------------------------------------------------------------------------
+void CompositeSurface::get_parents_virt( DLIList<TopologyBridge*>& list )
+{
+  DLIList<TopologyBridge*> parents, parents2;
+  for( int i = 0; i < num_surfs(); i++ )
+  {
+    parents.clean_out();
+    get_surface(i)->get_parents( parents );
+    parents.reset();
+    for ( int j = parents.size(); j--; )
+    {
+      TopologyBridge* shell = parents.get_and_step();
+      shell->get_parents( parents2 );
+      assert (parents2.size() == 1);
+      if (0 == dynamic_cast<CompositeLump*>(parents2.pop()->owner()))
+        list.append_unique( shell );
+    }
+  }
+  
+  CompositeCoSurf* cosurf = 0;
+  while ((cosurf = next_co_surface( cosurf )))
+    list.append_unique( cosurf->get_shell() );
+}
+void CompositeSurface::get_children_virt( DLIList<TopologyBridge*>& list )
+{
+  for( CompositeLoop* loop = firstLoop; loop; loop = loop->loopNext )
+    list.append( loop );
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Attach a CubitSimpleAttribute
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//-------------------------------------------------------------------------
+void CompositeSurface::append_simple_attribute_virt(
+						    CubitSimpleAttrib* simple_attrib_ptr )
+{
+  compGeom->add_attribute( simple_attrib_ptr );
+}
+
+//-------------------------------------------------------------------------
+// Purpose       : Remove an attached CubitSimpleAttrib
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//-------------------------------------------------------------------------
+void CompositeSurface::remove_simple_attribute_virt(
+						    CubitSimpleAttrib* simple_attrib_ptr )
+{
+  compGeom->rem_attribute( simple_attrib_ptr );
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Remove an all attached CubitSimpleAttrib
+//
+// Special Notes : 
+//
+// Creator       : Greg Nielson
+//
+// Creation Date : 07/10/98
+//-------------------------------------------------------------------------
+void CompositeSurface::remove_all_simple_attribute_virt()
+{
+  compGeom->rem_all_attributes( );
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Return the attached CubitSimpleAttribs.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::get_simple_attribute(
+						   DLIList<CubitSimpleAttrib*>& attrib_list )
+{
+  compGeom->get_attributes( attrib_list );
+  return CUBIT_SUCCESS;
+}
+CubitStatus CompositeSurface::get_simple_attribute(
+					const CubitString& name, DLIList<CubitSimpleAttrib*>& attrib_list )
+{
+  compGeom->get_attributes( name.c_str(), attrib_list );
+  return CUBIT_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Methods from TBOwner
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/07/02
+//-------------------------------------------------------------------------
+CubitStatus CompositeSurface::remove_bridge( TopologyBridge* bridge )
+{
+  int i = compGeom->index_of(bridge);
+  if( i < 0 )
+    return CUBIT_FAILURE;
+  
+  delete facetTool;
+  facetTool = 0;
+  
+  assert( bridge->owner() == this );
+  bridge->owner(0);
+  if (!compGeom->remove(i, true))
+    return CUBIT_FAILURE;
+  
+  if (compGeom->num_entities() == 0)
+    CompositeEngine::instance().notify_deactivated(this);
+  HadBridgeRemoved = 1;
+  return CUBIT_SUCCESS;
+}
+
+Surface* CompositeSurface::remove_surface( int index )
+{
+  Surface* result = get_surface(index);
+  if ( !result || !compGeom->remove(index,false) ) 
+    return 0;
+
+  result->owner(0);
+  return result;
+}
+
+  
+
+CubitStatus CompositeSurface::swap_bridge( TopologyBridge* o,
+                                           TopologyBridge* n, 
+                                           bool reversed )
+{
+  if( n->owner() )
+    return CUBIT_FAILURE;
+
+  int i = compGeom->index_of(o);
+  GeometryEntity* ge = dynamic_cast<GeometryEntity*>(n);
+  if( i >= 0 && ge != 0 )
+  {
+    o->owner(0);
+    n->owner(this);
+    if ( !compGeom->swap( i, ge ) )
+      return CUBIT_FAILURE;
+    
+    if (reversed)
+      compGeom->reverse_sense(i);
+    return CUBIT_SUCCESS;
+  }
+  else
+    return CUBIT_FAILURE;
+}
+CubitBoolean CompositeSurface::contains_bridge( TopologyBridge* bridge ) const
+{
+  return (CubitBoolean)(compGeom->index_of(bridge) >= 0);
+}
+
+
+    
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Return a pointer to VirtualQueryEngine
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//-------------------------------------------------------------------------
+GeometryQueryEngine* CompositeSurface::get_geometry_query_engine() const
+{
+  return VirtualQueryEngine::instance();
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Return the surface area.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//-------------------------------------------------------------------------
+double CompositeSurface::measure()
+{
+  return compGeom->measure();
+}
+
+
+//-------------------------------------------------------------------------
+// Purpose       : Find the closest point to the passed point.
+//
+// Special Notes : 
+//
+// Creator       : Jason Kraftcheck
+//
+// Creation Date : 03/10/98
+//-------------------------------------------------------------------------
+void CompositeSurface::closest_point_trimmed( CubitVector from_point,
+                                              CubitVector& point_on_surf )
+{
+  int index = closest_underlying_surface( from_point );
+  get_surface(index)->closest_point_trimmed( from_point, point_on_surf );
+}
+
+
+
+CubitStatus CompositeSurface::get_point_normal( CubitVector& origin,
+                                                CubitVector& normal )
+{
+  int count = num_surfs();
+  CubitVector* vect_list = new CubitVector[count];
+  double RESABS_SQUARED = CUBIT_RESABS * CUBIT_RESABS;
+  normal.set(0.0,0.0,0.0);
+	
+  if (count == 1)
+  {
+    return get_surface(0)->get_point_normal(origin,normal);
+  }
+  
+  for( int i = 0; i < count; i++ )
+  {
+    Surface* surf = get_surface(i);
+    if( surf->get_point_normal(origin,vect_list[i]) == CUBIT_FAILURE )
+    {
+      delete [] vect_list;
+      return CUBIT_FAILURE;
+    }
+
+    if( compGeom->sense(i) == CUBIT_REVERSED )
+      vect_list[i] *= -1.0;
+    normal += vect_list[i];
+  }
+  //If we reach this point, then all of the underlying surfaces are planar.
+  //Next check if they are coplanar.
+  if( normal.length_squared() < RESABS_SQUARED )
+  {
+    delete [] vect_list;
+    return CUBIT_FAILURE;
+  }
+  normal.normalize();
+  for( int j = 0; j < count; j++ )
+  {
+    if( fabs( 1.0 - (normal % ~vect_list[j]) ) > CUBIT_RESABS )
+    {
+      delete [] vect_list;
+      return CUBIT_FAILURE;
+    }
+  }
+	
+  delete [] vect_list;
+  CubitVector zero( 0.0, 0.0, 0.0 );
+  closest_point( zero, &origin );
+  return CUBIT_SUCCESS;
+}	
+
+// The CompositeSurface class has a variable 
+// "surfacesToIgnore" which specifies which surfaces
+// within the composite should be ignored during evaluation.
+// The "facetTool" variable has a corresponding list of flags
+// and this function syncs the flags in the "facetTool" variable
+// with those that are in the "surfacesToIgnore" variable.
+void CompositeSurface::update_facets_to_ignore()
+{
+   if(facetTool)
+   {
+      int i;
+      int num_surfs_in_composite = num_surfs();
+      for (i=0; i<num_surfs_in_composite; i++)
+      {
+         // Default to "don't ingore".
+         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())
+            {
+               facetTool->set_ignore_flag(i, 1);
+               j=0;
+            }
+         }
+      }
+   }
+}
+
+
+// This function tells the composite to ignore one of its
+// surfaces during evaluation.
+void CompositeSurface::ignore_surface(int surface_id)
+{
+   update_facet_tool();
+   if(facetTool)
+   {
+      int i;
+      int num_surfs_in_composite = num_surfs();
+      for (i=0; i<num_surfs_in_composite; i++)
+      {
+         Surface *cur_surf = get_surface(i);
+         if(cur_surf->get_saved_id() == surface_id)
+         {
+            break;
+         }
+      }
+      if(i < num_surfs_in_composite)
+      {
+         surfacesToIgnore.append_unique(surface_id);
+         update_facets_to_ignore();
+      }
+   }
+}
+
+// This function tells the composite to unset the ignore
+// flag for one of its surfaces.
+void CompositeSurface::unignore_surface(int surface_id)
+{
+   update_facet_tool();
+   if(facetTool)
+   {
+      int i;
+      int num_surfs_in_composite = num_surfs();
+      for (i=0; i<num_surfs_in_composite; i++)
+      {
+         Surface *cur_surf = get_surface(i);
+         if(cur_surf->get_saved_id() == surface_id)
+         {
+            break;
+         }
+      }
+      if(i < num_surfs_in_composite)
+      {
+         surfacesToIgnore.remove(surface_id);
+         update_facets_to_ignore();
+      }
+   }
+}
+
+vo