cgma
OCCModifyEngine.cpp
Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 //-------------------------------------------------------------------------
00003 
00004 // Filename      : OCCModifyEngine.cpp
00005 //
00006 // Purpose       : ModifyEngine for OCC geometry
00007 //
00008 // Special Notes : Modeled after GeometryModifyEngine
00009 //
00010 // Author        : Jane Hu
00011 //
00012 // Creation Date : 1/08
00013 //
00014 //-------------------------------------------------------------------------
00015 #include "gp_Pnt.hxx"
00016 #include "gp_Ax2.hxx"
00017 #include "gp_Dir.hxx"
00018 #include "gp_Hypr.hxx"
00019 #include "gp_Parab.hxx"
00020 #include "gp_Elips.hxx"
00021 #include "gp_Pln.hxx"
00022 #include "gp_Circ.hxx"
00023 #include "gp_Cylinder.hxx"
00024 #include "gp_Cone.hxx"
00025 #include "gp_Sphere.hxx"
00026 #include "gp_Torus.hxx"
00027 #include "BRepOffsetAPI_MakeOffset.hxx"
00028 #include "BRepBuilderAPI_MakeShell.hxx"
00029 #include "BRepBuilderAPI_MakeSolid.hxx"
00030 #include "BRepOffsetAPI_MakeDraft.hxx"
00031 #include "BRepBuilderAPI_TransitionMode.hxx"
00032 #include "BRepBuilderAPI_MakeWire.hxx"
00033 #include "BRepPrimAPI_MakeHalfSpace.hxx"
00034 #include "BRepBuilderAPI_MakePolygon.hxx"
00035 #include "BRepBuilderAPI_Sewing.hxx"
00036 #include "BRepBndLib.hxx"
00037 #include "IntersectionTool.hpp"
00038 #include "TopoDS_Shape.hxx"
00039 #include "TopoDS_Compound.hxx"
00040 #include "TopAbs_Orientation.hxx"
00041 #include "TopOpeBRep_Point2d.hxx"
00042 #include "TColgp_Array1OfPnt.hxx"
00043 #include "TColgp_HArray1OfPnt.hxx"
00044 #include "TColStd_HArray1OfBoolean.hxx"
00045 #include "TColgp_Array1OfVec.hxx"
00046 #include "TColStd_Array1OfReal.hxx"
00047 #include "TColStd_Array1OfInteger.hxx"
00048 #include "GC_MakeArcOfCircle.hxx"
00049 #include "GC_MakeCircle.hxx"
00050 #include "Geom_Circle.hxx"
00051 #include "Geom_SurfaceOfLinearExtrusion.hxx"
00052 #include "Geom_RectangularTrimmedSurface.hxx"
00053 #include "Geom_BSplineCurve.hxx"
00054 #include "Handle_Geom_RectangularTrimmedSurface.hxx"
00055 #include "GC_MakeArcOfHyperbola.hxx"
00056 #include "GC_MakeArcOfParabola.hxx"
00057 #include "GC_MakeArcOfEllipse.hxx"
00058 #include "GC_MakeSegment.hxx"
00059 #include "GC_MakeTrimmedCone.hxx"
00060 #include "GC_MakeTrimmedCylinder.hxx"
00061 #include "gce_MakeElips.hxx"
00062 #include "BRepFilletAPI_MakeFillet.hxx"
00063 #include "BRepFilletAPI_MakeChamfer.hxx"
00064 #include "BRepAdaptor_CompCurve.hxx"
00065 #include "GeomAPI_Interpolate.hxx"
00066 #include "BRepFilletAPI_MakeFillet2d.hxx"
00067 #include "ChFi2d_ConstructionError.hxx"
00068 #include "Geom_BezierCurve.hxx"
00069 #include "BndLib_AddSurface.hxx"
00070 #include "Handle_Geom_Plane.hxx"
00071 #include "Handle_Geom_OffsetCurve.hxx"
00072 #include "Geom_OffsetCurve.hxx"
00073 #include "BRepExtrema_DistShapeShape.hxx"
00074 #include "Extrema_ExtPC.hxx"
00075 #include "BRepPrimAPI_MakePrism.hxx"
00076 #include "BRepSweep_Revol.hxx"
00077 #include "BRepPrimAPI_MakeCone.hxx"
00078 #include "BRepOffsetAPI_ThruSections.hxx"
00079 #include "BRepLib_FuseEdges.hxx"
00080 #include "BRepOffsetAPI_MakePipe.hxx"
00081 #include "BRepPrimAPI_MakeTorus.hxx"
00082 #include "BRepPrimAPI_MakeCylinder.hxx"
00083 #include "BRepBuilderAPI_Transform.hxx"
00084 #include "BRepAdaptor_Curve.hxx"
00085 #include "GC_MakeEllipse.hxx"
00086 #include "BRepBuilderAPI_MakeEdge.hxx"
00087 #include "BRepAdaptor_Surface.hxx"
00088 #include "BRepBuilderAPI_MakeFace.hxx"
00089 #include "ShapeExtend_Status.hxx"
00090 #include "BRepOffsetAPI_MakeThickSolid.hxx"
00091 #include "BRepBuilderAPI_Sewing.hxx"
00092 #include "BRepBuilderAPI_Copy.hxx"
00093 #include "LocOpe_SplitShape.hxx"
00094 #include "BRep_Tool.hxx"
00095 #include "BRep_Builder.hxx"
00096 #include "GProp_GProps.hxx"
00097 #include "BRepGProp.hxx"
00098 #include "TopoDS.hxx"
00099 #include "ShapeFix.hxx"
00100 #include "TopologyBridge.hpp"
00101 #include "ProgressTool.hpp"
00102 #include "BRepAlgoAPI_Fuse.hxx"
00103 #include "BRepAlgoAPI_Cut.hxx"
00104 #include "BRepAlgoAPI_Section.hxx"
00105 #include "BRepAlgoAPI_Common.hxx"
00106 #include "BRepPrimAPI_MakeSphere.hxx"
00107 #include "BRepPrimAPI_MakeBox.hxx"
00108 #include "BRepPrimAPI_MakeWedge.hxx"
00109 #include "BRepTools_WireExplorer.hxx"
00110 #include "Handle_Geom_TrimmedCurve.hxx"
00111 #include "Handle_ShapeBuild_ReShape.hxx"
00112 #include "ShapeBuild_ReShape.hxx"
00113 #include "Handle_Geom_RectangularTrimmedSurface.hxx"
00114 #include "BndLib_Add3dCurve.hxx"
00115 #include "TopOpeBRep_EdgesIntersector.hxx"
00116 #include "TopExp_Explorer.hxx"
00117 #include "TopExp.hxx"
00118 #ifndef OCC_VERSION_MINOR
00119 #include "Standard_Version.hxx"
00120 #endif
00121 
00122 #include "OCCDrawTool.hpp"
00123 #include "OCCModifyEngine.hpp"
00124 #include "OCCQueryEngine.hpp"
00125 #include "CubitMessage.hpp"
00126 #include "CubitDefines.h"
00127 #include "TopTools_DataMapOfShapeInteger.hxx"
00128 #include "BRepFeat_SplitShape.hxx"
00129 #include "TopOpeBRep_ShapeIntersector.hxx"
00130 #include "TopTools_ListIteratorOfListOfShape.hxx"
00131 #include "CubitUtil.hpp"
00132 #include "GeometryQueryTool.hpp"
00133 #include "GeometryModifyTool.hpp"
00134 #include "OCCCoEdge.hpp"
00135 #include "OCCLoop.hpp"
00136 #include "OCCSurface.hpp"
00137 #include "OCCShell.hpp"
00138 #include "OCCLump.hpp"
00139 #include "OCCBody.hpp"
00140 #include "OCCCurve.hpp"
00141 #include "OCCPoint.hpp"
00142 #include "OCCAttribSet.hpp"
00143 #include "CubitFileIOWrapper.hpp"
00144 #include "Body.hpp"
00145 #include "GfxDebug.hpp"
00146 #include "RefFace.hpp"
00147 #include "CpuTimer.hpp"
00148 #include "AppUtil.hpp"
00149 #include "SphereEvaluator.hpp"
00150 #include "CylinderEvaluator.hpp"
00151 #include "GfxPreview.hpp"
00152 #include <vector>
00153 #include "CGMEngineDynamicLoader.hpp"
00154 
00155 CGM_ENGINE_EXPORT_CREATE_GME(OpenCascade)
00156 {
00157   return OCCModifyEngine::instance();
00158 }
00159 
00160 OCCModifyEngine* OCCModifyEngine::instance_ = 0;
00161 typedef std::map<OCCSurface*, std::pair<CubitVector, int> >::value_type valType;
00162 typedef std::map<OCCCurve*, std::pair<CubitVector, int> >::value_type valType2;
00163 #define DEBUG
00164 double TOL = 0.0;
00165 //===============================================================================
00166 // Function   : OCCModifyEngine
00167 // Member Type: PUBLIC
00168 // Description: constructor
00169 // Author     : John Fowler
00170 // Date       : 10/02
00171 //===============================================================================
00172 OCCModifyEngine::OCCModifyEngine()
00173 {
00174 //  assert( !instance_ );
00175 
00176     // add this modify engine to geometrymodifytool
00177   GeometryModifyTool::instance()->add_gme(this);
00178   TOL = OCCQueryEngine::instance()->get_sme_resabs_tolerance();
00179 }
00180 
00181 
00182 //===============================================================================
00183 // Function   : ~OCCModifyEngine
00184 // Member Type: PUBLIC
00185 // Description: destructor
00186 // Author     : John Fowler
00187 // Date       : 10/02
00188 //===============================================================================
00189 OCCModifyEngine::~OCCModifyEngine() 
00190 {
00191         instance_ = 0;
00192 }
00193 
00194 //===============================================================================
00195 // Function   : make_Point
00196 // Member Type: PUBLIC
00197 // Description: make a geometric entity point
00198 // Author     : Jane Hu 
00199 // Date       : 10/07
00200 //===============================================================================
00201 TBPoint* OCCModifyEngine::make_Point( CubitVector const& point) const
00202 {
00203   gp_Pnt pt = gp_Pnt( point.x(), point.y(), point.z());
00204   TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt);
00205 
00206   // Create a new Point object
00207   return OCCQueryEngine::instance()->populate_topology_bridge( theVertex, true );
00208 }
00209 
00210 //===============================================================================
00211 // Function   : make_Curve
00212 //              This function creates a curve given an existing curve, copy. 
00213 // Member Type: PUBLIC
00214 // Description: make a curve
00215 // Author     : Jane Hu
00216 // Date       : 01/08
00217 //===============================================================================
00218 Curve* OCCModifyEngine::make_Curve(Curve * curve_ptr, std::map<TopologyBridge*, TopologyBridge*> * /*old_tb_to_new_tb*/) const
00219 {
00220   OCCCurve* occ_curve = CAST_TO(curve_ptr, OCCCurve);
00221   if (!occ_curve)
00222   {
00223      PRINT_ERROR("Cannot create an OCC curve from the given curve.\n"
00224                  "Possible incompatible geometry engines.\n");
00225      return (Curve *)NULL;
00226   }
00227  
00228   TopoDS_Edge *theEdge = occ_curve->get_TopoDS_Edge();  
00229  
00230   BRepBuilderAPI_Copy api_copy(*theEdge);
00231 
00232   TopoDS_Shape newShape = api_copy.ModifiedShape(*theEdge);
00233  
00234   TopoDS_Edge newEdge = TopoDS::Edge(newShape);
00235 
00236   OCCQueryEngine::instance()->copy_attributes(*theEdge, newEdge);
00237 
00238   return OCCQueryEngine::instance()->populate_topology_bridge(newEdge, true);
00239 }
00240 
00241 //===============================================================================
00242 // Function   : make_Curve
00243 // Member Type: PUBLIC
00244 // Description: make a curve by projecting a straight line defined by 
00245 //              point1_ptr, and point2_ptr onto face_ptr, third_point
00246 //              is used for curves that could be periodic to dertermine
00247 //              the correct direction.
00248 // Author     : Jane Hu
00249 // Date       : 01/08
00250 //===============================================================================
00251 Curve* OCCModifyEngine::make_Curve( TBPoint const* point1_ptr,
00252                              TBPoint const* point2_ptr,
00253                              Surface* face_ptr,
00254                              const CubitVector * third_point) const
00255 {
00256   assert (point1_ptr != NULL && point2_ptr != NULL);
00257   GeometryType type = STRAIGHT_CURVE_TYPE;
00258   CubitBoolean closed = CUBIT_FALSE;
00259   DLIList<CubitVector*> mid_points;
00260   Curve* curve = NULL;
00261   if (point1_ptr != point2_ptr)
00262     curve = make_Curve(type, point1_ptr, point2_ptr, mid_points);
00263   else //could be a closed shape
00264   {
00265     if(third_point != NULL && face_ptr != NULL) 
00266     {
00267        closed = CUBIT_TRUE;
00268        TBPoint * Pnt = make_Point(*third_point);
00269        curve = make_Curve(type, point1_ptr, Pnt, mid_points);
00270     }
00271     else
00272     {
00273        PRINT_ERROR("Cannot create an OCC curve from the given duplicated points.\n");
00274        return (Curve *)NULL;
00275     }
00276   }
00277 
00278   Curve* new_curve = NULL;
00279   if(face_ptr == NULL)
00280     return curve;
00281  
00282   DLIList<TBPoint*> points;
00283   
00284   new_curve = 
00285     CAST_TO(curve, OCCCurve)->
00286            project_curve(face_ptr, points, closed, third_point);
00287   OCCQueryEngine::instance()->delete_solid_model_entities( curve );
00288   return new_curve;
00289 }
00290 
00291 //===============================================================================
00292 // Function   : make_Curve
00293 // Member Type: PUBLIC
00294 // Description: make a  spline curve by using the points and tangents.
00295 //              size of point list and tangents must be the same.
00296 //              values in the tangent list may be null.
00297 // Author     : Jane Hu
00298 // Date       : 01/11
00299 //===============================================================================
00300 Curve* OCCModifyEngine::make_Curve( DLIList<CubitVector*>& point_list,
00301                              DLIList<CubitVector*>& point_tangents) const
00302 {
00303     if (point_list.size() != point_tangents.size())
00304     {
00305         PRINT_ERROR("    point list and tangent list must have same size\n");
00306         return (Curve *)NULL;
00307     }
00308 
00309     if(point_list.size() < 2)
00310     {
00311         PRINT_ERROR("    Can't create a curve with less than 2 points\n");
00312         return (Curve *)NULL;
00313     }
00314 
00315     int size = point_list.size();
00316     Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1, size);
00317     TColgp_Array1OfVec tangents(1, size);
00318     Handle(TColStd_HArray1OfBoolean) tangentFlags = 
00319                                      new TColStd_HArray1OfBoolean(1,size);
00320     gp_Pnt pt, pt1;
00321     CubitVector *pt_vec, *tangent_vec;
00322     gp_Vec tangent;
00323     for (int i = 1 ; i <= size; i++)
00324     {
00325         pt_vec = point_list.get_and_step();
00326         pt.SetCoord(pt_vec->x(), pt_vec->y(), pt_vec->z()); 
00327         if(i == 1)
00328           pt1 = pt; 
00329         points->SetValue(i, pt);
00330 
00331         tangent_vec = point_tangents.get_and_step();
00332         if (!tangent_vec)
00333         {
00334           tangents.SetValue(i,tangent);
00335           tangentFlags->SetValue(i, CUBIT_FALSE);
00336         }
00337         else 
00338         {
00339           tangent.SetCoord(tangent_vec->x(), tangent_vec->y(),
00340                            tangent_vec->z());
00341           tangents.SetValue(i,tangent);
00342           tangentFlags->SetValue(i, CUBIT_TRUE);
00343         }
00344     }
00345     GeomAPI_Interpolate interpolater(points, CUBIT_FALSE, TOL);
00346     interpolater.Load(tangents, tangentFlags);
00347     interpolater.Perform() ;
00348     Handle(Geom_BSplineCurve) pcurve;
00349     if(interpolater.IsDone())
00350       pcurve = interpolater.Curve();
00351     
00352     else
00353     {
00354       PRINT_ERROR("Can't create a curve using provided points and tangents.\n");
00355       return (Curve *)NULL;
00356     }
00357    
00358     TopoDS_Edge topo_edge = BRepBuilderAPI_MakeEdge(pcurve, pt1, pt);
00359     return OCCQueryEngine::instance()->populate_topology_bridge(topo_edge, true);
00360 }
00361 
00362 //===============================================================================
00363 // Function   : make_Curve
00364 // Member Type: PUBLIC
00365 // Description: make a  spline curve by using the points on surface.
00366 // Author     : Jane Hu
00367 // Date       : 01/08
00368 //===============================================================================
00369 Curve* OCCModifyEngine::make_Curve( GeometryType curve_type,
00370                              TBPoint const* point1_ptr,
00371                              TBPoint const* point2_ptr,
00372                              DLIList<CubitVector*>& vector_list,
00373                              Surface* face_ptr) const
00374 {
00375   assert(point1_ptr != NULL && point2_ptr != NULL);
00376   
00377   if (curve_type != SPLINE_CURVE_TYPE
00378       && curve_type != STRAIGHT_CURVE_TYPE)
00379   {
00380      PRINT_ERROR("Cannot create an OCC curve from the given curve_type.\n"
00381                  "Candidates are SPLINE_CURVE_TYPE and STRAIGHT_CURVE_TYPE.\n");
00382      return (Curve *)NULL;
00383   }
00384 
00385   if (curve_type == STRAIGHT_CURVE_TYPE)
00386     return make_Curve(curve_type, point1_ptr, point2_ptr, NULL);
00387 
00388   OCCPoint* occ_point1 = CAST_TO(const_cast<TBPoint*>(point1_ptr), OCCPoint);
00389   OCCPoint* occ_point2 = CAST_TO(const_cast<TBPoint*>(point2_ptr), OCCPoint);
00390 
00391   if (occ_point1 == NULL || occ_point2 == NULL)
00392   {
00393      PRINT_ERROR("Cannot create an OCC curve from the given points.\n"
00394                  "Possible incompatible geometry engines.\n");
00395      return (Curve *)NULL;
00396   }
00397     
00398   //project all points on the surface if possible
00399   OCCSurface* occ_face = NULL;
00400   if (face_ptr != NULL)
00401      occ_face = CAST_TO(face_ptr, OCCSurface);
00402  
00403   gp_Pnt pt;
00404   int size = vector_list.size();
00405   Handle(TColgp_HArray1OfPnt) points = new TColgp_HArray1OfPnt(1, size);
00406   CubitVector vector;
00407   CubitVector closest_location;
00408   for(int i = 1; i <= size; i++)
00409   {
00410      vector = *vector_list.get_and_step();
00411      pt.SetCoord(vector.x(), vector.y(), vector.z());
00412 
00413      if (occ_face != NULL)
00414      {
00415        occ_face->closest_point(vector, &closest_location);
00416        pt.SetCoord(closest_location.x(), closest_location.y(), closest_location.z()) ;       
00417      }
00418 
00419      points->SetValue(i, pt);
00420   }    
00421      
00422   //make curve according to the curve type.
00423   if(curve_type == SPLINE_CURVE_TYPE)
00424   {
00425     if (size < 3)
00426     {
00427       PRINT_ERROR(" Must have at least 3 points to make a spline. \n");
00428       return (Curve*) NULL;
00429     }
00430   
00431     GeomAPI_Interpolate spline(points, CUBIT_FALSE, TOL);
00432     spline.Perform();
00433     if(spline.IsDone())
00434     {
00435       Handle_Geom_BSplineCurve curve = spline.Curve();
00436       TopoDS_Vertex * vt1 = occ_point1->get_TopoDS_Vertex();
00437       TopoDS_Vertex * vt2 = occ_point2->get_TopoDS_Vertex(); 
00438       TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve, *vt1, *vt2);
00439       return OCCQueryEngine::instance()->populate_topology_bridge(new_edge, true); 
00440     }
00441   }
00442 
00443   return (Curve*) NULL;
00444 }
00445 
00446 //===============================================================================
00447 // Function   : make_Curve
00448 // Member Type: PUBLIC
00449 // Description: make a curve
00450 // For STRAIGHT_CURVE_TYPE:
00451 //    intermediate_point_ptr  is not used
00452 //
00453 // For PARABOLA_CURVE_TYPE
00454 //    intermediate_point_ptr is the tip of the parabola
00455 //
00456 // For HYPERBOLA_CURVE_TYPE
00457 //    intermediate_point_ptr is the center of its two foci
00458 //
00459 // For ELLIPSE_CURVE_TYPE
00460 //    intermediate_point_ptr is the center of the ellipse
00461 //    the two points are vertices, one gives the major radius, 
00462 //    the other point gives the minor radius.
00463 //
00464 // For ARC_CURVE_TYPE
00465 //    arc passes three points
00466 //
00467 // Author     : Jane Hu 
00468 // Date       : 01/08
00469 //===============================================================================
00470 Curve* OCCModifyEngine::make_Curve( GeometryType curve_type,
00471                              TBPoint const* point1_ptr,
00472                              TBPoint const* point2_ptr,
00473                              CubitVector const* intermediate_point_ptr) const
00474 {
00475   assert (point1_ptr != NULL && point2_ptr != NULL);
00476   DLIList<CubitVector*> mid_points;
00477   if (intermediate_point_ptr)
00478   {
00479     CubitVector mid_point = *intermediate_point_ptr;
00480     mid_points.append(&mid_point);
00481   }
00482 
00483   CubitVector v1(point1_ptr->coordinates());
00484   CubitVector v2(point2_ptr->coordinates());
00485 
00486   gp_Pnt pt1(v1.x(),v1.y(), v1.z());
00487   gp_Pnt pt2(v2.x(),v2.y(), v2.z());
00488 
00489   CubitVector v3;
00490   gp_Pnt pt3;
00491 
00492   Handle(Geom_TrimmedCurve) curve_ptr;
00493   if(intermediate_point_ptr != NULL)
00494   {
00495     v3 = *intermediate_point_ptr;
00496     pt3.SetCoord(v3.x(),v3.y(), v3.z());
00497   }
00498 
00499   if (curve_type == STRAIGHT_CURVE_TYPE)
00500   {
00501      //make sure the two points are not coincident
00502      if(v1.about_equal(v2))
00503      {
00504         PRINT_ERROR("Can't create a line from two identical points.\n");
00505         return (Curve *)NULL;
00506      }
00507      curve_ptr = GC_MakeSegment(pt1,pt2);
00508   }
00509 
00510   else if (curve_type == ARC_CURVE_TYPE)
00511   {
00512      assert(intermediate_point_ptr != NULL);
00513      curve_ptr = GC_MakeArcOfCircle(pt1, pt3, pt2);
00514   }
00515 
00516   else if (curve_type == ELLIPSE_CURVE_TYPE)
00517   {
00518      assert(intermediate_point_ptr != NULL);
00519      
00520      gp_Pnt center(v3.x(), v3.y(), v3.z());
00521 
00522      gp_Elips ellipse;
00523      gce_MakeElips ellipse1(pt1 , pt2   , center);
00524      if(ellipse1.IsDone())
00525        ellipse = ellipse1.Value();
00526      else if(!ellipse1.IsDone() && ellipse1.Status() == gce_InvertAxis)
00527      {
00528         gce_MakeElips ellipse2(pt2, pt1, center);
00529         if(ellipse2.IsDone())
00530           ellipse = ellipse2.Value();
00531         else
00532         {
00533           PRINT_ERROR("Can't create an ellipse from give 3 points.\n");
00534           return (Curve *)NULL;
00535         }      
00536      } 
00537      else
00538      {
00539         PRINT_ERROR("Can't create an ellipse from give 3 points.\n");
00540         return (Curve *)NULL;
00541      }
00542      curve_ptr = GC_MakeArcOfEllipse(ellipse, pt1, pt2, CUBIT_TRUE);
00543   }
00544 
00545   else if(curve_type == PARABOLA_CURVE_TYPE || 
00546           curve_type == HYPERBOLA_CURVE_TYPE)
00547   {
00548     assert(intermediate_point_ptr != NULL);
00549 
00550     //find the directrix and focus of the parabola
00551     //or the axis, major radius and minor radius of the hyperbola
00552     CubitVector width_vec = v2 - v1;
00553     if(width_vec.length_squared() < TOL * TOL)
00554     {
00555        PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n"
00556                  "2 end points are the same.\n");
00557        return (Curve *)NULL;
00558     }
00559 
00560     CubitVector midpoint_vec = (v1 + v2)/2.0;
00561     CubitVector height_vec = midpoint_vec - v3;
00562     gp_Pnt center(v3.x(), v3.y(), v3.z());
00563  
00564     if (height_vec.length_squared() < TOL * TOL)
00565     { 
00566        PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n"
00567                  "3 points are in the same line.\n");
00568        return (Curve *)NULL;
00569     }
00570     CubitVector x = height_vec;
00571     x.normalize();
00572     gp_Dir x_dir(x.x(), x.y(), x.z());
00573  
00574     CubitVector N = x * (v2 - v1);  
00575     if (N.length_squared() < TOL * TOL)
00576     {
00577        PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n"
00578                  "3 points are in the same line.\n");
00579        return (Curve *)NULL;
00580     }
00581     N.normalize();
00582     gp_Dir N_dir(N.x(), N.y(), N.z());
00583 
00584     gp_Ax2 axis(center, N_dir, x_dir);  
00585 
00586     if(curve_type == HYPERBOLA_CURVE_TYPE)
00587     { 
00588        //    (focus2) (v3) . (v2)
00589        //          .   .   . (midpoint = focus1)
00590        //                  . (v1)
00591        CubitVector focus2 = 2 * v3 - midpoint_vec;
00592 
00593        //according to the definition of hyperbola,
00594        //2 * a = length(v2 - focus2)-length(v2 - focus1)
00595 
00596        double major = (v2 - focus2).length()/2.0 - (v2 - midpoint_vec).length()/2.0;
00597 
00598        // if a = 1/2 length major axis, b = 1/2 length minor axis and
00599        // c = distance center to focus, then a*a + b*b = c*c
00600 
00601        double c_squared = (midpoint_vec - v3).length_squared();
00602        double minor = sqrt(c_squared  - major*major );
00603        gp_Hypr hypt(axis, major, minor);
00604        curve_ptr =
00605              GC_MakeArcOfHyperbola(hypt, pt1, pt2, CUBIT_TRUE);
00606     }
00607 
00608     else
00609     {
00610        // Find the focus of this parabola.
00611        // Since for a parabola with its peak at the origin, y = (1/(4*a))*x^2,
00612        // and since we have restricted this parabola to be symmetric (per the 
00613        // FastQ method, see the FastQ file getwt.f), we can use the following 
00614        // relationship to
00615        // determine "a", the distance the focus lies from the peak on the line
00616        // formed by the peak and the midpoint of the start and end points`
00617        double a = width_vec.length_squared()/(16. * height_vec.length()); 
00618        gp_Parab parab(axis, a);
00619        curve_ptr =
00620         GC_MakeArcOfParabola(parab, pt1, pt2, CUBIT_TRUE);
00621     } 
00622   }
00623 
00624   else
00625   {
00626       PRINT_ERROR("In OCCModifyEngine::make_Curve\n"
00627                   "       Invalid curve type.\n");
00628       return (Curve *)NULL;
00629   }
00630 
00631   OCCPoint* occ_pt1 = CAST_TO(const_cast<TBPoint*>(point1_ptr),OCCPoint);
00632   OCCPoint* occ_pt2 = CAST_TO(const_cast<TBPoint*>(point2_ptr),OCCPoint);
00633   TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex();
00634   TopoDS_Vertex * vt2 = occ_pt2->get_TopoDS_Vertex();
00635   TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt2);
00636   return OCCQueryEngine::instance()->populate_topology_bridge(new_edge, true);
00637 }
00638 
00639 Surface* OCCModifyEngine::make_Surface( Surface *surface_ptr,
00640     std::map< TopologyBridge*, TopologyBridge* > * /*old_tb_to_new_tb*/) const
00641 {
00642   // Set extended_from argument to CUBIT_FALSE by default
00643   return make_Surface(surface_ptr, CUBIT_FALSE);
00644 }
00645 
00646 //===============================================================================
00647 // Function   : make_Surface
00648 //              This function creates a surface given an existing surface, copy.
00649 // Member Type: PRIVATE
00650 // Description: make a surface, OCC allows to create a stand along surface,
00651 //              however the CGM has a design of making all surfaces in a (sheet)
00652 //              body. This will add complexity on all free surface related 
00653 //              calculation and modification, and adding potential bugs too. 
00654 // Author     : Jane Hu
00655 // Date       : 02/08
00656 //===============================================================================
00657 Surface* OCCModifyEngine::make_Surface( Surface * surface_ptr,
00658                                  CubitBoolean extended_from) const
00659 {
00660   OCCSurface* occ_surface = CAST_TO(surface_ptr, OCCSurface);
00661   if (!occ_surface)
00662   {
00663      PRINT_ERROR("Cannot create an OCC surface from the given surface.\n"
00664                  "Possible incompatible geometry engines.\n");
00665      return (Surface *)NULL;
00666   }
00667 
00668   //Start of the codes
00669   double UMax, VMax, UMin, VMin;
00670   occ_surface->get_param_range_U(UMin, UMax);
00671   occ_surface->get_param_range_V(VMin, VMax);
00672 
00673   TopoDS_Face *theFace = occ_surface->get_TopoDS_Face();
00674 
00675   if( !theFace)
00676   {
00677      PRINT_ERROR("Cannot create an OCC surface from the given surface.\n"
00678                  "Possible incompatible geometry engines.\n");
00679      return (Surface *)NULL;
00680   }
00681 
00682   TopoDS_Face newFace;
00683   BRepAdaptor_Surface asurface(*theFace);
00684 
00685   CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box();
00686   double const height = 2*(bounding_box.diagonal()).length();
00687   CubitBox box = occ_surface->bounding_box();
00688   double ratio = height/(box.diagonal().length());
00689 
00690   double middleU = (UMin + UMax)/2.0;
00691   double middleV = (VMin + VMax)/2.0;
00692   double U1 = middleU - (UMax-UMin)/2.0 * ratio;
00693   double U2 = middleU + (UMax-UMin)/2.0 * ratio;
00694   double V1 = middleV - (VMax - VMin)/2.0 * ratio;
00695   double V2 = middleV + (VMax - VMin)/2.0 * ratio;
00696 
00697   if (extended_from == CUBIT_TRUE)
00698   {
00699      // We need to get the type of surface.
00700      GeometryType type = occ_surface->geometry_type();
00701      if (type  == PLANE_SURFACE_TYPE)
00702      {
00703         gp_Pln plane = asurface.Plane();
00704         newFace = BRepBuilderAPI_MakeFace(plane, U1, U2, V1, V2);
00705      }
00706      else if(type == CONE_SURFACE_TYPE)
00707      {
00708        //make an infinite cone.
00709        //Given this lets create another face that is extended from it.
00710        if(asurface.GetType() == GeomAbs_Cone)
00711        {
00712          gp_Cone cone = asurface.Cone();
00713 #if OCC_VERSION_MINOR > 5 
00714         newFace = BRepBuilderAPI_MakeFace(cone, U1, U2, V1, V2);
00715 #else
00716          gp_Pnt Apex = cone.Apex();
00717          double semi_angle = cone.SemiAngle();
00718          gp_Pnt p2;
00719          double radius2;
00720          gp_XYZ xyz;
00721          if (semi_angle > 0)
00722            xyz = Apex.XYZ() + cone.Position().Direction().XYZ()*height;
00723          else
00724            xyz = Apex.XYZ() - cone.Position().Direction().XYZ()*height;
00725 
00726          p2.SetXYZ(xyz);
00727          radius2 = height * tan(fabs(semi_angle));
00728          Handle(Geom_RectangularTrimmedSurface) trimmed_cone;
00729          trimmed_cone = GC_MakeTrimmedCone(Apex, p2, 0, radius2); 
00730   #if OCC_VERSION_MAINTENANCE < 2 
00731          newFace = BRepBuilderAPI_MakeFace(trimmed_cone);
00732   #else
00733          newFace = BRepBuilderAPI_MakeFace(trimmed_cone, TOL);
00734   #endif
00735 #endif
00736        }
00737        else
00738        {
00739          gp_Cylinder cylinder = asurface.Cylinder();
00740 #if OCC_VERSION_MINOR > 5
00741          newFace = BRepBuilderAPI_MakeFace(cylinder, U1, U2, V1, V2);
00742 #else
00743          double radius = cylinder.Radius();
00744          gp_Ax1 axis = cylinder.Axis(); 
00745          Handle(Geom_RectangularTrimmedSurface) trimmed_cyl;
00746          trimmed_cyl = GC_MakeTrimmedCylinder(axis, radius, height);
00747   #if OCC_VERSION_MAINTENANCE < 2 
00748          newFace = BRepBuilderAPI_MakeFace(trimmed_cyl);
00749   #else
00750          newFace = BRepBuilderAPI_MakeFace(trimmed_cyl, TOL);
00751   #endif
00752 #endif
00753        } 
00754      }
00755      else if(type == SPHERE_SURFACE_TYPE)
00756      {
00757        //make a whole sphere.
00758        gp_Sphere sphere = asurface.Sphere();
00759        newFace = BRepBuilderAPI_MakeFace(sphere);
00760      }
00761      else if(type == TORUS_SURFACE_TYPE)
00762      {
00763        //make a whole torus
00764        gp_Torus torus = asurface.Torus();
00765        newFace = BRepBuilderAPI_MakeFace(torus);
00766      }
00767      else if(type == SPLINE_SURFACE_TYPE ) 
00768      {
00769        //extend the surfaces using the equation if possible.
00770        Handle(Geom_BezierSurface) bezier = asurface.Bezier();
00771        Handle(Geom_Surface) p_surf = bezier;
00772 #if OCC_VERSION_MINOR > 5
00773        newFace = BRepBuilderAPI_MakeFace(p_surf, U1, U2, V1, V2, TOL);
00774 #else
00775   #if  OCC_VERSION_MAINTENANCE < 2                           
00776        newFace = BRepBuilderAPI_MakeFace(p_surf, U1, U2, V1, V2);
00777   #else
00778        newFace = BRepBuilderAPI_MakeFace(p_surf, U1, U2, V1, V2, TOL);
00779   #endif
00780 #endif
00781      }
00782   }
00783  
00784   else
00785   {
00786     BRepBuilderAPI_Copy api_copy(*theFace);
00787     TopoDS_Shape newShape = api_copy.ModifiedShape(*theFace);
00788     newFace = TopoDS::Face(newShape);
00789   }
00790   
00791   Surface *surface = OCCQueryEngine::instance()->populate_topology_bridge(
00792                                newFace, CUBIT_TRUE);
00793 
00794   return surface;
00795 }
00796 
00797 //===============================================================================
00798 // Function   : make_Surface
00799 // Member Type: PUBLIC
00800 // Description: make a surface of type surface_type, given the list of curves.
00801 //              check edges option is done in GeometryModifyTool level, so 
00802 //              disregard this option.
00803 // Author     : Jane Hu
00804 // Date       : 02/08
00805 //===============================================================================
00806 Surface* OCCModifyEngine::make_Surface( GeometryType surface_type,
00807                                  DLIList<Curve*>& curve_list,
00808                                  Surface * old_surface_ptr,
00809                                  bool check_edges) const
00810 {
00811   //Create TopoDS_Edge list to make a surface.
00812   DLIList<DLIList<TopoDS_Edge*>*> topo_edges_loops;
00813   curve_list.reset() ;
00814     
00815   //check no intersections of the TopoDS_Edge's.
00816   //need to check that no intersection in the middle of the curves, not at
00817   //vertices or out of boundary.
00818 
00819   int count = 0; //intersection point should be the same as curve_list size.
00820   for ( int i = 0 ; i < curve_list.size()-1 ; i++ )
00821   {
00822      for(int j = i+1; j < curve_list.size(); j ++)
00823      {
00824         DLIList<CubitVector> intscts;
00825     CubitBoolean bounded = CUBIT_TRUE;//dummy arg.
00826     CubitBoolean closest = CUBIT_TRUE;//dummy arg.
00827         CubitStatus yes_int = 
00828               OCCQueryEngine::instance()->get_intersections(curve_list[i],
00829                 curve_list[j], intscts, bounded, closest);
00830         if(yes_int)
00831         {
00832            //check intscts point should be vertex or outside boundary.
00833        if (intscts.size() > 2 )  
00834        {
00835          PRINT_ERROR("In OCCModifyEngine::make_Surface\n"
00836                  "       Cannot make Surface with intersecting curves.\n");
00837              return (Surface *)NULL;
00838            }
00839            else
00840            {
00841              for(int k = 0; k < intscts.size(); k++)
00842              {
00843                CubitVector &v = intscts.get_and_step();
00844            CubitPointContainment is_on = CAST_TO(curve_list[i],OCCCurve)->
00845                     point_containment(v);
00846                if (is_on == CUBIT_PNT_BOUNDARY)
00847                {
00848          is_on = CAST_TO(curve_list[j],OCCCurve)->
00849                 point_containment(v);
00850          if (is_on == CUBIT_PNT_BOUNDARY)
00851                    count++;
00852                }
00853                else if(is_on == CUBIT_PNT_INSIDE)
00854                {
00855                  PRINT_ERROR("In OCCModifyEngine::make_Surface\n"
00856                  "       Cannot make Surface with intersecting curves.\n");
00857                  return (Surface *)NULL;
00858                }
00859          }
00860        }
00861         }
00862      }
00863   }
00864  
00865   if (count > curve_list.size()) 
00866   {
00867       PRINT_ERROR("In OCCModifyEngine::make_Surface\n"
00868                 "       Cannot make Surface with intersecting curves.\n");
00869       return (Surface *)NULL;
00870   }
00871 
00872   CubitStatus stat = sort_curves(curve_list, topo_edges_loops); 
00873   if( stat == CUBIT_FAILURE ) //case of one disconnected curve , open wires
00874   {
00875      //loft curves.
00876      BRepOffsetAPI_ThruSections loft(CUBIT_FALSE);
00877      CubitStatus stat = do_loft(loft, topo_edges_loops);
00878      for (int i = 0; i < topo_edges_loops.size(); i++)
00879      {
00880        DLIList<TopoDS_Edge*>* topo_edges = topo_edges_loops.get_and_step();
00881        for(int j = 0; j < topo_edges->size(); j++)
00882          topo_edges->pop();
00883        delete topo_edges;
00884        topo_edges = NULL;
00885      }
00886      if(!stat)
00887        return (Surface*) NULL;
00888 
00889      TopoDS_Shape shape = loft.Shape();
00890      TopoDS_Shell shell = TopoDS::Shell(shape);
00891      TopExp_Explorer Ex;
00892      int num_surfaces = 0;
00893      TopoDS_Face topo_face ;
00894      for (Ex.Init(shell, TopAbs_FACE); Ex.More(); Ex.Next())
00895      {
00896        topo_face = TopoDS::Face(Ex.Current());
00897        num_surfaces ++;
00898      }
00899 
00900      if(num_surfaces != 1)
00901      {
00902        PRINT_ERROR("In OCCModifyEngine::skin_surface\n"
00903                  "   Cannot create a skin surface for given curves.\n");
00904        return (Surface*) NULL;
00905      }
00906    
00907      Surface* surf = OCCQueryEngine::instance()->populate_topology_bridge(topo_face, CUBIT_TRUE);
00908      if (surf == NULL)
00909      {
00910        PRINT_ERROR("In OCCModifyEngine::skin_surfaces\n"
00911                    "   Cannot create a skin surface for given curves.\n");
00912        return (Surface*) NULL;
00913      }
00914  
00915      return surf;
00916   }
00917 
00918   // Use the topo_edges to make a topo_face
00919   TopoDS_Face* topo_face;
00920   topo_face = make_TopoDS_Face(surface_type,topo_edges_loops, old_surface_ptr);
00921  
00922   for (int i = 0; i < topo_edges_loops.size(); i++)
00923   {
00924     DLIList<TopoDS_Edge*>* topo_edges = topo_edges_loops.get_and_step();
00925     for(int j = 0; j < topo_edges->size(); j++)
00926       topo_edges->pop();
00927     delete topo_edges;
00928     topo_edges = NULL;
00929   }
00930   
00931   if(!topo_face)
00932   {
00933      PRINT_ERROR("In OCCModifyEngine::make_Surface\n"
00934                  "       Cannot make Surface object.\n");
00935      return (Surface *)NULL;
00936   }
00937 
00938   // make the topology bridges for the face
00939   Surface *surface = OCCQueryEngine::instance()->populate_topology_bridge(
00940                                *topo_face, CUBIT_TRUE); 
00941   topo_face->Nullify();
00942   delete topo_face;
00943   topo_face = NULL;
00944 
00945   //Created new surface uses existing OCCPoints on the curves, but created
00946   //new curves, so remove the curves from the curvelist on those points.
00947   if(surface)
00948   {
00949     for(int i = 0; i <  curve_list.size(); i++)
00950     {
00951       OCCCurve* test_c = CAST_TO(curve_list.get_and_step(), OCCCurve);
00952       DLIList<OCCPoint*> points;
00953       CAST_TO(surface, OCCSurface)->get_points(points);
00954       for(int j = 0; j <  points.size(); j ++)
00955         points.get_and_step()->remove_curve(test_c);      
00956     }
00957   }
00958   return surface ;
00959 }
00960 
00961 CubitStatus OCCModifyEngine::do_loft(BRepOffsetAPI_ThruSections& loft,
00962                                      DLIList<DLIList<TopoDS_Edge*>*> loops) const
00963 {
00964    TopoDS_Edge  new_edge;
00965    for(int i = 0; i < loops.size(); i++)
00966    {
00967      BRepBuilderAPI_MakeWire aWire;
00968      DLIList<TopoDS_Edge*> edges = *(loops.get_and_step());
00969 
00970      for(int j = 0; j <  edges.size(); j++)
00971      {
00972        TopoDS_Edge* topo_edge = edges.get_and_step();
00973 
00974        BRepBuilderAPI_Copy api_copy(*topo_edge);
00975        TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_edge);
00976        new_edge = TopoDS::Edge(newShape);
00977        aWire.Add(new_edge);
00978      }
00979      loft.AddWire(aWire.Wire());
00980    }
00981    loft.Build();
00982    if(!loft.IsDone())
00983    {
00984      PRINT_ERROR("Curves can't be loft into a surface.\n");
00985      return CUBIT_FAILURE;
00986    }
00987    return CUBIT_SUCCESS;
00988 } 
00989 
00990 //===============================================================================
00991 // Function   : sort_curves
00992 // Member Type: PROTECTED
00993 // Description: sort the curves so they are in order and make closed loop 
00994 // Author     : Jane Hu
00995 // Date       : 03/08
00996 //===============================================================================
00997 CubitStatus OCCModifyEngine::sort_curves(DLIList<Curve*> curve_list,
00998                         DLIList<DLIList<TopoDS_Edge*>*>& topo_edges_loops)const
00999 {
01000   topo_edges_loops.clean_out();
01001   CubitStatus stat = CUBIT_SUCCESS;
01002   std::vector< DLIList<TopoDS_Edge*>* > topo_edges(curve_list.size());
01003   int size_in = curve_list.size();
01004   for(int i = 0; i < size_in; i++)
01005     topo_edges[i] = new DLIList<TopoDS_Edge*>;
01006 
01007   curve_list.reset() ;
01008   Curve const* curve_ptr = NULL ;
01009   OCCCurve* occ_curve = NULL;
01010   TopoDS_Edge* topo_edge = NULL;
01011 
01012   OCCPoint* start = NULL;
01013   OCCPoint* end = NULL;
01014   DLIList<OCCPoint*> point_list;
01015   CubitBoolean new_end = CUBIT_FALSE;
01016   int size = curve_list.size();
01017 
01018   int count = 0;
01019   for ( int i = 0 ; i < size ; i++ )
01020   {
01021      if (i == 0)
01022        new_end = CUBIT_TRUE;
01023      for(int j = 0; j < curve_list.size(); j ++)
01024      {
01025         curve_ptr = curve_list.get() ; 
01026         occ_curve = CAST_TO(const_cast<Curve*>(curve_ptr), OCCCurve);
01027 
01028         if(occ_curve ==  NULL)
01029         {
01030            PRINT_ERROR("In OCCModifyEngine::sort_curves\n"
01031                        "       Got a NULL pointer to OCCCurve\n") ;
01032            return CUBIT_FAILURE;
01033         }
01034 
01035         point_list.clean_out();
01036         occ_curve->get_points(point_list);
01037         //assert(point_list.size()==2);
01038 
01039         if (i == 0)
01040         {
01041           start = point_list.get();
01042           end = point_list.pop();  
01043           break;
01044         }
01045 
01046         if(end->is_equal(*(point_list.get()), TOL) ||
01047            end->is_equal(*(point_list.step_and_get()),TOL)) 
01048         {
01049            end = point_list.step_and_get();
01050            new_end = CUBIT_TRUE;
01051            break;
01052         }
01053    
01054         else if(start->is_equal(*(point_list.get()), TOL) ||
01055            start->is_equal(*(point_list.step_and_get()),TOL))
01056         {
01057            start = end;
01058            end = point_list.step_and_get(); 
01059            new_end = CUBIT_TRUE;
01060            break;
01061         }
01062         curve_list.step();
01063      }
01064 
01065      if (new_end)//found next curve 
01066      {
01067         topo_edge = occ_curve->get_TopoDS_Edge();
01068         topo_edges[count]->append(topo_edge);
01069         curve_list.remove();
01070         if(start->is_equal( *end, TOL))  //formed a closed loop
01071         {
01072           i = -1;
01073           size = curve_list.size() ;
01074           topo_edges_loops.append(topo_edges[count]);
01075           count++;
01076         }
01077         else
01078           new_end = CUBIT_FALSE;
01079      }
01080      else
01081      {
01082         stat = CUBIT_FAILURE; 
01083         i = -1;
01084         size = curve_list.size();
01085         topo_edges_loops.append(topo_edges[count]);
01086         count++;
01087      }
01088   }
01089 
01090   if( new_end == CUBIT_FALSE ) //case of one disconnected curve
01091   {
01092     topo_edges_loops.append(topo_edges[count]); 
01093     stat = CUBIT_FAILURE;
01094   }
01095 
01096   for(int i = 0; i < size_in; i++)
01097   {
01098      if(topo_edges[i]->size() == 0)
01099      {
01100        delete topo_edges[i];
01101        topo_edges[i] = NULL;
01102      }
01103   }
01104   return stat;
01105 } 
01106 //===============================================================================
01107 // Function   : make_TopoDS_Face
01108 // Member Type: PROTECTED
01109 // Description: make a opoDS_Face of type surface_type, given the list of 
01110 //              TopoDS_Edge. the TopoDS_Edge's should be in order in loops.
01111 //              check edges option is done in GeometryModifyTool level, so
01112 //              disregard this option.
01113 // Author     : Jane Hu
01114 // Date       : 02/08
01115 //===============================================================================
01116 TopoDS_Face* OCCModifyEngine::make_TopoDS_Face(GeometryType surface_type,
01117                   DLIList<DLIList<TopoDS_Edge*>*> topo_edges_list,
01118                   Surface * old_surface_ptr)const
01119 {
01120   TopoDS_Face* topo_face = NULL;
01121   // Make sure a supported type of surface is being requested.
01122   if ( surface_type != PLANE_SURFACE_TYPE  &&
01123        surface_type != BEST_FIT_SURFACE_TYPE)
01124   {
01125       PRINT_WARNING("In OCCGeometryEngine::make_TopoDS_Face\n"
01126                     "       At this time, cannot make a TopoDS_Face that isn't"
01127                     " planar or best fit.\n");
01128       return topo_face;
01129   }
01130  
01131   // Set the TopoDS_Face pointer, if requested.
01132   TopoDS_Face *fit_Face = NULL;
01133   Handle_Geom_Surface S;
01134   if ( old_surface_ptr != NULL )
01135   {
01136       OCCSurface *surf = CAST_TO(old_surface_ptr, OCCSurface );
01137       fit_Face = surf->get_TopoDS_Face();
01138       S = BRep_Tool::Surface(*fit_Face);
01139   }
01140  
01141   // Make a wire from the topo_edges.
01142   // Coincident TopoDS_Vertex will be deleted by OCC.
01143   if(topo_edges_list.size() == 0)
01144       return topo_face;
01145 
01146   DLIList<TopoDS_Wire*> wires;
01147   GProp_GProps myProps;
01148   double max_area  = 0.0;
01149   TopoDS_Wire* out_Wire = NULL;
01150   TopoDS_Wire test_Wire;
01151   DLIList<TopoDS_Edge*>* topo_edges; 
01152   //check and make sure the outer loop is in the first
01153   for(int i = 0; i < topo_edges_list.size() ; i++)
01154   {
01155     topo_edges = topo_edges_list.get_and_step();
01156     BRepBuilderAPI_MakeWire aWire(*(topo_edges->get()));
01157     for(int j = 1; j < topo_edges->size(); j++)
01158       aWire.Add(*(topo_edges->step_and_get()));
01159 
01160     test_Wire = aWire.Wire();
01161     wires.append(&test_Wire);
01162    
01163     if (topo_edges_list.size() == 1)
01164       break;
01165 
01166     BRepBuilderAPI_MakeFace made_face(test_Wire);
01167 
01168     if (!made_face.IsDone())
01169     {
01170        PRINT_ERROR("In OCCModifyEngine::make_TopoDS_Face\n"
01171                    "   Cannot find the best fit surface for given curves.\n");
01172        return topo_face;
01173     }
01174     TopoDS_Face test_face = made_face.Face();
01175     BRepGProp::SurfaceProperties(test_face, myProps); 
01176     double area = myProps.Mass();
01177     out_Wire = max_area > area ? out_Wire : &test_Wire;
01178     max_area = max_area > area ? max_area : area;
01179   } 
01180 
01181   if (out_Wire)
01182   {
01183     wires.remove(out_Wire);
01184     wires.insert_first(out_Wire);
01185   }
01186 
01187   //create the TopoDS_Face
01188   CubitBoolean error = CUBIT_FALSE;
01189 
01190   for(int i = 0; i < topo_edges_list.size() ; i++)
01191   {
01192     TopoDS_Wire *the_wire = wires.get_and_step();
01193     if (i == 0)
01194     {
01195       if( old_surface_ptr != NULL )
01196       {
01197         BRepBuilderAPI_MakeFace made_face(S, *the_wire);
01198         if (!made_face.IsDone())
01199         {
01200           error = CUBIT_TRUE;
01201           break;
01202         }
01203         topo_face = new TopoDS_Face(made_face.Face());
01204       }
01205       else
01206       {
01207         CubitBoolean is_planar = (surface_type == PLANE_SURFACE_TYPE ?
01208                   CUBIT_TRUE : CUBIT_FALSE); 
01209         BRepBuilderAPI_MakeFace made_face(*the_wire, is_planar);
01210         if (!made_face.IsDone())
01211         {
01212           error = CUBIT_TRUE;
01213           break;
01214         }
01215 
01216         topo_face = new TopoDS_Face(made_face.Face());
01217       }
01218     }
01219     else
01220     {
01221       BRepBuilderAPI_MakeFace made_face(*topo_face, *the_wire);
01222       if (!made_face.IsDone())
01223       {
01224         error = CUBIT_TRUE;
01225         break;
01226       }
01227       delete topo_face;
01228       topo_face = new TopoDS_Face(made_face.Face());
01229     }
01230   } 
01231 
01232   if(error)
01233   {
01234     PRINT_ERROR("In OCCModifyEngine::make_TopoDS_Face\n"
01235                  "   Cannot find the best fit surface for given curves.\n");
01236     return (TopoDS_Face*) NULL;
01237   }
01238 
01239   return topo_face;
01240 }
01241 //===============================================================================
01242 // Function   : make_Lump
01243 // Member Type: PUBLIC
01244 // Description: make a lump of one shell
01245 // Author     : Jane Hu
01246 // Date       : 02/08
01247 //===============================================================================
01248 Lump* OCCModifyEngine::make_Lump( DLIList<Surface*>& surface_list ) const
01249 {
01250   if (surface_list.size() < 2) 
01251     return (Lump*) NULL;
01252 
01253   //all surfaces should be stand along surface bodies or shell bodies' surface
01254   DLIList<BodySM*> body_list;
01255   for(int i = 0; i < surface_list.size(); i++)
01256   {
01257     OCCSurface* occ_surface = CAST_TO(surface_list.get_and_step(), OCCSurface);
01258     if (occ_surface == NULL)
01259     {
01260        PRINT_ERROR("Cannot create an OCC lump from the given surfaces.\n"
01261                  "Possible incompatible geometry engines.\n");
01262        return (Lump *)NULL;
01263     }
01264     OCCBody* occ_body = occ_surface->my_body();
01265     if(!occ_body)
01266     {
01267       OCCShell* occ_shell = occ_surface->my_shell();
01268       if(occ_shell)
01269         occ_body = occ_shell->my_body();
01270     }
01271     if(!occ_body)
01272     {
01273       DLIList<OCCBody*> original_bodies;
01274       occ_surface->get_bodies(original_bodies);
01275       if(original_bodies.size() > 1)
01276       {
01277         PRINT_ERROR( "Cannot make lump in non-mainfold solids. \n");
01278         return (Lump*) NULL;
01279       }
01280       else if(original_bodies.size() == 0)
01281       {
01282         PRINT_ERROR( "Interal error: Can't find associated solid. \n");
01283         return (Lump*) NULL;
01284       }
01285       occ_body = original_bodies.get();
01286       assert(occ_body != NULL);
01287     }
01288     DLIList<Lump*> lumps;
01289     DLIList<OCCShell*> shells;
01290     DLIList<OCCSurface*> surfaces;
01291     surfaces = occ_body->my_sheet_surfaces();
01292     shells = occ_body->shells();
01293     lumps = occ_body->lumps();
01294     if(lumps.size() > 0 || shells.size() + surfaces.size() > 1)
01295     {
01296       PRINT_ERROR("Cannot create an OCC lump from the given surfaces.\n"
01297                "The surfaces are not free.\n");
01298       return (Lump *)NULL;
01299     }
01300     body_list.append_unique(occ_body);
01301   }
01302 
01303   TopoDS_Shape aShape;
01304   CubitStatus stat = stitch_surfs(body_list, aShape);
01305   if(!stat)
01306   {
01307     PRINT_ERROR("The surfaces are not all connected, can't make a lump. \n");
01308     return (Lump*)NULL;
01309   }
01310 
01311   TopExp_Explorer Ex, Ex2;
01312   TopoDS_Shell aShell ;
01313   for (Ex.Init(aShape, TopAbs_SHELL, TopAbs_SOLID); Ex.More()&& stat; Ex.Next())
01314     aShell = TopoDS::Shell(Ex.Current());
01315  
01316   //check to make sure the aShell is closed.
01317   int num_edges = 0;
01318   int pairs = 0;
01319   //sometimes there's duplicate TopoDS_Edges in the shell.
01320   DLIList<TopoDS_Edge*> edge_list;
01321   for (Ex.Init(aShell, TopAbs_EDGE); Ex.More()&& stat; Ex.Next())
01322   {
01323     TopoDS_Edge edge1 = TopoDS::Edge(Ex.Current());
01324     TopoDS_Edge* new_edge = new TopoDS_Edge(edge1);
01325     edge_list.append(new_edge);
01326   }
01327 
01328   int size = edge_list.size();
01329   for (int i = 0; i < size; i++)
01330   {
01331     TopoDS_Edge edge1 = *edge_list[i];
01332     int same = 0;
01333     for (int j = i+1; j < edge_list.size(); j++)
01334     {
01335       TopoDS_Edge edge2 = *edge_list[j];
01336       if(edge1.IsEqual(edge2))
01337       {
01338            same ++;
01339            edge_list.remove(&edge1);
01340            i--;
01341            size--;
01342            break;
01343       }
01344     }
01345     if(same > 0)
01346       continue;
01347 
01348     else
01349       num_edges++;
01350   
01351     for (int j = 0; j < size; j++)  
01352     {
01353       TopoDS_Edge edge2 = *edge_list[j];    
01354       if (!edge1.IsEqual(edge2)&& edge1.IsSame(edge2))
01355       {
01356         pairs++;
01357         break;
01358       }
01359     }
01360   }
01361 
01362   for (int k = 0; k < edge_list.size(); k++)
01363   {
01364     TopoDS_Edge* edge = edge_list.get_and_step();
01365     edge->Nullify();
01366     delete edge;
01367     edge = NULL;
01368   }
01369 
01370   if (num_edges == pairs )
01371     aShell.Closed(CUBIT_TRUE);
01372 
01373   else
01374     PRINT_ERROR("Surfaces must make a water-tight shape to make a lump.\n");
01375   
01376   if(aShell.Closed())
01377   {
01378     BRepBuilderAPI_MakeSolid aMakeSolid(aShell);
01379     if (!aMakeSolid.IsDone())
01380     {
01381        PRINT_ERROR("Cannot create an OCC Lump from the given surfaces.\n"
01382                    "OCC internal error.\n");
01383        return (Lump *)NULL;
01384     }
01385 
01386     TopoDS_Solid aSolid = aMakeSolid.Solid();
01387 
01388     return
01389       OCCQueryEngine::instance()->populate_topology_bridge(aSolid, CUBIT_TRUE); 
01390   }
01391 
01392   return (Lump*) NULL;
01393 }
01394 
01395 //===============================================================================
01396 // Function   : make_BodySM
01397 // Member Type: PUBLIC
01398 // Description: make a BodySM from a surface
01399 // Author     : Jane Hu
01400 // Date       : 02/08
01401 //===============================================================================
01402 BodySM* OCCModifyEngine::make_BodySM( Surface *surface ) const
01403 {
01404   OCCSurface* occ_surface = CAST_TO(surface, OCCSurface);
01405   if(!occ_surface)
01406   {
01407      PRINT_ERROR("Cannot create an OCC body from the given surface.\n"
01408                  "Possible incompatible geometry engines.\n");
01409      return (BodySM *)NULL;
01410   }
01411 
01412   OCCBody* occ_body = occ_surface->my_body();
01413   TopoDS_Face* face = occ_surface->get_TopoDS_Face();
01414   TopoDS_Face newFace;
01415   if(!occ_body)
01416   {
01417     DLIList<OCCBody*> original_bodies;
01418     occ_surface->get_bodies(original_bodies);
01419     if(original_bodies.size() > 0)
01420       occ_body = original_bodies.get();
01421   }
01422   if(occ_body)
01423   {
01424      //copy the surface to make a sheet body.
01425      BRepBuilderAPI_Copy api_copy(*face);
01426      TopoDS_Shape newShape = api_copy.ModifiedShape(*face);
01427      newFace = TopoDS::Face(newShape);
01428      face = new TopoDS_Face(newFace);
01429   }
01430 
01431   surface = OCCQueryEngine::instance()->populate_topology_bridge(*face, CUBIT_TRUE);
01432    
01433   return CAST_TO(surface, OCCSurface)->my_body();
01434 }
01435 
01436 
01437 
01438 //===============================================================================
01439 // Function   : make_BodySM
01440 // Member Type: PUBLIC
01441 // Description: make a BodySM given a list of Lumps.
01442 // Author     : Jane Hu
01443 // Date       : 02/08
01444 //===============================================================================
01445 BodySM* OCCModifyEngine::make_BodySM( DLIList<Lump*>& lump_list ) const
01446 {
01447   if (lump_list.size() == 0)
01448     return (BodySM*) NULL;
01449 /*
01450   //Create a compsolid shape, copy all BodySM's solids to create new compbody 
01451   DLIList<BodySM*> bodysm_list;
01452   TopoDS_Compound CS;
01453   BRep_Builder B;
01454   B.MakeCompound(CS);
01455 
01456   //Add every shape to the CompSolid
01457   for(int i = 0; i < lump_list.size(); i++)
01458   {
01459      Lump* lump = lump_list.get_and_step();
01460      OCCLump* occ_lump = CAST_TO(lump, OCCLump);
01461      if(!occ_lump)
01462      {
01463         PRINT_ERROR("Cannot create an OCC BodySM from the given lumps.\n"
01464                     "Possible incompatible geometry engines.\n");
01465         return (BodySM *)NULL;
01466      }
01467      TopoDS_Solid* solid = occ_lump->get_TopoDS_Solid();
01468      BRepBuilderAPI_Copy api_copy(*solid);
01469      TopoDS_Shape newShape = api_copy.ModifiedShape(*solid);
01470      B.Add(CS, newShape);
01471   }
01472 */
01473  
01474   //check if the lumps are already in some bodies, in this case, have to use 
01475   //unite operation to create compound.
01476   for (int i = 0 ; i < lump_list.size(); i++)
01477   {
01478     OCCLump* lump = CAST_TO(lump_list.get_and_step(), OCCLump);
01479     if(lump == NULL)
01480     {
01481       PRINT_ERROR("Incompatible engines.\n");
01482       return (BodySM*) NULL;
01483     }
01484     BodySM* body = lump->get_body();
01485     if(body != NULL)
01486       OCCQueryEngine::instance()->delete_body(body, CUBIT_FALSE);
01487   }
01488   TopoDS_Compound* Co;
01489   DLIList<OCCShell*> shells;
01490   DLIList<OCCSurface*> surfaces;
01491   Co = OCCBody::make_Compound(lump_list, shells, surfaces); 
01492   assert (Co != NULL);
01493   BodySM* bodysm = OCCQueryEngine::instance()->populate_topology_bridge(*Co);
01494   Co->Nullify();
01495   delete Co;
01496   Co = NULL;
01497   return bodysm;
01498 
01499 }
01500 
01501 
01502 //===============================================================================
01503 // Function   : sphere
01504 // Member Type: PUBLIC
01505 // Description: build an OCC sphere
01506 // Author     : Jane Hu
01507 // Date       : 03/08
01508 //===============================================================================
01509 BodySM* OCCModifyEngine::sphere(double radius) const
01510 {
01511   if (radius <= 0)
01512     return (BodySM*) NULL; 
01513 
01514   TopoDS_Solid S = BRepPrimAPI_MakeSphere(radius);
01515   
01516   Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, 
01517                                 CUBIT_TRUE);
01518   if (lump == NULL)
01519     return (BodySM*)NULL;
01520 
01521   return CAST_TO(lump, OCCLump)->get_body();
01522 }
01523 
01524 
01525 //===============================================================================
01526 // Function   : brick
01527 // Member Type: PUBLIC
01528 // Description: build an OCC brick 
01529 // Author     : Jane Hu
01530 // Date       : 03/08
01531 //===============================================================================
01532 BodySM* OCCModifyEngine::brick( double wid, double dep, double hi ) const
01533 {
01534   if (wid <= 0 || dep <=0 || hi <= 0)
01535     return (BodySM*)NULL;
01536   
01537   TopoDS_Solid S = BRepPrimAPI_MakeBox(wid, dep, hi);
01538 
01539   Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S,
01540                                 CUBIT_TRUE);
01541 
01542   if (lump == NULL)
01543     return (BodySM*)NULL;
01544 
01545   BodySM* body = CAST_TO(lump, OCCLump)->get_body();
01546   if(body)
01547     CAST_TO(body,OCCBody)->move(-wid/2.0, -dep/2.0, -hi/2.0);
01548   return body;
01549 }
01550 
01551 
01552 //===============================================================================
01553 // Function   : brick
01554 // Member Type: PUBLIC
01555 // Description: create an OCC brick given center axes and extension
01556 //              extension is equvlent to (wid/2, dep/2, hi/2)
01557 //              center should be given the coordinates in global system
01558 // Author     : Jane Hu
01559 // Date       : 03/08
01560 //===============================================================================
01561 BodySM* OCCModifyEngine::brick( const CubitVector& center, 
01562                                 const CubitVector axes[3],
01563                                 const CubitVector &extension) const
01564 {
01565   gp_Pnt left_point(0,0,0);
01566   gp_Dir main_dir(axes[2].x(), axes[2].y(), axes[2].z());
01567   gp_Dir x_dir(axes[0].x(), axes[0].y(), axes[0].z());
01568   gp_Ax2 Axis(left_point, main_dir, x_dir);
01569   TopoDS_Solid S = BRepPrimAPI_MakeBox( Axis, extension.x()*2, extension.y()*2,
01570                     extension.z()*2);
01571 
01572   Lump* lump =  OCCQueryEngine::instance()->populate_topology_bridge(S,
01573                                 CUBIT_TRUE);
01574   if (lump == NULL)
01575     return (BodySM*)NULL;
01576 
01577   BodySM* body = CAST_TO(lump, OCCLump)->get_body();
01578   if(body)
01579   {
01580     CubitVector center_point;
01581     double volume;
01582     OCCBody* occ_body = CAST_TO(body,OCCBody);
01583     occ_body->mass_properties(center_point, volume); 
01584     CubitVector move_vec = center - center_point;
01585     occ_body->move(move_vec.x(), move_vec.y(), move_vec.z());
01586     return body;
01587   }
01588   return (BodySM*)NULL;
01589 }
01590 
01591 //===============================================================================
01592 // Function   : prism
01593 // Member Type: PUBLIC
01594 // Description: create an OCC prism 
01595 // Author     : Jane Hu  
01596 // Date       : 03/08
01597 //===============================================================================
01598 BodySM* OCCModifyEngine::prism( double height, int sides, double major,
01599                                double minor) const
01600 {
01601   if(major <= 0. || minor <= 0. || (major - minor) <=  -TOL)
01602   {
01603     PRINT_ERROR("Major and minor radii must be greater than zero.\n");
01604     return (BodySM*)NULL;
01605   }
01606 
01607   if (sides == 4)
01608     return brick(2 * major, 2 * minor, height); 
01609 
01610   TopoDS_Wire wire ;
01611     make_base_for_prim_pyramid(major, minor, height, sides, wire);
01612 
01613   TopoDS_Face base = BRepBuilderAPI_MakeFace(wire, Standard_True);
01614   gp_Dir main_dir(0.0, 0.0, 1.0);
01615   gp_Vec norm(main_dir);
01616   norm *= height;
01617   BRepSweep_Prism swept(base, norm);
01618   TopoDS_Shape new_shape = swept.Shape();
01619   DLIList<TopologyBridge*> tbs;
01620   tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
01621   assert(tbs.size() == 1);
01622 
01623   BodySM* bodysm = CAST_TO(tbs.get(), BodySM);
01624   return bodysm;
01625 }
01626 
01627 void OCCModifyEngine::make_base_for_prim_pyramid(double major,
01628                                                  double minor,
01629                                                  double height,
01630                                                  int sides,
01631                                                  TopoDS_Wire& wire)const
01632 {
01633   //One of the polygon side will be perpendicular to positive x-axis.
01634   double y = major * sin(CUBIT_PI/sides);
01635   double x = sqrt(major * major - y * y);
01636   gp_Pnt start(x, y, -height/2.0);
01637 
01638   DLIList<gp_Pnt> point_list;
01639   double theta = 2.0/sides*CUBIT_PI;
01640   for(int n =1 ; n < sides; n++)
01641   {
01642     double angle = theta * (n + 0.5);
01643     gp_Pnt v(major * cos(angle), major * sin(angle), -height/2.0);
01644     point_list.append(v);
01645   }
01646 
01647   TopoDS_Edge new_edge;
01648   BRepBuilderAPI_MakePolygon poly_maker;
01649   gp_Dir main_dir(0.0, 0.0, 1.0);
01650   point_list.append(start);
01651 
01652   if (fabs(major - minor) < TOL)
01653     for (int i = 0; i <sides; i++)
01654       poly_maker.Add(point_list[i]);
01655   else
01656   {
01657     for (int i = 0; i <sides; i++)
01658     {
01659       x = point_list[i].X();
01660       if((y=point_list[i].Y()) > 0.0)
01661         y = sqrt((1-x*x/major/major)*minor*minor);
01662       else
01663         y = -sqrt((1-x*x/major/major)*minor*minor);
01664       point_list[i].SetY(y);
01665       poly_maker.Add(point_list[i]);
01666     }
01667   }
01668   poly_maker.Close();
01669 
01670   wire = poly_maker.Wire();
01671 }
01672 
01673 //===============================================================================
01674 // Function   : pyramid
01675 // Member Type: PUBLIC
01676 // Description: create an OCC pyramid 
01677 // Author     : Jane Hu
01678 // Date       : 03/08
01679 //===============================================================================
01680 BodySM* OCCModifyEngine::pyramid( double height, int sides, double major,
01681                                  double minor, double top) const
01682 {
01683   TopoDS_Solid S;
01684 
01685   //build the top and bottom shapes.
01686   TopoDS_Wire wire_bottom ; 
01687   make_base_for_prim_pyramid(major, minor, height, sides, wire_bottom);
01688   double top_minor = top * minor / major;
01689   TopoDS_Wire wire_top ; 
01690   BRepOffsetAPI_ThruSections builder(CUBIT_TRUE, CUBIT_TRUE);
01691   builder.AddWire(wire_bottom);
01692   if(top > TOL)
01693   {
01694     make_base_for_prim_pyramid(top, top_minor, -height, sides, wire_top); 
01695     builder.AddWire(wire_top);
01696   }
01697   else
01698   {
01699     gp_Pnt pt = gp_Pnt( 0.0, 0.0, height/2.0);
01700     TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt);
01701     builder.AddVertex(theVertex);
01702   }
01703   builder.Build() ;
01704   S = TopoDS::Solid(builder.Shape());
01705  
01706   Lump* lump =  OCCQueryEngine::instance()->populate_topology_bridge(S,
01707                                                                 CUBIT_TRUE);
01708   if (lump == NULL)
01709     return (BodySM*)NULL;
01710 
01711   BodySM* body = CAST_TO(lump, OCCLump)->get_body();
01712   return body;
01713   
01714 }
01715 
01716 //===============================================================================
01717 // Function   : cylinder
01718 // Member Type: PUBLIC
01719 // Description: create an OCC cylinder, its base shape can be ellipse with
01720 //      r1, r2 while r3 = 0; or it can be a cone with r1, 
01721 //      r3 while r2 = 0. 
01722 // Author     : Jane Hu
01723 // Date       : 03/08
01724 //===============================================================================
01725 BodySM* OCCModifyEngine::cylinder( double hi, double r1, double r2, double r3 ) const
01726 {
01727   TopoDS_Solid S;
01728   if(r2 != r1)//elliptical based cylinder
01729   {
01730     gp_Pnt center(0.0, 0.0, 0.0);
01731     gp_Dir main_dir(0.0, 0.0, 1.0);
01732     gp_Dir x_dir(1.0, 0.0, 0.0);
01733     gp_Ax2 Axis(center, main_dir, x_dir); 
01734     if(r1 < r2)
01735     {  
01736       double temp_r = r1;
01737       r1 = r2;
01738       r2 = temp_r;
01739     }
01740     Handle(Geom_Curve) curve_ptr = GC_MakeEllipse(Axis, r1, r2); 
01741     TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr);
01742     BRepBuilderAPI_MakeWire aWire(new_edge);
01743 
01744     TopoDS_Wire test_Wire = aWire.Wire();
01745     
01746     BRepOffsetAPI_ThruSections builder(CUBIT_TRUE, CUBIT_TRUE);
01747     builder.AddWire(test_Wire);
01748     if (r3 == 0)
01749     {
01750       gp_Pnt pt = gp_Pnt( 0.0, 0.0, hi);
01751       TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt);
01752       builder.AddVertex(theVertex);
01753     }
01754     else
01755     {
01756       gp_Pnt center2(0.0, 0.0,hi);
01757       gp_Ax2 Axis2(center2, main_dir, x_dir);
01758       Handle(Geom_Curve) curve_ptr = GC_MakeEllipse(Axis2, r3, r3*r2/r1);
01759       TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr);
01760       BRepBuilderAPI_MakeWire aWire(new_edge);
01761       TopoDS_Wire test_Wire = aWire.Wire();
01762       builder.AddWire(test_Wire);
01763     }
01764     builder.Build() ;
01765     S = TopoDS::Solid(builder.Shape());
01766   }
01767 
01768   else // cone
01769   {
01770     if(r1 == r3) //cylinder
01771       S = BRepPrimAPI_MakeCylinder(r1, hi);
01772     else
01773       S = BRepPrimAPI_MakeCone(r1, r3, hi);
01774   }
01775 
01776   Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S,
01777                                                                 CUBIT_TRUE);
01778 
01779   if (lump == NULL)
01780   {
01781     PRINT_ERROR("In OCCModifyEngine::cylinder\n"
01782                 "   Cannot create a cylinder for given radii.\n");
01783     return (BodySM*)NULL;
01784   }
01785 
01786   BodySM* body = CAST_TO(lump, OCCLump)->get_body();
01787   if(body)
01788     CAST_TO(body, OCCBody)->move(0, 0, -hi/2.0);
01789   return body;
01790 }
01791 
01792 //===============================================================================
01793 // Function   : torus
01794 // Member Type: PUBLIC
01795 // Description: create an OCC torus
01796 // Author     : Jane Hu
01797 // Date       : 03/08
01798 //===============================================================================
01799 BodySM* OCCModifyEngine::torus( double r1, double r2 ) const
01800 {
01801   if (r1 <= 0 || r2 <= 0)
01802     return (BodySM*) NULL;
01803  
01804   TopoDS_Solid S = BRepPrimAPI_MakeTorus(r1, r2);
01805 
01806   Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S,
01807                                                                 CUBIT_TRUE);
01808 
01809   if (lump == NULL)
01810   {
01811     PRINT_ERROR("In OCCModifyEngine::torus\n"
01812                 "   Cannot create a torus for given radii.\n");
01813     return (BodySM*)NULL;
01814   }
01815 
01816   return CAST_TO(lump, OCCLump)->get_body();
01817 }
01818 
01819 //===============================================================================
01820 // Function   : planar_sheet
01821 // Member Type: PUBLIC
01822 // Description: create an OCC planar_sheet with four vectors. 
01823 // Author     : Jane Hu
01824 // Date       : 03/08
01825 //===============================================================================
01826 BodySM* OCCModifyEngine::planar_sheet ( const CubitVector& p1,
01827                                        const CubitVector& p2,
01828                                        const CubitVector& p3,
01829                                        const CubitVector& p4) const
01830 {
01831   TBPoint* point1 = make_Point(p1);
01832   TBPoint* point2 = make_Point(p2);
01833   TBPoint* point3 = make_Point(p3);
01834   TBPoint* point4 = make_Point(p4);
01835   Curve * curve1 = make_Curve( point1, point2);
01836   if (curve1 == NULL)
01837     return (BodySM*) NULL;
01838   Curve * curve2 = make_Curve( point2, point3); 
01839   if (curve2 == NULL)
01840         return (BodySM*) NULL;
01841   Curve * curve3 = make_Curve( point3, point4);
01842   if (curve3 == NULL)
01843         return (BodySM*) NULL;
01844   Curve * curve4 = make_Curve( point4, point1);
01845   if (curve4 == NULL)
01846         return (BodySM*) NULL;
01847   DLIList<Curve*> curves;
01848   curves.append(curve1);
01849   curves.append(curve2);
01850   curves.append(curve3);
01851   curves.append(curve4);
01852   Surface* surface = make_Surface(PLANE_SURFACE_TYPE, curves);
01853   if (surface == NULL)
01854     return (BodySM*) NULL;
01855 
01856   return CAST_TO(surface,OCCSurface)->my_body();
01857 }
01858 
01859 //===============================================================================
01860 // Function   : copy_body
01861 // Member Type: PUBLIC
01862 // Description: copy an OCC-based body
01863 // Author     : Jane Hu
01864 // Date       : 03/08
01865 //===============================================================================
01866 BodySM* OCCModifyEngine::copy_body ( BodySM* bodyPtr, std::map<TopologyBridge*, TopologyBridge*> * /*old_tb_to_new_tb*/ ) const
01867 {
01868   BodySM* new_body = NULL;
01869   OCCBody* occ_body = CAST_TO(bodyPtr, OCCBody);
01870   if (!occ_body)
01871   {
01872      PRINT_ERROR("Cannot create an OCC bodySM from the given bodySM.\n"
01873                  "Possible incompatible geometry engines.\n");
01874      return (BodySM *)NULL;
01875   }
01876 
01877   DLIList<CubitSimpleAttrib> list;
01878   TopoDS_Compound *theCS = occ_body->get_TopoDS_Shape();
01879   
01880   if (theCS == NULL) //single lump or shell or surface body
01881   {
01882     DLIList<OCCShell*> shells = occ_body->shells();
01883     assert(shells.size() < 2);
01884     for(int i = 0 ; i < shells.size(); i++)
01885     {
01886       TopoDS_Shell* shell = shells.get_and_step()->get_TopoDS_Shell();
01887       BRepBuilderAPI_Copy api_copy(*shell);
01888       TopoDS_Shape newShape = api_copy.ModifiedShape(*shell);
01889       TopoDS_Shell newShell = TopoDS::Shell(newShape);
01890       new_body = OCCQueryEngine::instance()->populate_topology_bridge(newShell, CUBIT_TRUE)->my_body();
01891       copy_body_attributes((TopoDS_Shape)(*shell), api_copy);
01892     }
01893  
01894     DLIList<OCCSurface*> surfaces = occ_body->my_sheet_surfaces();
01895     assert(surfaces.size() < 2);
01896     
01897     for(int i = 0 ; !new_body && i < surfaces.size(); i++)
01898     {
01899       OCCSurface *occ_surface = CAST_TO(surfaces.get_and_step(), OCCSurface);
01900       TopoDS_Face *theFace = occ_surface->get_TopoDS_Face();
01901       BRepBuilderAPI_Copy api_copy(*theFace);
01902       TopoDS_Shape newShape = api_copy.ModifiedShape(*theFace);
01903       TopoDS_Face newFace = TopoDS::Face(newShape);
01904       Surface* surface = OCCQueryEngine::instance()->populate_topology_bridge(
01905                            newFace, CUBIT_TRUE );
01906       OCCSurface* occ_surf = CAST_TO(surface, OCCSurface);
01907       new_body = occ_surf->my_body();
01908       copy_body_attributes((TopoDS_Shape)(*theFace) , api_copy);
01909     }
01910 
01911     //single lump body
01912     if (!new_body)
01913     {
01914       Lump *lump = occ_body->lumps().get();
01915       TopoDS_Solid solid = *(CAST_TO(lump, OCCLump)->get_TopoDS_Solid());
01916       BRepBuilderAPI_Copy api_copy(solid);
01917       TopoDS_Shape newShape = api_copy.ModifiedShape(solid);
01918       TopoDS_Solid newSolid = TopoDS::Solid(newShape);
01919       lump = OCCQueryEngine::instance()->populate_topology_bridge(newSolid,
01920                                                         CUBIT_TRUE);
01921 
01922       new_body = CAST_TO(lump, OCCLump)->get_body();
01923       copy_body_attributes((TopoDS_Shape)solid, api_copy);
01924     }
01925   }
01926 
01927   if(!new_body && theCS && !theCS->IsNull() &&
01928      OCCQueryEngine::instance()->OCCMap->IsBound(*theCS))
01929   {
01930     BRepBuilderAPI_Copy api_copy(*theCS);
01931 
01932     TopoDS_Shape newShape = api_copy.ModifiedShape(*theCS);
01933 
01934     TopoDS_Compound newCS = TopoDS::Compound(newShape);
01935 
01936     new_body = OCCQueryEngine::instance()->populate_topology_bridge(newCS);
01937     copy_body_attributes((TopoDS_Shape)(*theCS), api_copy);
01938     OCCAttribSet::get_attributes(newCS, list);
01939     for(int kk = 0; kk < list.size(); kk++)
01940       new_body->append_simple_attribute_virt(list.get_and_step());
01941   }
01942   
01943   return new_body;
01944 }
01945 
01946 BodySM* OCCModifyEngine::create_body( VolumeFacets& volume, 
01947                            std::map<FacetShapes*, GeometryEntity*>& entity_map,
01948                            const FacetPointSet& points, 
01949                            int interp_order) const
01950 {
01951   return (BodySM*) NULL;
01952 }
01953 
01954 CubitStatus OCCModifyEngine::copy_body_attributes(TopoDS_Shape orig_shape,
01955                                            BRepBuilderAPI_Copy& api_copy)const 
01956 {
01957   DLIList<CubitSimpleAttrib> list;
01958   TopTools_IndexedMapOfShape M;
01959   TopExp::MapShapes(orig_shape, TopAbs_SOLID, M);
01960   for(int ii=1; ii<=M.Extent(); ii++)
01961   {
01962     TopoDS_Solid solid = TopoDS::Solid(M(ii));
01963     TopoDS_Solid new_solid = TopoDS::Solid(api_copy.ModifiedShape(solid));
01964     if(!new_solid.IsNull())
01965       OCCQueryEngine::instance()->copy_attributes(solid, new_solid);
01966     list.clean_out();
01967     OCCAttribSet::get_attributes(new_solid,list);
01968     OCCLump *lump = NULL;
01969     int k = OCCQueryEngine::instance()->OCCMap->Find(new_solid);
01970     lump = (OCCLump*) (OCCQueryEngine::instance()->OccToCGM->find(k))->second;         
01971     for(int kk = 0; kk < list.size(); kk++)
01972       lump->append_simple_attribute_virt(list.get_and_step());
01973     
01974     if (list.size() == 0)
01975     {
01976       k = OCCQueryEngine::instance()->OCCMap->Find(solid);
01977       OCCLump *orig_lump = (OCCLump*) (OCCQueryEngine::instance()->OccToCGM->find(k))->second;
01978       OCCBody* body = (OCCBody*)orig_lump->get_body();
01979       if(body)
01980       {
01981         body->get_simple_attribute(list);
01982         for (int kk = 0; kk < list.size(); kk++) 
01983           lump->get_body()->append_simple_attribute_virt(list.get_and_step()); 
01984       }
01985     }
01986   }
01987 
01988   M.Clear();
01989   TopExp::MapShapes(orig_shape, TopAbs_FACE, M);
01990   for(int ii=1; ii<=M.Extent(); ii++)
01991   {
01992     TopoDS_Face face = TopoDS::Face(M(ii));
01993     TopoDS_Face new_face = TopoDS::Face(api_copy.ModifiedShape(face));
01994     if(!new_face.IsNull())
01995       OCCQueryEngine::instance()->copy_attributes(face, new_face);
01996     list.clean_out();
01997     OCCAttribSet::get_attributes(new_face, list);
01998     OCCSurface* surf = NULL;
01999     int k = OCCQueryEngine::instance()->OCCMap->Find(new_face);
02000     surf = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
02001     for(int kk = 0; kk < list.size(); kk++)
02002       surf->append_simple_attribute_virt(list.get_and_step());
02003   
02004     if(list.size() == 0)
02005     {
02006       k = OCCQueryEngine::instance()->OCCMap->Find(orig_shape);
02007       OCCBody* body = NULL;
02008       if(orig_shape.ShapeType() == TopAbs_FACE)
02009       {
02010         OCCSurface *orig_surf = (OCCSurface*) (OCCQueryEngine::instance()->OccToCGM->find(k))->second;
02011         body = orig_surf->my_body();
02012       }
02013       else if(orig_shape.ShapeType() == TopAbs_SHELL)
02014       {
02015         OCCShell* orig_shell = (OCCShell*) (OCCQueryEngine::instance()->OccToCGM->find(k))->second;
02016         body = orig_shell->my_body();
02017       }
02018       //Solid and Compound case has been considered in the above cases.
02019       if(body)
02020       {
02021         body->get_simple_attribute(list);
02022         for (int kk = 0; kk < list.size(); kk++) 
02023           surf->my_body()->append_simple_attribute_virt(list.get_and_step());
02024       }
02025     }
02026   }
02027 
02028   M.Clear();
02029   TopExp::MapShapes(orig_shape, TopAbs_EDGE, M);
02030   for(int ii=1; ii<=M.Extent(); ii++)
02031   {
02032     TopoDS_Edge edge = TopoDS::Edge(M(ii));
02033     TopoDS_Edge new_edge = TopoDS::Edge(api_copy.ModifiedShape(edge));
02034     if(!new_edge.IsNull())
02035       OCCQueryEngine::instance()->copy_attributes(edge, new_edge);
02036     list.clean_out();
02037     OCCAttribSet::get_attributes(new_edge, list);
02038     if(list.size() > 0)
02039     {
02040       int k = OCCQueryEngine::instance()->OCCMap->Find(new_edge);
02041       OCCCurve* curve = (OCCCurve*) (OCCQueryEngine::instance()->OccToCGM->find(k))->second;
02042       for(int kk = 0; kk < list.size(); kk++)
02043         curve->append_simple_attribute_virt(list.get_and_step());
02044     }
02045   }
02046 
02047   M.Clear();
02048   TopExp::MapShapes(orig_shape, TopAbs_VERTEX, M);
02049   for(int ii=1; ii<=M.Extent(); ii++)
02050   {
02051     TopoDS_Vertex vertex = TopoDS::Vertex(M(ii));
02052     TopoDS_Vertex new_vertex = TopoDS::Vertex(api_copy.ModifiedShape(vertex));
02053     if(!new_vertex.IsNull())
02054       OCCQueryEngine::instance()->copy_attributes(vertex, new_vertex);
02055     list.clean_out();
02056     OCCAttribSet::get_attributes(new_vertex, list);
02057     if(list.size() > 0)
02058     {
02059       int k = OCCQueryEngine::instance()->OCCMap->Find(new_vertex);
02060       OCCPoint* point = (OCCPoint*) (OCCQueryEngine::instance()->OccToCGM->find(k))->second;
02061       for(int kk = 0; kk < list.size(); kk++)
02062         point->append_simple_attribute_virt(list.get_and_step());
02063     }
02064   }
02065   return CUBIT_SUCCESS;
02066 }
02067 //===============================================================================
02068 // Function   : stitch
02069 // Member Type: PUBLIC
02070 // Description: stitch all surfs and try to make a shell body.
02071 //              tighten_gaps and tolerance are not used here.
02072 // Author     : Jane Hu
02073 // Date       : 03/08
02074 //===============================================================================
02075 CubitStatus OCCModifyEngine::stitch(
02076                       DLIList<BodySM*>& surf_bodies,
02077                       DLIList<BodySM*> &new_bodies,
02078                       bool tighten_gaps,
02079                       double tolerance) const
02080 {
02081   if (surf_bodies.size()==0)
02082     return CUBIT_SUCCESS;
02083 
02084   if (surf_bodies.size()==1)
02085   {
02086     new_bodies = surf_bodies;
02087     return CUBIT_SUCCESS;
02088   }
02089 
02090   TopoDS_Shape fuse;
02091   CubitStatus stat =  stitch_surfs(surf_bodies, fuse);
02092     
02093   TopExp_Explorer Ex;
02094   DLIList<TopologyBridge*> tbs;
02095   for (Ex.Init(fuse, TopAbs_SHELL, TopAbs_SOLID); Ex.More(); Ex.Next())
02096   {
02097     TopoDS_Shape shape = Ex.Current();
02098     tbs += OCCQueryEngine::instance()->populate_topology_bridge(shape);
02099   }
02100 
02101   if (stat)
02102   {
02103     BodySM* body = CAST_TO(tbs.get(), BodySM);
02104     new_bodies.append(body);
02105   }
02106 
02107   else
02108   {
02109     for(int i= 0; i<tbs.size(); i++)
02110       new_bodies.append(CAST_TO(tbs.get_and_step(), OCCBody));
02111   }
02112 
02113   PRINT_WARNING("Occ engine doesn't consider tighten_gaps and tolerance in stitch operation. \n");
02114   return CUBIT_SUCCESS;
02115 }
02116 
02117 //===============================================================================
02118 // Function   : stitch_surfs
02119 // Member Type: PUBLIC
02120 // Description: stitch all surfs and try to make a TopoDS_Shell .
02121 //              called by stitch into surface body
02122 // Author     : Jane Hu
02123 // Date       : 03/08
02124 //===============================================================================
02125 CubitStatus OCCModifyEngine::stitch_surfs(
02126                       DLIList<BodySM*>& surf_bodies,
02127                       TopoDS_Shape& fuse) const
02128 {
02129   if (surf_bodies.size() < 2)
02130     return CUBIT_SUCCESS;
02131 
02132   DLIList<TopoDS_Shape*> faces_to_stitch;
02133   DLIList<OCCSurface*> original_surfaces;
02134   for (int i = 0; i < surf_bodies.size(); i++)
02135   {
02136      BodySM * tool_body = surf_bodies.get_and_step();
02137      OCCBody* occ_body = CAST_TO(tool_body, OCCBody);
02138      DLIList<OCCSurface*> surfaces = occ_body->my_sheet_surfaces();
02139      DLIList<OCCShell*> shells = occ_body->shells();
02140      DLIList<Lump*> lumps = occ_body->lumps();
02141      if (surfaces.size()+shells.size() != 1 || lumps.size() > 0)
02142      {
02143        PRINT_ERROR("Can't stitch non-sheet bodySM's. \n");
02144        return CUBIT_FAILURE;
02145      }
02146 
02147      original_surfaces += surfaces;
02148      delete occ_body;
02149      OCCQueryEngine::instance()->BodyList->remove(occ_body);
02150      if (surfaces.size() == 1)
02151      {
02152        OCCSurface* surface = surfaces.get();
02153        delete surface->my_shell();
02154        delete surface->my_lump();
02155        surface->set_shell(NULL);
02156        surface->set_lump(NULL);
02157        surface->set_body(NULL);
02158 
02159        TopoDS_Face* topods_face = surface->get_TopoDS_Face();
02160        if (topods_face != NULL)
02161          faces_to_stitch.append(topods_face);
02162      }
02163      else
02164      {
02165        OCCShell* shell = shells.get();
02166        delete shell->my_lump();
02167        shell->set_body(NULL);
02168        shell->set_lump(NULL);
02169 
02170        TopoDS_Shell* topods_shell = shell->get_TopoDS_Shell();
02171        if(topods_shell)
02172           faces_to_stitch.append(topods_shell);
02173      }
02174   }
02175 
02176   faces_to_stitch.reset();
02177 
02178   BRepBuilderAPI_Sewing sew;
02179 
02180   for( int i = faces_to_stitch.size()-1; i >= 0; i --)
02181   {
02182       TopoDS_Shape* face = faces_to_stitch[i];
02183       sew.Add(*face);
02184   }
02185 
02186   sew.Perform();
02187   TopoDS_Shape sewn_shape=sew.SewedShape();
02188 
02189   fuse=sewn_shape;
02190 
02191   TopExp_Explorer Ex;
02192   int count_shell = 0;
02193   for (Ex.Init(fuse, TopAbs_SHELL, TopAbs_SOLID); Ex.More(); Ex.Next())
02194     count_shell++;
02195 
02196   if ( count_shell != 1)
02197   {
02198      PRINT_ERROR("Can't stitch all surfaces into one BodySM's. \n");
02199      return CUBIT_FAILURE;
02200   }
02201 
02202   for( int i = original_surfaces.size()-1; i >= 0; i --)
02203     OCCQueryEngine::instance()->
02204       delete_solid_model_entities( (Surface*)original_surfaces.pop());
02205 
02206   return CUBIT_SUCCESS;
02207 }
02208 
02209 //===============================================================================
02210 // Function   : subtract
02211 // Member Type: PUBLIC
02212 // Description: subtract boolean operation on OCC-based bodies
02213 // Author     : Jane Hu
02214 // Date       : 03/08
02215 //===============================================================================
02216 CubitStatus     OCCModifyEngine::subtract(DLIList<BodySM*> &tool_body_list,
02217                                           DLIList<BodySM*> &from_bodies,
02218                                           DLIList<BodySM*> &new_bodies,
02219                                           bool imprint,
02220                                           bool keep_old) const
02221 {
02222   // copy the bodies in case keep_old is true
02223   DLIList<TopoDS_Shape*> tool_bodies_copy;
02224 
02225   //for subtract function, tool-body has to be solid, 
02226   //otherwise it's just imprint
02227   DLIList<CubitBox*>* tool_boxes = new DLIList<CubitBox*>();
02228   DLIList<CubitBoolean> is_tool_volume;
02229   //keep the tool_body untouched
02230   CubitStatus stat = 
02231     get_shape_list(tool_body_list, tool_bodies_copy, is_tool_volume, CUBIT_TRUE, tool_boxes);
02232 
02233   if(!stat)
02234     return stat;
02235 
02236   stat = do_subtract(from_bodies, tool_bodies_copy, is_tool_volume,
02237                      tool_boxes, new_bodies, keep_old, imprint) ;
02238 
02239   //ok, we're done with all cuts, delete unnecessaries.
02240   CubitBoolean delete_tool_boxes = CUBIT_FALSE;
02241   if(tool_boxes->size() > 0)
02242     delete_tool_boxes = CUBIT_TRUE;
02243   while (tool_boxes->size())
02244     delete tool_boxes->pop();
02245   if(delete_tool_boxes)
02246     delete tool_boxes;
02247   while (tool_bodies_copy.size())
02248     delete tool_bodies_copy.pop();
02249   if(!keep_old) //delete tool_bodies
02250     OCCQueryEngine::instance()->delete_solid_model_entities(tool_body_list);
02251   return stat;
02252 }
02253 
02254 CubitStatus OCCModifyEngine::do_subtract(DLIList<BodySM*> &from_bodies,
02255                                       DLIList<TopoDS_Shape*> &tool_bodies_copy,
02256                                       DLIList<CubitBoolean> &is_tool_volume,
02257                                       DLIList<CubitBox*>* tool_boxes,
02258                                       DLIList<BodySM*> &new_bodies,
02259                                       bool keep_old,
02260                                       bool imprint) const
02261 {
02262   DLIList<TopoDS_Shape*> from_bodies_copy;
02263   DLIList<CubitBoolean> is_volume;
02264   //get the from_bodies underling shapes
02265   CubitStatus stat = get_shape_list(from_bodies, from_bodies_copy, is_volume, keep_old);
02266   if(!stat)
02267   {
02268     for (int i = 0; i < tool_bodies_copy.size(); i++)
02269     {
02270        TopoDS_Shape* shape = tool_bodies_copy.get_and_step();
02271        delete shape;
02272        shape = NULL;
02273     }
02274     tool_bodies_copy.clean_out();
02275     return CUBIT_FAILURE;
02276   } 
02277 
02278   //check that tool_bodies are all solid, shell and surface body can't be used
02279   //for subtracting solids.
02280   if(is_tool_volume.is_in_list(CUBIT_FALSE) && !is_volume.is_in_list(CUBIT_FALSE))
02281   {
02282      PRINT_WARNING("Surfaces or Shells can't be used to cut a solid.\n");
02283      while (tool_bodies_copy.size())
02284        delete tool_bodies_copy.pop();
02285      while (from_bodies_copy.size())
02286        delete from_bodies_copy.pop(); 
02287      return CUBIT_FAILURE;
02288   }
02289 
02290   int fraction_remaining = 100;
02291 
02292   // subtract the tool body from each body in the list
02293 
02294   TopoDS_Shape*  from_shape = from_bodies_copy.get();
02295   DLIList<TopologyBridge*> tbs;
02296   for (int i = 0; i < from_bodies_copy.size(); i++)
02297   {
02298     CubitBoolean from_volume = is_volume.get_and_step();
02299     BodySM* from_body = from_bodies.get();
02300     CubitBox box1 = CAST_TO(from_body, OCCBody)->get_bounding_box();
02301     int count = 0;  //count for not preforming cut
02302     for(int j = 0; j < tool_bodies_copy.size(); j ++)
02303     {
02304       CubitBoolean tool_volume = is_tool_volume.get_and_step();
02305       if(tool_volume == CUBIT_FALSE && from_volume == CUBIT_TRUE)
02306       {
02307         PRINT_WARNING("Surfaces or Shells can't be used to cut a solid.\n");
02308         continue;
02309       }
02310       if (AppUtil::instance()->interrupt())
02311       {
02312          PRINT_ERROR("Subtraction interrupted.  Aborting...\n");
02313          while (tool_bodies_copy.size())
02314             delete tool_bodies_copy.pop();
02315          while (from_bodies_copy.size())
02316             delete from_bodies_copy.pop();
02317          return CUBIT_FAILURE;
02318       }
02319       CubitBox tool_box = *tool_boxes->get_and_step();  
02320       if(!tool_box.overlap(TOL,box1))
02321       {
02322         count++;
02323         continue;
02324       } 
02325       TopoDS_Shape* tool_shape = tool_bodies_copy.get_and_step();
02326 
02327       //bodies overlap, proceed with the subtract
02328       BRepAlgoAPI_Cut cutter(*from_shape, *tool_shape);
02329       TopoDS_Shape cut_shape = cutter.Shape(); 
02330 
02331       //compare to see if the from_shape has gotten cut.
02332       CubitBoolean has_changed = CUBIT_FALSE;
02333       double after_mass = 0.0;
02334       GProp_GProps myProps;
02335       if(is_volume[i])
02336         BRepGProp::VolumeProperties(cut_shape, myProps);
02337 
02338       else
02339         BRepGProp::SurfaceProperties(cut_shape, myProps);
02340       after_mass = myProps.Mass();
02341       if(after_mass > TOL)
02342         check_operation(cut_shape, from_shape, is_volume[i], has_changed,
02343                     &cutter, keep_old);
02344       else
02345       {
02346 /*
02347         if(!keep_old)
02348           OCCQueryEngine::instance()->delete_solid_model_entities(from_body);
02349         from_shape->Nullify();
02350 */
02351         from_shape = NULL;
02352       }
02353 
02354       int stat;
02355       if(!has_changed && from_shape && !from_shape->IsNull())
02356       {
02357         //Add imprint code here 
02358         DLIList<TopoDS_Face*> face_list;
02359         if(imprint)
02360         {
02361           stat = imprint_toposhapes(from_shape, tool_shape, face_list);
02362           if(stat)
02363           {
02364             PRINT_ERROR("Can't do imprint operation on the body. \n");
02365             count++;
02366           }
02367           continue;
02368         }
02369       }
02370     }
02371 
02372     //ok, we're done with all cuts, construct new Body'
02373     if (count < tool_bodies_copy.size() && from_shape && !from_shape->IsNull())
02374       tbs += OCCQueryEngine::instance()->populate_topology_bridge(*from_shape);
02375     else if (from_shape && !from_shape->IsNull())
02376     {
02377       PRINT_INFO("The %d body did not change because cutting tools are not interscting with it.\n", i+1);
02378       from_bodies.change_to(NULL);
02379     }
02380     from_bodies.step();
02381     from_shape = from_bodies_copy.step_and_get();
02382 
02383     // done with this j iteration; write out count, if necessary
02384     if (from_bodies.size() * tool_bodies_copy.size() > 1)
02385     {
02386        int frac_done = (100 * (i+1)) / (from_bodies.size());
02387        if ((100 - frac_done) < fraction_remaining)
02388        {
02389           fraction_remaining = 100 - frac_done;
02390           PRINT_INFO("%d%% remaining.\n ", fraction_remaining+1);
02391        }
02392     }
02393   }
02394 
02395   for (int i = 0; i< tbs.size(); i++)
02396   {
02397     BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM);
02398     if (bodysm)
02399       new_bodies.append(bodysm);
02400   }    
02401 
02402   //ok, we're done with all cuts, delete unnecessaries. 
02403   if(keep_old)
02404   {
02405     int size  = from_bodies_copy.size();
02406     for (int i = 0; i < size; i++)
02407     {
02408       TopoDS_Shape* shape = from_bodies_copy.pop();
02409       if(shape != NULL )
02410       {
02411         shape->Nullify();
02412         //delete shape; - Must not be deleted, causes random failure on OSX
02413         shape = NULL;
02414       }
02415     }
02416   } 
02417   return CUBIT_SUCCESS; 
02418 }
02419 
02420 //===============================================================================
02421 // Function   : imprint_toposhapes
02422 // Member Type: PROTECTED
02423 // Description: imprint boolean operation on OCC-based bodies.
02424 //              from_shape must be TopoDS_Face or above, tool_shape can be
02425 //              TopoDS_Edge or above. 
02426 //              on_faces works only when tool_shape is an Edge, indicates that
02427 //              those edges only imprint on the on_faces.
02428 //              success: return 0
02429 //              needs intersect-subtract-union boolean: return 1
02430 //              fail:     return 2
02431 //              needs face intersect for periodic geometry: return 3 
02432 //              the cutting surface's topoDS_Face in returned in the
02433 //              the last of on_faces list.
02434 // Author     : Jane HU
02435 // Date       : 03/08
02436 //===============================================================================
02437 int OCCModifyEngine::imprint_toposhapes(TopoDS_Shape*& from_shape, 
02438                                         TopoDS_Shape* tool_shape,
02439                                         DLIList<TopoDS_Face*>&on_faces)const
02440 {
02441   int count = 0;   //number of imprinting
02442  
02443   //indicate if there's more faces to be imprinted
02444   CubitBoolean more_face = CUBIT_TRUE; 
02445   CubitBoolean face_created = CUBIT_FALSE;
02446 
02447   //list of face on from_shape that has been imprinted
02448   DLIList<TopoDS_Face*> from_faces; 
02449   while( more_face)
02450     {
02451       TopoDS_Face from_face,tool_face;
02452       TopoDS_Edge* common_edge = NULL;
02453       DLIList<TopoDS_Shape*> tool_faces_edges;
02454       TopTools_ListOfShape list_of_edges;
02455       BRepFeat_SplitShape splitor(*from_shape);
02456       CubitBoolean qualified = CUBIT_TRUE;
02457       if (tool_shape->ShapeType() == TopAbs_EDGE)
02458     {
02459       if(count == 1)
02460         break;
02461       
02462       DLIList<TopoDS_Face*> faces;
02463       //need to delete TopoDS_Face* in faces
02464       common_edge = find_imprinting_edge(*from_shape, TopoDS::Edge(*tool_shape),faces);
02465       if (common_edge)
02466         {
02467           if (on_faces.size() > 0)
02468         qualified = CUBIT_FALSE;
02469           for(int j = 0; j < faces.size(); j++)
02470         {
02471           from_face = *faces.get();
02472           for (int i = 0; i < on_faces.size(); i++)
02473             {
02474               if (from_face.IsSame(*(on_faces.get_and_step())))
02475             {
02476               qualified = CUBIT_TRUE; 
02477               break;
02478             }
02479             }
02480           faces.get()->Nullify();
02481           delete faces.get();
02482           faces.step();
02483         }
02484           if (qualified && (from_faces.size() == 0 || (from_faces.size() && !from_face.IsSame(*from_faces.get()))) )
02485         list_of_edges.Append(*common_edge);
02486           else
02487         from_face.Nullify();
02488           common_edge->Nullify();
02489           delete common_edge;
02490               common_edge = NULL;
02491         }
02492     }
02493       else 
02494     {
02495       TopOpeBRep_ShapeIntersector intersector;
02496       intersector.InitIntersection(*from_shape, *tool_shape);
02497 
02498       //find the intersecting edges and faces.
02499       int max_edge = 0;
02500                      
02501       for(; intersector.MoreIntersection(); )
02502         {
02503           TopoDS_Shape face1;
02504           face1 = intersector.ChangeFacesIntersector().Face(1);
02505           CubitBoolean has_imprinted = CUBIT_FALSE;
02506           for (int j = 0; j < from_faces.size(); j++)
02507         {
02508           TopoDS_Face* topo_face = from_faces.get_and_step();
02509           if(face1.IsSame(*topo_face))
02510             {
02511               has_imprinted = CUBIT_TRUE;
02512               break;
02513             }
02514         }
02515 
02516           if (has_imprinted == CUBIT_TRUE)
02517         {
02518           intersector.NextIntersection();
02519           continue;
02520         }
02521           TopoDS_Shape edge_face;
02522 
02523           edge_face = intersector.ChangeFacesIntersector().Face(2);
02524           BRepAlgoAPI_Section section(face1, edge_face);
02525 
02526           //intersection edges between face1 and edge_face
02527           TopTools_ListOfShape temp_list_of_edges;
02528 #if OCC_VERSION_MINOR > 5
02529               TopoDS_Shape s_shape = section.Shape();
02530               TopExp_Explorer Ex;
02531               for (Ex.Init(s_shape, TopAbs_EDGE, TopAbs_WIRE); Ex.More(); Ex.Next())
02532                 temp_list_of_edges.Append(TopoDS::Edge( Ex.Current())); 
02533 #else
02534               temp_list_of_edges.Assign(section.SectionEdges());
02535 #endif
02536           int num_edges = temp_list_of_edges.Extent();
02537   
02538           CubitBoolean is_same = face1.IsSame(from_face);
02539           CubitBoolean is_same_tool = CUBIT_FALSE;
02540           for (int j = 0; j < tool_faces_edges.size(); j++)
02541         {
02542           TopoDS_Shape* topo_face_edge = tool_faces_edges.get_and_step();
02543           if(edge_face.IsSame(*topo_face_edge))
02544             {
02545               is_same_tool = CUBIT_TRUE;
02546               break;
02547             }
02548         }
02549           if (max_edge < num_edges )
02550         {
02551           list_of_edges.Assign(temp_list_of_edges);  
02552           max_edge =  num_edges ;
02553           from_face = TopoDS::Face(face1);
02554           TopoDS_Shape* topo_shape = new TopoDS_Shape(edge_face);
02555           DLIList<TopoDS_Shape*> shape_list;
02556           for(int iii = 0; iii < tool_faces_edges.size(); iii++)
02557             {
02558               int size = shape_list.size();
02559               shape_list.append_unique(tool_faces_edges.get_and_step());
02560               if (size < shape_list.size())
02561             {
02562               shape_list.last();
02563               shape_list.get()->Nullify();
02564               delete shape_list.get();
02565             }
02566             }
02567           tool_faces_edges.clean_out();
02568           for(int i = 0 ; i < num_edges; i++)
02569             //later has to use it num_edges times 
02570             tool_faces_edges.append(topo_shape);
02571         }
02572           else if(num_edges == max_edge && is_same && !is_same_tool) 
02573         //multi tool faces cut the same face
02574         {
02575           TopTools_ListIteratorOfListOfShape Itor, temp_Itor;
02576           temp_Itor.Initialize(temp_list_of_edges);
02577           for(; temp_Itor.More(); temp_Itor.Next())
02578             {
02579               TopoDS_Edge temp_edge = TopoDS::Edge(temp_Itor.Value());
02580               Itor.Initialize(list_of_edges);
02581               CubitBoolean same_edge = CUBIT_FALSE;
02582               
02583               GProp_GProps myProps1;
02584               BRepGProp::LinearProperties(temp_edge, myProps1);
02585               gp_Pnt center1 = myProps1.CentreOfMass();
02586               for(; Itor.More(); Itor.Next())
02587             {
02588               TopoDS_Edge edge = TopoDS::Edge(Itor.Value());
02589               GProp_GProps myProps2;
02590               BRepGProp::LinearProperties(edge, myProps2);
02591               gp_Pnt center2 = myProps2.CentreOfMass();
02592               if(center1.IsEqual(center2, TOL))
02593                 {
02594                   same_edge = CUBIT_TRUE;
02595                   break;
02596                 }
02597             }
02598               if(!same_edge)
02599             {
02600               list_of_edges.Append(temp_edge);
02601               TopoDS_Shape* topo_shape = new TopoDS_Shape(edge_face);
02602               tool_faces_edges.append(topo_shape);
02603             }
02604             }//end 'for'
02605         }//end  'else if'
02606               intersector.NextIntersection();
02607         } //end 'for'
02608     }//end 'else'
02609       if (from_face.IsNull())
02610     {
02611       more_face = CUBIT_FALSE;
02612       DLIList<TopoDS_Shape*> shape_list;
02613       for(int iii = 0; iii < tool_faces_edges.size(); iii++)
02614         {
02615           int size = shape_list.size();
02616           shape_list.append_unique(tool_faces_edges.get_and_step());
02617           if (size < shape_list.size())
02618         {
02619           shape_list.last();
02620           shape_list.get()->Nullify();
02621           delete shape_list.get();
02622         }
02623         }
02624       tool_faces_edges.clean_out();
02625 
02626       for (int iii=0; iii < from_faces.size(); iii++)
02627         {
02628           TopoDS_Face* topo_face = from_faces.get_and_step();
02629           topo_face->Nullify();
02630           delete topo_face;
02631               topo_face = NULL;
02632         }
02633       continue;
02634     }
02635   
02636       TopTools_ListIteratorOfListOfShape Itor;
02637 
02638       //list_of_edges is the intersection edges on tool_faces_edges 
02639       Itor.Initialize(list_of_edges);
02640       int total_edges = list_of_edges.Extent();
02641       DLIList<Curve*> curve_list;
02642       DLIList<OCCCurve*> occ_curves;
02643       CubitBoolean topo_changed = CUBIT_FALSE;
02644       tool_faces_edges.reset();
02645 
02646       //check to see if the intersection edge is:
02647       //1. on from_face: if not, skip it
02648       //2. overlap with from_edges : if not, add the edge for splitting face
02649       //3. if overlap, is it the same edge:if not add it for splitting edge
02650       // if yes, skip it too
02651 
02652       Surface* face = NULL;
02653       if (OCCQueryEngine::instance()->OCCMap->IsBound(from_face))
02654     {
02655       int i = OCCQueryEngine::instance()->OCCMap->Find(from_face);
02656       face = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(i))->second;
02657     }
02658       if (face == NULL)
02659       {
02660         face_created = CUBIT_TRUE;
02661         face = OCCQueryEngine::instance()->populate_topology_bridge(from_face);
02662       }
02663       OCCSurface* occ_face = CAST_TO(face, OCCSurface);
02664 
02665       GeometryType type = occ_face->geometry_type();
02666       CubitBoolean periodic = occ_face->is_periodic();
02667 
02668       DLIList<Curve*> common_curves;
02669       for(; Itor.More(); Itor.Next())
02670       {
02671         TopoDS_Edge edge = TopoDS::Edge(Itor.Value());
02672 
02673         //copy the edge for imprinting.
02674         BRepBuilderAPI_Copy api_copy(edge);
02675         TopoDS_Shape newShape = api_copy.ModifiedShape(edge);
02676         edge = TopoDS::Edge(newShape);
02677         Curve* curve = NULL;
02678         if(!OCCQueryEngine::instance()->OCCMap->IsBound(edge))
02679         {
02680           curve = OCCQueryEngine::instance()->populate_topology_bridge(edge, true);
02681           DLIList<OCCPoint*> points;
02682           OCCCurve* occ_c = CAST_TO(curve, OCCCurve);
02683           occ_c->get_points(points);
02684           for(int i = 0 ; i <  points.size(); i++)
02685             points.get_and_step()->remove_curve(occ_c);
02686         }
02687         else
02688           curve = OCCQueryEngine::instance()->populate_topology_bridge(edge);
02689         if(curve)
02690           common_curves.append(curve);
02691       }
02692       DLIList<DLIList<TopoDS_Edge*>*> temp_edge_lists;
02693       if (common_curves.size() >= 1)
02694          sort_curves(common_curves, temp_edge_lists);
02695 
02696       if ( common_curves.size() >= 2 && 
02697            (type == CONE_SURFACE_TYPE || type == SPHERE_SURFACE_TYPE ||
02698             type == TORUS_SURFACE_TYPE ||type == UNDEFINED_SURFACE_TYPE ||
02699             type == SPLINE_SURFACE_TYPE))
02700       {
02701         //if the two shapes has common volume, do boolean operations
02702         BRepAlgoAPI_Common intersector(*from_shape, *tool_shape);
02703         TopTools_ListOfShape shapes;
02704         shapes.Assign(intersector.Modified(*tool_shape));
02705      
02706         TopoDS_Shape common_shape;
02707         if (shapes.IsEmpty())
02708           common_shape = intersector.Shape();
02709         else 
02710           common_shape = shapes.First();
02711 
02712         if(!common_shape.IsNull()) 
02713         { 
02714           TopTools_IndexedMapOfShape M;
02715           TopExp::MapShapes(common_shape, TopAbs_SOLID, M);
02716           if(M.Extent() > 0)
02717           {
02718             GProp_GProps myProps;
02719             BRepGProp::VolumeProperties(common_shape, myProps);
02720             double after_mass = myProps.Mass();
02721             BRepGProp::VolumeProperties(*from_shape, myProps);
02722             double orig_mass = myProps.Mass();
02723             if(fabs(-after_mass + orig_mass) > TOL && after_mass > TOL)
02724               return 1; 
02725           }
02726           //have to use boolean operation, see 
02727           //http://www.opencascade.org/org/forum/thread_20672/ for more info
02728         }
02729       }
02730 
02731       list_of_edges.Clear(); 
02732       if (common_curves.size() >= 1)
02733     {
02734       DLIList<TopoDS_Edge*>* edge_list;
02735       int size = temp_edge_lists.size();
02736       for(int i = 0; i < size; i++)
02737         {
02738           edge_list = temp_edge_lists.get_and_step();
02739           //make sure the copied edges are sharing vertices.
02740           BRepBuilderAPI_MakeWire myWire;
02741           edge_list->reset();
02742           for(int j = 0; j < edge_list->size(); j++)
02743         {
02744           TopoDS_Edge e = *(edge_list->get_and_step());
02745                   //Don't include zero length edge.
02746                   GProp_GProps myProps;
02747                   BRepGProp::LinearProperties(e, myProps);
02748                   double d = myProps.Mass();
02749                   if(d > TOL) 
02750             myWire.Add(e);
02751         }
02752           TopoDS_Wire wire = myWire.Wire();
02753           BRepTools_WireExplorer Ex(wire); 
02754           for(; Ex.More(); Ex.Next())
02755         list_of_edges.Append(Ex.Current());
02756               edge_list->clean_out();
02757               delete edge_list;
02758         }
02759     }
02760       for(Itor.Initialize(list_of_edges); Itor.More(); Itor.Next())
02761     {
02762       TopoDS_Edge edge = TopoDS::Edge(Itor.Value());
02763           CubitBoolean added = CUBIT_FALSE;
02764       //check to see if the intersection edge is on from_face
02765       TopExp_Explorer Ex;
02766       CubitBoolean skipped = CUBIT_FALSE;
02767       GProp_GProps myProps1;
02768       BRepGProp::LinearProperties(edge, myProps1);
02769       double d1 = myProps1.Mass();
02770           Curve* curve = NULL;
02771           //edge should all be bounded, it comes from common_curves
02772           if (OCCQueryEngine::instance()->OCCMap->IsBound(edge))
02773           {
02774             int i = OCCQueryEngine::instance()->OCCMap->Find(edge);
02775             curve = (Curve*)
02776                     (OCCQueryEngine::instance()->OccToCGM->find(i))->second;
02777           }
02778           else 
02779           {
02780             curve = OCCQueryEngine::instance()->populate_topology_bridge(edge, true);
02781             DLIList<OCCPoint*> points;
02782             OCCCurve* occ_c = CAST_TO(curve, OCCCurve);
02783             occ_c->get_points(points);
02784             for(int i = 0 ; i <  points.size(); i++)
02785               points.get_and_step()->remove_curve(occ_c);
02786           }
02787       gp_Pnt pt = myProps1.CentreOfMass();
02788       CubitVector p = curve->center_point();
02789 
02790       CubitVector point_on_surf;
02791       occ_face->closest_point_trimmed(p, point_on_surf);
02792 
02793       if(p.distance_between(point_on_surf) > TOL) //edge not on from_face
02794         {
02795           skipped = CUBIT_TRUE;
02796           total_edges--;
02797         }
02798 
02799       else 
02800         {
02801           for (Ex.Init(from_face, TopAbs_EDGE); Ex.More(); Ex.Next())
02802         {
02803           //check if the edge is on from_face edges, add such edge on existing
02804           //edge to split it.
02805           TopoDS_Edge from_edge = TopoDS::Edge(Ex.Current());
02806          
02807           GProp_GProps myProps2;
02808           BRepGProp::LinearProperties(from_edge, myProps2);
02809           double d2 = myProps2.Mass();
02810                   gp_Pnt pt2 = myProps2.CentreOfMass();
02811                   CubitBoolean found_ = CUBIT_FALSE;
02812                   Curve* from_curve;
02813           if (OCCQueryEngine::instance()->OCCMap->IsBound(from_edge))
02814           {
02815                     int i = OCCQueryEngine::instance()->OCCMap->Find(from_edge);
02816             from_curve = (OCCCurve*)
02817                         (OCCQueryEngine::instance()->OccToCGM->find(i))->second;
02818                     found_ = CUBIT_TRUE;
02819           }
02820           else
02821             from_curve = OCCQueryEngine::instance()->populate_topology_bridge(from_edge, true);
02822                   if(!from_curve)
02823                     continue;
02824 
02825           OCCCurve* occ_curve = CAST_TO(from_curve, OCCCurve);
02826 
02827                   if(pt.IsEqual(pt2, TOL) && fabs(d2-d1)< TOL) //overlap
02828                   {
02829                     skipped = CUBIT_TRUE;
02830                     total_edges--;
02831                     break;
02832                   }
02833 
02834           CubitPointContainment pc = CUBIT_PNT_OFF;
02835                   pc = occ_curve->point_containment(p);
02836                   if((d2 - d1) > TOL && pc == CUBIT_PNT_ON) 
02837                   {
02838                     added = CUBIT_TRUE;
02839                     splitor.Add(edge, from_edge);
02840                     total_edges--;
02841                     break;
02842                   }
02843 
02844                   if(!found_ && from_curve)
02845                     OCCQueryEngine::instance()->
02846                       delete_solid_model_entities(from_curve);
02847         } 
02848           if(list_of_edges.Extent() == 1 && !skipped) 
02849         {
02850           added = CUBIT_TRUE;
02851           curve_list.append(curve); 
02852         }
02853         } 
02854       if(added)
02855         {
02856           topo_changed = CUBIT_TRUE;
02857           continue;
02858         }
02859       if (!skipped)
02860         {
02861           //check if edge's inside from_face by checking bounding boxes  
02862           BRepAdaptor_Curve acurve(edge);
02863           BRepAdaptor_Surface asurface( from_face);
02864           Bnd_Box aBox_edge, aBox_face;
02865           BndLib_Add3dCurve::Add(acurve, Precision::Approximation(), aBox_edge);
02866           BndLib_AddSurface::Add(asurface, Precision::Approximation(), aBox_face);
02867           double min[3], max[3];
02868           aBox_edge.Get( min[0], min[1], min[2], max[0], max[1], max[2]);
02869           CubitBox aBox_e(min, max);
02870           aBox_face.Get( min[0], min[1], min[2], max[0], max[1], max[2]);
02871           CubitBox aBox_f(min, max);
02872               //hexlat3 has tolerance issue where aBox_e.x_min is within 
02873               //tolerance and greater than aBox_f.x_min, causing no edge
02874               //imprint of the faces. change to add consideration of tolerance
02875               // lose the bounding box critiral a little more.
02876               int num_satisfied = 0;
02877               
02878               if (aBox_f.min_x() >= 0 && aBox_e.min_x() >= aBox_f.min_x() *0.9)
02879                   num_satisfied ++;
02880               if(aBox_f.min_x() < 0 && aBox_e.min_x() >= aBox_f.min_x() *1.1)
02881           num_satisfied ++;
02882      
02883               if (aBox_f.min_y() >= 0 && aBox_e.min_y() >= aBox_f.min_y() *0.9)
02884                   num_satisfied ++;
02885               if(aBox_f.min_y() < 0 && aBox_e.min_y() >= aBox_f.min_y() *1.1)
02886                   num_satisfied ++;
02887 
02888               if(aBox_f.min_z() >= 0 && aBox_e.min_z() >= aBox_f.min_z() *0.9)
02889                   num_satisfied ++;
02890               if (aBox_f.min_z() < 0 && aBox_e.min_z() >= aBox_f.min_z() *1.1)
02891                   num_satisfied ++;
02892 
02893               if (aBox_f.max_x() > 0  && aBox_e.max_x() <= aBox_f.max_x() *1.1)
02894                 num_satisfied ++;
02895               if(aBox_f.max_x() <= 0 && aBox_e.max_x() <= aBox_f.max_x() *0.9)
02896                 num_satisfied ++;
02897               if( aBox_f.max_y() > 0 && aBox_e.max_y() <= aBox_f.max_y() *1.1) 
02898                 num_satisfied ++;
02899               if( aBox_f.max_y() <= 0 && aBox_e.max_y() <= aBox_f.max_y() *0.9)
02900                 num_satisfied ++;
02901               if( aBox_f.max_z() >= 0 && aBox_e.max_z() <= aBox_f.max_z() *1.1)
02902                 num_satisfied ++;  
02903               if( aBox_f.max_z() < 0 && aBox_e.max_z() <= aBox_f.max_z() *0.9)
02904                 num_satisfied ++;
02905 
02906               if(num_satisfied == 6) 
02907         {
02908           curve_list.append_unique(curve);
02909         }
02910               else
02911               {
02912                 curve_list.remove(curve);
02913                 OCCQueryEngine::instance()->delete_solid_model_entities( curve );
02914                 total_edges--;
02915               }
02916         }
02917     }
02918 
02919       if(face_created)
02920       {
02921         OCCQueryEngine::instance()->delete_solid_model_entities(occ_face);
02922         face_created = CUBIT_FALSE;
02923       }
02924       DLIList<DLIList<TopoDS_Edge*>*> edge_lists;
02925       if ( total_edges >= 1) 
02926     {      
02927       CubitStatus stat = CUBIT_SUCCESS;
02928           if(curve_list.size() > 0)
02929         stat = sort_curves(curve_list, edge_lists); 
02930           else
02931         {
02932           TopoDS_Face* topo_face = new TopoDS_Face(from_face);
02933           from_faces.append(topo_face);
02934           continue;
02935         }
02936       DLIList<TopoDS_Edge*>* edge_list;
02937           int size = edge_lists.size();
02938         
02939           //if size > 1 , outer wire first. 
02940           DLIList<CubitBox*> bs;
02941           edge_lists.reset();
02942           CubitBox box;
02943           for(int i = 0; i < size && size > 1; i++)
02944           {
02945             edge_list = edge_lists.get_and_step();
02946             for(int j = 0; j < edge_list->size(); j++)
02947             {
02948               TopoDS_Edge e = *(edge_list->get_and_step());
02949               CubitBoolean bound = CUBIT_FALSE;
02950               Curve* curve = NULL;
02951               if(OCCQueryEngine::instance()->OCCMap->IsBound(e))
02952               {
02953                 int k = OCCQueryEngine::instance()->OCCMap->Find(e);
02954                 bound = CUBIT_TRUE;
02955                 curve = (Curve*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
02956               }
02957               else
02958                 curve = OCCQueryEngine::instance()->
02959                          populate_topology_bridge(e, true);
02960               if(j == 0)
02961                 box = curve->bounding_box();
02962               else
02963                 box |= curve->bounding_box();
02964               if(!bound)
02965                 OCCQueryEngine::instance()->delete_solid_model_entities(curve);
02966             }
02967             CubitBox* pbox = new CubitBox(box);
02968             bs.append(pbox);
02969           }
02970           bs.append((CubitBox*) NULL);
02971 
02972           for(int i = 0; i < size-1; i++)
02973           {
02974             for(int j = i + 1; j < size; j ++)
02975             {
02976               edge_lists.reset();
02977               if(*bs[j] <= *bs[i])
02978               {
02979                 edge_lists.step(j);
02980                 edge_lists.get()->clean_out();
02981                 delete edge_lists.get();
02982                 edge_lists.change_to((DLIList<TopoDS_Edge*>*)NULL);
02983                 continue;
02984               }
02985               if(*bs[i] <= *bs[j])
02986               {
02987                 edge_lists.step(i);
02988                 edge_lists.get()->clean_out();
02989                 delete edge_lists.get();
02990                 edge_lists.change_to((DLIList<TopoDS_Edge*>*)NULL);
02991                 break;
02992               }
02993             }
02994           }
02995           for(int i = 0; i < size && size > 1; i++)
02996             delete bs.pop();
02997 
02998           edge_lists.remove_all_with_value((DLIList<TopoDS_Edge*>*)NULL);
02999 
03000           size = edge_lists.size();
03001           for (int iii = 0; iii < size; iii++)
03002         {
03003           edge_list = edge_lists.pop();
03004 
03005           //check if the edges make a split of the surface, error out if it's
03006           //just a scar on the surface
03007           int count_intersection = 0;
03008           if (stat == CUBIT_FAILURE) //Open wire
03009         {
03010           count_intersection = check_intersection(edge_list, from_face);
03011             
03012           if (count_intersection == 1 )
03013                   {
03014             PRINT_WARNING("Cant make a scar on existing face without splitting it. \n");
03015                     edge_list->clean_out();
03016                     delete edge_list;
03017                   }
03018         } 
03019           if (stat || count_intersection == 2)
03020         {
03021           BRepBuilderAPI_MakeWire myWire;
03022           edge_list->reset(); 
03023                   DLIList<Curve*> wire_curves;
03024           for(int i = 0; i < edge_list->size(); i++)
03025             {
03026               TopoDS_Edge e = *(edge_list->get_and_step());
03027                       //remove curve from its vertice's curve list
03028                       if(OCCQueryEngine::instance()->OCCMap->IsBound(e))
03029                       {
03030                         int j = OCCQueryEngine::instance()->OCCMap->Find(e);
03031                         Curve* curve = (Curve*)(OCCQueryEngine::instance()->OccToCGM->find(j))->second;
03032                         OCCCurve* curve_to_remove = (OCCCurve*) curve;
03033                         wire_curves.append(curve);
03034                         DLIList<OCCPoint*> points;
03035                         curve_to_remove->get_points(points);
03036                         for (int k = 0; k < points.size(); k++)
03037                           points.get_and_step()->remove_curve(curve_to_remove);
03038                       }
03039                       else if(periodic && count_intersection != 2)
03040                       {
03041                         Curve* curve = OCCQueryEngine::instance()->
03042                                populate_topology_bridge(e,true);
03043                         wire_curves.append(curve);
03044                       }
03045               myWire.Add(e); 
03046             }
03047                   edge_list->clean_out();
03048                   delete edge_list;
03049                   if(!periodic || count_intersection == 2 ||
03050                      type == PLANE_SURFACE_TYPE)
03051                   {
03052             splitor.Add(myWire.Wire(),from_face);
03053             topo_changed = CUBIT_TRUE; 
03054                      
03055                   }
03056                   else 
03057                   {
03058                     //use the myWire to create a surface and webcut the 
03059                     //periodic body.
03060                     Surface *wire_surf = make_Surface(BEST_FIT_SURFACE_TYPE,
03061                        wire_curves);
03062                     if(wire_surf == NULL)
03063                       wire_surf = make_Surface(PLANE_SURFACE_TYPE, wire_curves);
03064                     if(wire_surf)
03065                     {
03066                       OCCSurface* occ_wire_s = CAST_TO(wire_surf, OCCSurface);
03067                       TopoDS_Face *topo_face = occ_wire_s->get_TopoDS_Face();
03068                       on_faces.append(topo_face);
03069                       return 3; 
03070                     }
03071                   } 
03072         }
03073         }
03074     } 
03075       if(topo_changed)
03076     {
03077       splitor.Build();
03078       topo_changed = CUBIT_FALSE;
03079       if(splitor.IsDone())
03080         {
03081           //take care of on_faces list first:after operation, the on_faces
03082           // will have at least one face changed, update the pointer.
03083               int size = on_faces.size();
03084           if (size > 0)
03085         {
03086           for(int k = 0; k < size; k++)
03087             {
03088               TopoDS_Face* compare_face = on_faces.get();
03089                       TopTools_ListOfShape shapes;
03090                       shapes.Assign(splitor.Modified(*compare_face));
03091                       if(shapes.Extent() > 0 && 
03092                          !compare_face->IsSame(shapes.First()))
03093                       {
03094                 on_faces.change_to(NULL);
03095                 while(shapes.Extent() > 0)
03096                 {
03097                   TopoDS_Face* face = 
03098                 new TopoDS_Face(TopoDS::Face(shapes.First())); 
03099               shapes.RemoveFirst();
03100               on_faces.append(face);
03101             }
03102                       }
03103                       on_faces.step();
03104             }
03105                     on_faces.remove_all_with_value(NULL);
03106         }
03107 
03108           TopoDS_Shape new_from_shape = splitor.Shape();
03109           if(from_shape->ShapeType() == TopAbs_COMPOUND)
03110         {
03111           TopoDS_Compound old_csolid = TopoDS::Compound(*from_shape);
03112           OCCBody::update_OCC_entity(old_csolid, new_from_shape, &splitor);
03113                   if(!old_csolid.IsEqual(new_from_shape))
03114                   {
03115                      from_shape->Nullify();
03116                      *from_shape = new_from_shape;
03117                   }                     
03118         }
03119 
03120           else if(from_shape->ShapeType() == TopAbs_SOLID)
03121         {
03122           TopoDS_Solid old_solid = TopoDS::Solid(*from_shape);
03123           OCCLump::update_OCC_entity(old_solid, new_from_shape, &splitor);
03124                   if(!old_solid.IsEqual(new_from_shape))
03125                   { 
03126                      from_shape->Nullify();
03127                      *from_shape = new_from_shape;
03128                   }
03129         }
03130           else if(from_shape->ShapeType() == TopAbs_SHELL)
03131         {
03132           TopoDS_Shell old_shell = TopoDS::Shell(*from_shape);
03133           OCCShell::update_OCC_entity(old_shell,new_from_shape, &splitor);
03134                   if(!old_shell.IsEqual(new_from_shape))
03135                   {
03136                      from_shape->Nullify();
03137                      *from_shape = new_from_shape;
03138                   }
03139         }
03140           else if(from_shape->ShapeType() == TopAbs_FACE)
03141         {
03142           TopoDS_Face old_face = TopoDS::Face(*from_shape);
03143           OCCSurface::update_OCC_entity(old_face,new_from_shape, &splitor);
03144                   if(!old_face.IsEqual(new_from_shape))
03145                   {
03146                      from_shape->Nullify();
03147                      *from_shape = new_from_shape;
03148                   }
03149         }
03150 
03151           TopTools_ListOfShape shapes;
03152           for(int i = 0; i < from_faces.size(); i++)
03153         {
03154           TopoDS_Face* topo_face = from_faces.get();
03155           shapes.Assign(splitor.Modified(*topo_face));
03156           topo_face = new TopoDS_Face(TopoDS::Face(shapes.First()));
03157           from_faces.get()->Nullify();
03158           delete from_faces.get();
03159           from_faces.change_to(topo_face);
03160           from_faces.step();
03161         } 
03162           count++;
03163         }
03164     }
03165       else
03166     {
03167       TopoDS_Face* topo_face = new TopoDS_Face(from_face);
03168       from_faces.append(topo_face);
03169     } 
03170     }
03171   
03172   TopExp_Explorer Ex;
03173   int num_face = 0;
03174   for (Ex.Init(*from_shape, TopAbs_FACE); Ex.More(); Ex.Next())
03175     {
03176       TopoDS_Face face = TopoDS::Face(Ex.Current());
03177       num_face++;
03178     }
03179   
03180 #ifdef DEBUG  
03181   PRINT_INFO("Total %d cuts performed, with from_shape having %d faces.\n", count, num_face); 
03182 #endif
03183 
03184   if (count > 0)
03185     return 0;
03186   return 2;
03187 }
03188 
03189 //===============================================================================
03190 // Function   : find_imprinting_edge
03191 // Member Type: PROTECTED
03192 // Description: imprint boolean operation on OCC-based bodies.
03193 //              from_shape must be TopoDS_Face or above, tool_shape must be
03194 //              TopoDS_Edge.
03195 // Author     : Jane HU
03196 // Date       : 05/08
03197 //===============================================================================
03198 TopoDS_Edge* OCCModifyEngine::find_imprinting_edge(TopoDS_Shape& from_shape,
03199                                         TopoDS_Edge& tool_shape,
03200                                         DLIList<TopoDS_Face*>& from_faces)const
03201 {
03202   TopoDS_Edge* edge = NULL;
03203   //list of face on from_shape that has been imprinted
03204   from_faces.clean_out();
03205   BRepAdaptor_Curve acurve(tool_shape);
03206   Bnd_Box aBox_edge, aBox_face;
03207   BndLib_Add3dCurve::Add(acurve, Precision::Approximation(), aBox_edge);
03208 
03209   TopExp_Explorer Ex;
03210   for (Ex.Init(from_shape, TopAbs_FACE); Ex.More(); Ex.Next())
03211   {
03212     TopoDS_Face face = TopoDS::Face(Ex.Current());
03213     BRepAdaptor_Surface asurface( face);
03214     aBox_face.SetVoid();
03215     BndLib_AddSurface::Add(asurface, Precision::Approximation(), aBox_face);
03216     if (aBox_face.IsOut(aBox_edge))
03217       continue;
03218 
03219     BRepAlgoAPI_Common intersector(face, tool_shape);
03220     TopTools_ListOfShape shapes;
03221     shapes.Assign(intersector.Generated(tool_shape));
03222     if(shapes.IsEmpty())
03223       shapes.Assign(intersector.Modified(tool_shape));
03224     if (shapes.IsEmpty())
03225       continue;
03226     if ( shapes.Extent() > 1)
03227     {
03228       PRINT_ERROR("Edge has multiple intersection with the shape, make it simpler. \n");
03229       continue;
03230     }
03231     if (shapes.First().ShapeType() != TopAbs_EDGE  && 
03232         shapes.First().ShapeType() != TopAbs_COMPOUND)
03233       continue;
03234 
03235     TopoDS_Shape result = shapes.First();
03236     TopoDS_Edge common_edge;
03237     if(edge == NULL && result.ShapeType() == TopAbs_EDGE)
03238       common_edge = TopoDS::Edge(result);
03239     
03240     else if(edge == NULL && 
03241             result.ShapeType() == TopAbs_COMPOUND)
03242     {
03243       TopExp_Explorer Ex(result, TopAbs_EDGE);
03244       if(Ex.More())
03245         common_edge = TopoDS::Edge(Ex.Current());
03246     }  
03247     if (common_edge.IsNull())
03248       continue;
03249     BRepBuilderAPI_Copy api_copy(common_edge);
03250     TopoDS_Shape newShape = api_copy.ModifiedShape(common_edge);
03251     edge = new TopoDS_Edge(TopoDS::Edge(newShape));
03252 
03253     from_faces.append(new TopoDS_Face(face));
03254   }
03255   return edge;
03256 }
03257 
03258 int OCCModifyEngine::check_intersection(DLIList<TopoDS_Edge*>*& edge_list,
03259                         TopoDS_Face from_face)const
03260 {
03261   int  count_intersection = 0;
03262 
03263   gp_Pnt newP[2] , p_test ;
03264   for(int kk = 0; kk < edge_list->size(); kk++)
03265   {
03266     TopoDS_Edge* edge = edge_list->get_and_step();
03267     BRepAdaptor_Curve acurve(*edge);
03268     double lower_bound = acurve.FirstParameter();
03269     double upper_bound = acurve.LastParameter();
03270     TopExp_Explorer Ex;
03271     for (Ex.Init(from_face, TopAbs_EDGE); Ex.More(); Ex.Next())
03272     {
03273       TopoDS_Edge from_edge = TopoDS::Edge(Ex.Current());
03274       BRepAdaptor_Curve acurve2(from_edge);
03275       double lower_bound2 = acurve2.FirstParameter();
03276       double upper_bound2 = acurve2.LastParameter();
03277       BRepExtrema_DistShapeShape distShapeShape(*edge, from_edge);
03278 
03279       if (distShapeShape.IsDone() && distShapeShape.Value() < TOL)
03280       {
03281         //double check that the point is on the edges.
03282         double newVal;
03283         for(int j =1; j <= distShapeShape.NbSolution(); j++)
03284         {
03285           if(count_intersection == 2)
03286             break;
03287 
03288           p_test = distShapeShape.PointOnShape1(j);
03289           Extrema_ExtPC ext(p_test, acurve, Precision::Approximation());
03290           // At this time, there must be a intersection point at least.
03291           if (ext.IsDone() && (ext.NbExt() > 0)) {
03292             for ( int i = 1 ; i <= ext.NbExt() ; i++ ) {
03293               newVal = ext.Point(i).Parameter();
03294               if ((newVal-lower_bound) >= -TOL &&
03295                   (upper_bound - newVal) >= -TOL)
03296               {
03297                 Extrema_ExtPC ext(p_test, acurve2, Precision::Approximation());
03298                 if (ext.IsDone() && (ext.NbExt() > 0)) {
03299                   for ( int k = 1 ; k <= ext.NbExt() ; k++ ) {
03300                     newVal = ext.Point(i).Parameter();
03301                     if ((newVal-lower_bound2) >= -TOL &&
03302                         (upper_bound2 - newVal) >= -TOL)
03303                     {
03304                       newP[count_intersection] = p_test;
03305                       count_intersection ++;
03306                       break;
03307                     }
03308                   }
03309                 }
03310               }
03311             }
03312           }
03313         }
03314       }
03315 
03316       if (count_intersection == 2)
03317       {
03318          //make sure the two intersect point are not the same one
03319          if (newP[0].IsEqual(newP[1], TOL))
03320            count_intersection--;
03321       }
03322       if (count_intersection == 2)
03323         break;
03324     } //for loop
03325   }
03326   return count_intersection;
03327 }
03328 //===============================================================================
03329 // Function   : imprint
03330 // Member Type: PUBLIC
03331 // Description: imprint boolean operation on OCC-based bodies
03332 // Author     : Jane Hu
03333 // Date       : 04/08
03334 //===============================================================================
03335 CubitStatus     OCCModifyEngine::imprint(BodySM* BodyPtr1, BodySM* BodyPtr2,
03336                                          BodySM*& newBody1, BodySM*& newBody2,
03337                                          bool  keep_old) const
03338 {
03339   newBody1 = NULL;
03340   newBody2 = NULL;
03341   DLIList<TopoDS_Shape*> shape_list;
03342   DLIList<CubitBoolean> is_volume;
03343   
03344   DLIList<BodySM*> bodysm_list;
03345   bodysm_list.append(BodyPtr1);
03346   bodysm_list.append(BodyPtr2);
03347   
03348   CubitStatus stat = get_shape_list(bodysm_list,shape_list,is_volume,keep_old);
03349 
03350   if(!stat)
03351     return stat;
03352 
03353   TopoDS_Shape* shape1 = shape_list.get();
03354   TopoDS_Shape* shape2 = shape_list.step_and_get();
03355   DLIList<TopologyBridge*> tbs;
03356   DLIList<TopoDS_Face*> face_list;
03357   int result = imprint_toposhapes(shape1, shape2, face_list);
03358   if(result == 0)
03359   {
03360     tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape1); 
03361     newBody1 = CAST_TO(tbs.get(),BodySM);
03362   }
03363 
03364   else if(result == 1)
03365   {
03366     //for cylinder overlapping cases, doing boolean operation is necessary for 
03367     //now. 10/25/11
03368     BodySM* tool_copy = copy_body(BodyPtr2);
03369 /*
03370     DLIList<BodySM*> tools;
03371     tools.append(tool_copy);
03372     DLIList<BodySM*> from_bodies ;
03373     BodySM* from_copy = copy_body(BodyPtr1);
03374     from_bodies.append(from_copy);
03375     DLIList<BodySM*> new_bodies;
03376     stat = subtract(tools, from_bodies, new_bodies, false, false);
03377     if (stat)
03378     {
03379       tool_copy = copy_body(BodyPtr2);
03380       from_bodies.clean_out();
03381       from_bodies.append(BodyPtr1);
03382       intersect(tool_copy, from_bodies, new_bodies, false);
03383       if(new_bodies.size() > 1)
03384       {
03385         DLIList<BodySM*> final_bodies;
03386         unite(new_bodies, final_bodies, false); 
03387         newBody1 = final_bodies.get();
03388       }
03389       else
03390         newBody1 = new_bodies.get();
03391     }
03392 */
03393     stat = result_1_imprint(BodyPtr1, tool_copy, newBody1);
03394     if(stat == CUBIT_FAILURE)
03395       result = 2;
03396   }
03397   else if(result == 3)
03398   {
03399     TopoDS_Face* face = face_list.pop();
03400     int j = OCCQueryEngine::instance()->OCCMap->Find(*face);
03401     OCCSurface* cut_face = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(j))->second; 
03402     OCCBody* tool_body = cut_face->my_body();
03403     stat = result_3_imprint(BodyPtr1,tool_body, newBody1); 
03404     if(stat == CUBIT_FAILURE)
03405       result = 2;
03406   }
03407 
03408   if(result && keep_old)
03409   {
03410     delete shape1;
03411     shape1 = NULL;
03412     PRINT_INFO("There's no imprint on the first body.\n");
03413     newBody1 = BodyPtr1;
03414   }
03415 
03416   tbs.clean_out();
03417   result = imprint_toposhapes(shape2, shape1, face_list);
03418   if(result == 0)
03419   {
03420     tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape2);
03421     newBody2 = CAST_TO(tbs.get(),BodySM);     
03422   }
03423   
03424   else if(result == 1)
03425   {
03426     //for cylinder overlapping cases, doing boolean operation is necessary for 
03427     //now. 10/25/11
03428     BodySM* tool_copy = copy_body(BodyPtr1);
03429 /*
03430     DLIList<BodySM*> tools;
03431     tools.append(tool_copy);
03432     DLIList<BodySM*> from_bodies ;
03433     BodySM* from_copy = copy_body(BodyPtr2);
03434     from_bodies.append(from_copy);
03435     DLIList<BodySM*> new_bodies;
03436     stat = subtract(tools, from_bodies, new_bodies, false, false);
03437     if (stat)
03438     {
03439       tool_copy = copy_body(BodyPtr1);
03440       from_bodies.clean_out();
03441       from_bodies.append(BodyPtr2);
03442       intersect(tool_copy, from_bodies, new_bodies, false);
03443       if(new_bodies.size() > 1)
03444       {
03445         DLIList<BodySM*> final_bodies;
03446         unite(new_bodies, final_bodies, false);       
03447         newBody2 = final_bodies.get();
03448       }
03449       else
03450         newBody2 = new_bodies.get();
03451     }
03452 */
03453     stat = result_1_imprint(BodyPtr2, tool_copy, newBody2);
03454     if(stat == CUBIT_FAILURE)
03455       result = 2; 
03456   }
03457 
03458   else if(result == 3)
03459   {
03460     TopoDS_Face* face = face_list.pop();
03461     int j = OCCQueryEngine::instance()->OCCMap->Find(*face);
03462     OCCSurface* cut_face = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(j))->second; 
03463     OCCBody* tool_body = cut_face->my_body();
03464     stat = result_3_imprint(BodyPtr2,tool_body, newBody2); 
03465     if(stat == CUBIT_FAILURE)
03466       result = 2;
03467   }
03468 
03469   if(result && keep_old)
03470   {
03471     delete shape2;
03472     shape2 = NULL;
03473     PRINT_INFO("There's no imprint on the second body.\n");
03474     newBody2 = BodyPtr2;
03475   }
03476   return CUBIT_SUCCESS;
03477 }
03478 
03479 //===============================================================================
03480 // Function   : get_shape_list
03481 // Member Type: PRIVATE
03482 // Description: get the TopoDS_Shape list for imprinting use. 
03483 // Author     : Jane Hu
03484 // Date       : 05/08
03485 //===============================================================================
03486 CubitStatus OCCModifyEngine::get_shape_list(DLIList<BodySM*>& BodySM_list, 
03487                                          DLIList<TopoDS_Shape*>& shape_list,
03488                                          DLIList<CubitBoolean>& is_volume,
03489                                          bool  keep_old,
03490                                          DLIList<CubitBox*>* b_boxes) const
03491 {
03492   OCCBody* occ_body = NULL;
03493   shape_list.clean_out();
03494   is_volume.clean_out();
03495   CubitStatus stat = CUBIT_SUCCESS;
03496   for(int i = 0; i <BodySM_list.size(); i++)
03497   {
03498     occ_body = CAST_TO(BodySM_list.get_and_step(), OCCBody);
03499     if (!occ_body)
03500       continue;
03501 
03502     if(b_boxes)
03503     {
03504       CubitBox *tool_box = new CubitBox(occ_body->get_bounding_box());
03505       b_boxes->append(tool_box);
03506     }
03507 
03508     TopoDS_Compound* shape = occ_body->get_TopoDS_Shape();
03509     if( shape && !shape->IsNull())
03510     {
03511       if(keep_old)
03512       {
03513         BRepBuilderAPI_Copy api_copy(*shape);
03514         TopoDS_Shape newShape = api_copy.ModifiedShape(*shape);
03515         TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape);
03516         shape_list.append(Shape1);
03517       }
03518       else
03519         shape_list.append_unique(shape);
03520       TopExp_Explorer Ex(*shape, TopAbs_SOLID);
03521       if(Ex.More())
03522         is_volume.append( CUBIT_TRUE);
03523       else
03524         is_volume.append( CUBIT_FALSE);
03525       continue;
03526     }
03527 
03528     DLIList<OCCSurface*> surfaces;
03529     DLIList<OCCShell*>   shells;
03530     DLIList<OCCCurve*>   curves;    
03531 
03532     surfaces = occ_body->my_sheet_surfaces();
03533     shells = occ_body->shells();
03534     if(surfaces.size() + shells.size() > 1)
03535     {
03536       PRINT_ERROR("Can't do boolean operation on multiple-volume body.\n");
03537       stat = CUBIT_FAILURE;
03538       break;
03539     }
03540     is_volume.append( CUBIT_TRUE);
03541 
03542     if(surfaces.size() == 1)
03543     {
03544       TopoDS_Face* topo_face = surfaces.get()->get_TopoDS_Face();
03545       if(!topo_face)
03546       {
03547         stat = CUBIT_FAILURE;
03548         break;
03549       }
03550       if(keep_old)
03551       {
03552         BRepBuilderAPI_Copy api_copy(*topo_face);
03553         TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_face);
03554         TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape);
03555         shape_list.append(Shape1);
03556       }
03557       else
03558         shape_list.append(topo_face);
03559       is_volume.last();
03560       is_volume.change_to( CUBIT_FALSE);
03561     }
03562     else if(shells.size() == 1)
03563     {
03564       TopoDS_Shell* topo_shell = shells.get()->get_TopoDS_Shell();
03565       if(!topo_shell)
03566       {
03567         stat = CUBIT_FAILURE;
03568         break;
03569       }
03570       if(keep_old)
03571       {
03572         BRepBuilderAPI_Copy api_copy(*topo_shell);
03573         TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_shell);
03574         TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape);
03575         shape_list.append(Shape1);
03576       }
03577       else
03578         shape_list.append(topo_shell);
03579       is_volume.change_to( CUBIT_FALSE);
03580     }
03581 
03582     else 
03583     {
03584       DLIList<Lump*> lumps = occ_body->lumps();
03585       if (lumps.size() > 1)
03586       {
03587         PRINT_ERROR("Can't do boolean operation on multi-volumes types. \n");
03588         stat = CUBIT_FAILURE;
03589         break;
03590       }
03591 
03592       TopoDS_Solid* solid = CAST_TO(lumps.get(), OCCLump)->get_TopoDS_Solid();
03593       if(!solid)
03594       {
03595         stat = CUBIT_FAILURE;
03596         break;
03597       }
03598       if(keep_old)
03599       {
03600         BRepBuilderAPI_Copy api_copy(*solid);
03601         TopoDS_Shape newShape = api_copy.ModifiedShape(*solid);
03602         TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape);
03603         shape_list.append(Shape1);
03604       }
03605       else
03606         shape_list.append(solid);
03607     }
03608   }
03609   if(!stat)
03610   {   
03611     for (int i = 0; keep_old && i < shape_list.size(); i++)
03612     {
03613           TopoDS_Shape* shape = shape_list.get_and_step();
03614           delete shape;
03615           shape = NULL;
03616     }
03617     shape_list.clean_out();
03618     return CUBIT_FAILURE;
03619   }
03620   return CUBIT_SUCCESS;
03621 }
03622 //===============================================================================
03623 // Function   : imprint multiple bodies at once
03624 // Member Type: PUBLIC
03625 // Description: imprint boolean operation on OCC-based bodies
03626 // Author     : Jane HU
03627 // Date       : 04/08
03628 //===============================================================================
03629 CubitStatus OCCModifyEngine::imprint(DLIList<BodySM*> &from_body_list ,
03630                                      DLIList<BodySM*> &new_from_body_list,
03631                                      bool keep_old,
03632                                      DLIList<TopologyBridge*>* new_tbs,
03633                                      DLIList<TopologyBridge*>* att_tbs) const
03634 {
03635   CubitStatus success = CUBIT_SUCCESS;
03636   DLIList<TopoDS_Shape*> shape_list;
03637   DLIList<CubitBoolean> is_vo;
03638 
03639   //keep record of all vertices and edges and faces in the from_body_list,
03640   //for comparison to generated new_tbs and att_tbs.
03641   DLIList<OCCSurface*> surfaces;
03642   DLIList<OCCCurve*> curves;
03643   DLIList<OCCPoint*> points;
03644 
03645   CubitStatus stat = get_shape_list(from_body_list, shape_list, is_vo,keep_old);
03646 
03647   if(!stat)
03648     return stat;
03649  
03650   int size = shape_list.size();
03651   // total number of imprints to be done
03652   int total_imprints = size * (size -1);
03653 
03654   if( size > 2 )
03655   {
03656      char message[128];
03657      sprintf(message, "Imprinting %d OCC Bodies", from_body_list.size() ); 
03658      AppUtil::instance()->progress_tool()->start(0, total_imprints, message);
03659   }
03660   
03661   std::map<OCCSurface*, std::pair<CubitVector, int> > surf_property_map;
03662   std::map<OCCCurve*, std::pair<CubitVector, int> > curve_property_map;
03663 
03664   for(int i = 0; i < size; i++)
03665   {
03666     TopoDS_Shape* shape1 = shape_list[i];
03667     CubitBoolean modified = CUBIT_FALSE;
03668 
03669     DLIList<TopoDS_Face*> face_list;
03670     for(int j = i+1; j < size+i; j ++)
03671     {
03672        if (AppUtil::instance()->interrupt())
03673        {
03674           success = CUBIT_FAILURE;
03675           break;
03676        }
03677 
03678        TopoDS_Shape* shape2 = shape_list[j%size];
03679        DLIList<TopologyBridge*> tbs;
03680        int result = imprint_toposhapes(shape1, shape2, face_list);
03681        if(result == 0)
03682        {
03683           DLIList<TopologyBridge*> tbs;
03684           tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape1);
03685           from_body_list[i] = CAST_TO(tbs.get(),BodySM);
03686           modified = CUBIT_TRUE;
03687        }
03688        else if(result == 1)
03689        {
03690          //for cylinder overlapping cases, doing boolean operation is necessary for 
03691          //now. 10/25/11
03692          BodySM* tool_copy = copy_body(from_body_list[j%size]);
03693          BodySM* newBody = NULL;
03694 
03695          stat = result_1_imprint(from_body_list[i], tool_copy, newBody);
03696          if (stat && newBody)
03697          {
03698            modified = CUBIT_TRUE;
03699            DLIList<TopoDS_Shape*> shapes;
03700            DLIList<CubitBoolean> is_volume;
03701            DLIList<BodySM*> new_bodies;
03702            new_bodies.append(newBody);
03703            get_shape_list(new_bodies, shapes, is_volume,false);
03704            shape1 = shapes.get();
03705            //shape_list[i] = shape1;
03706            from_body_list[i] = newBody;
03707          }
03708        }
03709        else if(result == 3)
03710        {
03711          BodySM* newBody = NULL;
03712          BodySM* oldBody = from_body_list[i];
03713          TopExp_Explorer Ex;
03714          Ex.Init(*shape1, TopAbs_SOLID);
03715          int nSolid = 0;
03716          for(; Ex.More(); Ex.Next())
03717            nSolid++;
03718          do
03719          { 
03720            TopoDS_Face* face = face_list.pop();
03721            int k = OCCQueryEngine::instance()->OCCMap->Find(*face);
03722            OCCSurface* cut_face = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
03723            OCCBody* tool_body = cut_face->my_body();
03724 
03725            stat = result_3_imprint(oldBody, tool_body, newBody);
03726            if (newBody)
03727            {
03728              modified = CUBIT_TRUE;
03729              DLIList<TopoDS_Shape*> shapes;
03730              DLIList<CubitBoolean> is_volume;
03731              DLIList<BodySM*> new_bodies;
03732              new_bodies.append(newBody);
03733              get_shape_list(new_bodies, shapes, is_volume,false);
03734              shape1 = shapes.get();
03735              //shape_list[i] = shape1;
03736              from_body_list[i] = newBody;
03737            }
03738            if(nSolid == 1)
03739              break;
03740            else
03741              nSolid --;
03742            result = imprint_toposhapes(shape1, shape2, face_list); 
03743            oldBody = newBody;
03744          }while (result == 3);
03745        }
03746     }
03747     if(modified)
03748       new_from_body_list.append(from_body_list[i]);
03749     
03750     shape_list.reset();
03751     if( size > 2 )
03752       AppUtil::instance()->progress_tool()->step();
03753   }
03754 
03755   if( size > 2 )
03756     AppUtil::instance()->progress_tool()->end();
03757 
03758   if( AppUtil::instance()->interrupt() )
03759         PRINT_INFO("Imprint aborted.\n");
03760 
03761   return success;
03762 }
03763 
03764 CubitStatus OCCModifyEngine::result_3_imprint(BodySM* from_body, 
03765                                               BodySM* tool_body, 
03766                                               BodySM*& newBody)const
03767 {
03768   DLIList<BodySM*> from_bodies;
03769   from_bodies.append(from_body); 
03770   DLIList<BodySM*> results_list;
03771   DLIList<BodySM*> neighbor_imprint_list;
03772   CubitStatus stat = webcut(from_bodies, tool_body, neighbor_imprint_list, 
03773                             results_list);
03774   if(results_list.size() > 1)
03775   {
03776     DLIList<BodySM*> bodies;
03777     unite(results_list, bodies, false); 
03778     newBody = bodies.get();
03779   }
03780   else if (results_list.size() == 1)
03781     newBody = results_list.get();
03782  
03783   return stat;
03784 
03785 }
03786 
03787 CubitStatus OCCModifyEngine::result_1_imprint(BodySM* from_body,  
03788                                               BodySM* tool_body,
03789                                               BodySM*& newBody)const
03790 {
03791   //for compound of solids in from_body, try to determine if subtracting or
03792   //intersecting will keep the from_body un-deleted by checking subtracting
03793   //first, if it kept the from_body, don't take any further risk, do intersect
03794   //first, then subtract.
03795 
03796   DLIList<TopoDS_Shape*> from_bodies_shapes;
03797   DLIList<BodySM*> from_bodies ;
03798   DLIList<CubitBoolean> is_volume;
03799   from_bodies.append(from_body);
03800   //get the from_bodies underling shapes
03801   CubitStatus stat = get_shape_list(from_bodies, from_bodies_shapes, is_volume, CUBIT_FALSE);
03802 
03803   TopoDS_Shape* from_shape = from_bodies_shapes.get();
03804   int num_solids = 0;
03805   if(from_shape->ShapeType() == TopAbs_COMPOUND)
03806   {
03807     TopExp_Explorer Ex;
03808     for (Ex.Init(*from_shape, TopAbs_SOLID);Ex.More(); Ex.Next())
03809       num_solids++;
03810   }
03811   BodySM* tool_copy = copy_body(tool_body);
03812   DLIList<BodySM*> tools;
03813   tools.append(tool_copy);
03814   from_bodies.clean_out() ;
03815   BodySM* from_copy = copy_body(from_body);
03816   from_bodies.append(from_copy);
03817   DLIList<BodySM*> new_bodies;
03818   stat = subtract(tools, from_bodies, new_bodies, false, false);
03819   if (stat)
03820   {
03821     if (num_solids > 1 && from_copy == new_bodies.get())
03822     {
03823       //double check if subtract kept the original from_bodies pointer.
03824       //if so, do intersect first, then subtract.
03825       tool_copy = copy_body(tool_body);
03826       from_bodies.clean_out(); 
03827       from_copy = copy_body(from_body);
03828       from_bodies.append(from_copy);
03829       OCCQueryEngine::instance()->delete_solid_model_entities(new_bodies);
03830       new_bodies.clean_out();
03831       intersect(tool_copy, from_bodies, new_bodies, false);
03832 
03833       tool_copy = copy_body(tool_body);
03834       tools.clean_out();
03835       tools.append(tool_copy);
03836       from_bodies.clean_out();
03837       from_bodies.append(from_body);
03838       subtract(tools, from_bodies, new_bodies, false, false);
03839     }
03840     else
03841     { 
03842       tool_copy = copy_body(tool_body);
03843       from_bodies.clean_out();
03844       from_bodies.append(from_body);
03845       intersect(tool_copy, from_bodies, new_bodies, false);
03846     }
03847     
03848     //make sure the first body in new_bodies is the one we want to keep.
03849     new_bodies.reverse();
03850     if(new_bodies.size() > 1)
03851     {
03852        DLIList<BodySM*> final_bodies;
03853        unite(new_bodies, final_bodies, false);
03854        new_bodies.clean_out();
03855        new_bodies = final_bodies;
03856     }
03857     newBody = new_bodies.get();
03858   }
03859   return stat;
03860 } 
03861 
03862 //===============================================================================
03863 // Function   : imprint
03864 // Member Type: PUBLIC
03865 // Description: imprint curves onto body_list
03866 // Author     : Jane Hu
03867 // Date       : 05/08
03868 //===============================================================================
03869 CubitStatus     OCCModifyEngine::imprint( DLIList<BodySM*> &body_list,
03870                                            DLIList<Curve*> &ref_edge_list,
03871                                            DLIList<BodySM*>& new_body_list,
03872                                            DLIList<TopologyBridge*> &temp_bridges,
03873                                            bool keep_old,
03874                                            bool show_messages) const
03875 {
03876   CubitStatus success = CUBIT_SUCCESS;
03877   DLIList<TopoDS_Shape*> shape_list, tool_shapes;
03878   DLIList<CubitBoolean> is_vo;
03879   CubitStatus stat = get_shape_list(body_list, shape_list, is_vo, keep_old);
03880   if (!stat)
03881     return stat;
03882 
03883   int size = ref_edge_list.size();
03884   // total number of imprints to be done
03885 
03886   if( size > 2 && show_messages)
03887   {
03888      char message[128];
03889      sprintf(message, "Imprinting %d OCC Bodies", body_list.size() );
03890      AppUtil::instance()->progress_tool()->start(0, size, message);
03891   }
03892   for (int i = 0; i < ref_edge_list.size(); i++)
03893   {
03894     OCCCurve* curve = CAST_TO(ref_edge_list.get_and_step(), OCCCurve) ;
03895     if (!curve)
03896       continue;
03897 
03898     TopoDS_Edge* edge = curve->get_TopoDS_Edge();
03899     if (edge->IsNull())
03900       continue;
03901     
03902     if (AppUtil::instance()->interrupt())
03903     {
03904        success = CUBIT_FAILURE;
03905        break;
03906     }
03907     DLIList<TopoDS_Face*> face_list;
03908     for(int j = 0; j < shape_list.size(); j ++)
03909     {
03910       TopoDS_Shape* shape = shape_list.get();
03911         
03912       int result = imprint_toposhapes(shape, (TopoDS_Shape*)edge, face_list);
03913       if (result == 0)
03914         shape_list.change_to(shape);
03915       shape_list.step();
03916       body_list.step();
03917     }
03918 
03919     if( size > 2 )
03920       AppUtil::instance()->progress_tool()->step();
03921   }   
03922 
03923   for(int j = 0; j < shape_list.size(); j ++)
03924   {
03925     DLIList<TopologyBridge*> tbs;
03926     TopoDS_Shape* shape = shape_list.get_and_step();
03927     tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape);
03928     new_body_list.append(CAST_TO(tbs.get(),BodySM));
03929   }
03930 
03931   if( size > 2 )
03932     AppUtil::instance()->progress_tool()->end();
03933 
03934   if( AppUtil::instance()->interrupt() )
03935         PRINT_INFO("Imprint aborted.\n"); 
03936   return success;
03937 }
03938 
03939 //===============================================================================
03940 // Function   : imprint
03941 // Member Type: PUBLIC
03942 // Description: to be consistante with  imprint.
03943 //              The surfaces must be part of a body, but the curves 
03944 //              just have to be valid OCC edge.
03945 // Author     : Jane Hu
03946 // Date       : 05/08
03947 //===============================================================================
03948 CubitStatus OCCModifyEngine::imprint( DLIList<Surface*> &ref_face_list,
03949                                       DLIList<Curve*> &edge_list,
03950                                       DLIList<TopologyBridge*> &temp_bridges,
03951                                       DLIList<BodySM*>& new_body_list,
03952                                       bool keep_old) const
03953 {
03954   DLIList<TopoDS_Face*> face_list;
03955   DLIList<TopoDS_Shape*> shape_list;
03956  
03957   face_edge_imprint(ref_face_list, edge_list, face_list, shape_list, keep_old);
03958 
03959   TopExp_Explorer Ex;
03960   int num_face = 0;
03961   TopoDS_Shape* shape = shape_list.get_and_step();
03962   for (Ex.Init(*shape, TopAbs_FACE); Ex.More(); Ex.Next())
03963     { 
03964       TopoDS_Face face = TopoDS::Face(Ex.Current());
03965       num_face++;
03966     }
03967 
03968   for(int j = 0; j < shape_list.size(); j ++)
03969   {
03970     DLIList<TopologyBridge*> tbs;
03971     TopoDS_Shape* shape = shape_list.get_and_step();
03972     if (!shape || shape->IsNull())
03973       continue;
03974     if (shape->ShapeType() == TopAbs_COMPOUND)
03975     {
03976       if(!OCCQueryEngine::instance()->OCCMap->IsBound(*shape)) 
03977       {
03978         TopExp_Explorer Ex;
03979         for (Ex.Init(*shape, TopAbs_SOLID);Ex.More(); Ex.Next())
03980         {
03981           TopoDS_Shape subshape = Ex.Current();
03982           tbs += OCCQueryEngine::instance()->populate_topology_bridge(subshape);
03983           new_body_list.append_unique(CAST_TO(tbs.get(),BodySM));
03984         }
03985       }
03986     }
03987     else
03988     {
03989       tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape);
03990       new_body_list.append_unique(CAST_TO(tbs.get(),BodySM));
03991     }
03992   }
03993 
03994 /*
03995   if (keep_old)
03996   {
03997     for(int i = 0; i < face_list.size(); i++)
03998     {
03999       TopoDS_Face* face = face_list.get();
04000       face->Nullify();
04001       delete face;
04002       face =NULL;
04003     }
04004   }
04005 */
04006   return CUBIT_SUCCESS;
04007 }
04008 
04009 //===============================================================================
04010 // Function   : face_edge_imprint
04011 // Member Type: PRIVATE
04012 // Description: to be consistante with  imprint.
04013 //              The surfaces must be part of a body, but the curves
04014 //              just have to be valid OCC edge.
04015 // Author     : Jane Hu
04016 // Date       : 05/08
04017 //===============================================================================
04018 CubitStatus 
04019 OCCModifyEngine::face_edge_imprint( DLIList<Surface*> &ref_face_list,
04020                                     DLIList<Curve*> &edge_list,
04021                                     DLIList<TopoDS_Face*>& face_list,
04022                                     DLIList<TopoDS_Shape*>& shape_list,
04023                                     bool keep_old ) const
04024 {
04025   for(int i = 0; i <ref_face_list.size(); i++)
04026   {
04027     OCCSurface* surface = CAST_TO(ref_face_list.get_and_step(), OCCSurface);
04028     if(!surface)
04029       continue;
04030 
04031     TopoDS_Face* topo_face = surface->get_TopoDS_Face();
04032     face_list.append(topo_face);
04033 
04034     OCCBody* occ_body = NULL;
04035     OCCShell* shell = surface->my_shell();
04036     if(shell && shell->my_body())
04037       occ_body = shell->my_body();
04038     else
04039     {
04040       DLIList<OCCBody*> bodies;
04041       surface->get_bodies(bodies);
04042       if(bodies.size() != 1)
04043       {
04044         PRINT_ERROR("Can't find the corresponding manifold solid body.\n");
04045         return CUBIT_FAILURE;
04046       }
04047       occ_body = bodies.get();
04048     }
04049     TopoDS_Shape *shape ; 
04050     occ_body->get_TopoDS_Shape(shape);
04051 
04052     if(shape && !shape->IsNull())
04053       shape_list.append_unique(shape);
04054   }
04055 
04056   if(keep_old)
04057   {
04058     for(int i = 0; i < shape_list.size(); i++)
04059     {
04060       TopoDS_Shape* shape = shape_list.get();
04061       BRepBuilderAPI_Copy api_copy(*shape);
04062       TopoDS_Shape newShape = api_copy.ModifiedShape(*shape);
04063       TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape);
04064       for(int j = 0; j < face_list.size(); j++)
04065       {
04066         TopoDS_Face* face = face_list.get();
04067         TopExp_Explorer Ex, Ex_new;
04068         for (Ex.Init(*shape, TopAbs_FACE); Ex.More(); Ex.Next())
04069         {
04070           if(face->IsSame(Ex.Current()))
04071           {
04072             face = new TopoDS_Face(TopoDS::Face(api_copy.ModifiedShape(*face)));
04073             face_list.change_to(face);
04074           }
04075         }
04076         face_list.step();
04077       }
04078       shape_list.change_to(Shape1);
04079       shape_list.step();
04080     }
04081   }
04082 
04083   for (int i = 0; i < edge_list.size(); i++)
04084   {
04085     OCCCurve* curve = CAST_TO(edge_list.get_and_step(), OCCCurve) ;
04086     if (!curve)
04087       continue;
04088 
04089     TopoDS_Edge* edge = curve->get_TopoDS_Edge();
04090     if (edge->IsNull())
04091       continue;
04092 
04093     for(int j = 0; j < shape_list.size(); j ++)
04094     {
04095       TopoDS_Shape* shape = shape_list.get_and_step();
04096       DLIList<TopoDS_Face*> record_faces;
04097       for (int e = 0; e < face_list.size(); e++)
04098         record_faces.append(face_list.get_and_step()); 
04099 
04100       imprint_toposhapes(shape, (TopoDS_Shape*)edge, face_list);
04101       for (int e = 0; e < record_faces.size()&& keep_old; e++)  
04102       {
04103         TopoDS_Face* test_face = record_faces.get_and_step();
04104         if(!face_list.move_to(test_face))
04105         {
04106           test_face->Nullify();
04107           delete test_face;
04108         }
04109       }
04110     }
04111   }
04112 
04113   for(int j = 0; keep_old && j < face_list.size(); j++)
04114   {
04115     TopoDS_Face* face = face_list.get_and_step(); 
04116     face->Nullify();
04117     delete face;
04118   }
04119 
04120   TopExp_Explorer Ex;
04121   int num_face = 0;
04122   TopoDS_Shape* shape = shape_list.get_and_step();
04123   for (Ex.Init(*shape, TopAbs_FACE); Ex.More(); Ex.Next())
04124     {
04125       TopoDS_Face face = TopoDS::Face(Ex.Current());
04126       num_face++;
04127     }
04128 
04129   return CUBIT_SUCCESS;
04130 }
04131 //===============================================================================
04132 // Function   : imprint
04133 // Member Type: PUBLIC
04134 // Description: To be consistent with  ModifyEngine, althought it's hard
04135 //              to have a GUI interface for users to input. All surface must
04136 //              on the same body. 
04137 // Author     : Jane HU 
04138 // Date       : 06/08
04139 //===============================================================================
04140 CubitStatus OCCModifyEngine::imprint( DLIList<Surface*>& surface_list,
04141                                    DLIList<DLIList<Curve*>*>& curve_lists_list,
04142                                    BodySM*& new_body,
04143                                    bool keep_old,
04144                                    bool expand,
04145                                    DLIList<TopologyBridge*> *new_tbs,
04146                                    DLIList<TopologyBridge*> *att_tbs  ) const
04147 {
04148   DLIList<TopoDS_Face*> face_list;
04149   DLIList<TopoDS_Shape*> shape_list;
04150   DLIList<TopoDS_Shape*> shape_list_all;
04151   DLIList<OCCSurface*> surfaces;
04152   DLIList<OCCCurve*> curves;
04153   DLIList<OCCPoint*> points;
04154  
04155   assert (surface_list.size() == curve_lists_list.size());
04156   DLIList<OCCBody*> bodies;
04157 
04158   std::map<OCCSurface*, std::pair<CubitVector, double> > surf_property_map;
04159   std::map<OCCCurve*, std::pair<CubitVector, double> > curve_property_map;
04160 
04161   for(int j = 0; j < surface_list.size(); j++)
04162   {
04163     Surface* surface = surface_list.get_and_step();
04164     
04165     //keep record of old bodies, surfaces, curves and points
04166     OCCSurface* occ_surface = CAST_TO(surface, OCCSurface);
04167     occ_surface->get_bodies(bodies);
04168     if(j == 0)
04169     {
04170       bodies.get()->get_all_surfaces(surfaces);
04171       bodies.get()->get_all_curves(curves);
04172       bodies.get()->get_all_points(points);
04173  
04174       //save surface with its area and center info in the map
04175       for(int i = 0; i < surfaces.size(); i++)
04176       {
04177         OCCSurface* surf = CAST_TO(surfaces.get(), OCCSurface);
04178         double d = surf->measure();
04179         CubitVector center = surf->center_point();
04180         surf_property_map.insert(valType
04181              (surf, std::pair<CubitVector, double>(center,d)));
04182       }
04183 
04184       //save curve with its length and center info in the map
04185       for(int i = 0; i < curves.size(); i++)
04186       {
04187         OCCCurve* curve = CAST_TO(curves.get(), OCCCurve);
04188         double d = curve->measure();
04189         CubitVector center = curve->center_point();
04190         curve_property_map.insert(valType2
04191              (curve, std::pair<CubitVector, double>(center,d)));
04192       }
04193     }
04194     DLIList<Surface*> ref_face_list;
04195     ref_face_list.append(surface);
04196     DLIList<Curve*> *edge_list = curve_lists_list.get_and_step();
04197     face_edge_imprint(ref_face_list, *edge_list, face_list, shape_list, keep_old);
04198 
04199     for(int i = 0; i < shape_list.size(); i++)
04200     {
04201       TopoDS_Shape* shape = shape_list.get_and_step();
04202       shape_list_all.append_unique(shape);
04203     }
04204     shape_list.clean_out();
04205 
04206     if (keep_old)
04207     {
04208       for(int i = 0; i < face_list.size(); i++)
04209       {
04210         TopoDS_Face* face = face_list.get();
04211         face->Nullify();
04212         delete face;
04213         face = NULL;
04214       }
04215     }
04216 
04217     face_list.clean_out();
04218   }
04219 
04220   assert (bodies.size() == 1);
04221 
04222   DLIList<BodySM*> new_body_list;
04223   shape_to_bodySM(shape_list, new_body_list);
04224   
04225   if (new_body_list.size() == 1)
04226   {
04227     new_body = new_body_list.get();
04228     //find new_tbs and att_tbs;
04229     DLIList<OCCSurface*> new_surfs;
04230     DLIList<OCCCurve*> new_curves;
04231     DLIList<OCCPoint*> new_points;
04232     if(new_tbs || att_tbs) 
04233     {
04234       OCCBody* occ_body = CAST_TO(new_body, OCCBody);
04235       occ_body->get_all_surfaces(new_surfs);
04236       occ_body->get_all_curves(new_curves);
04237       occ_body->get_all_points(new_points);
04238     } 
04239     if(new_tbs)
04240       get_new_tbs(surf_property_map, curve_property_map, points, new_surfs, 
04241                   new_curves, new_points, new_tbs);
04242     if(att_tbs)
04243       get_att_tbs(new_surfs, new_curves, new_points, "COMPOSITE_GEOM",
04244                   att_tbs);
04245 
04246     return CUBIT_SUCCESS;
04247   }
04248   return CUBIT_FAILURE;
04249 }
04250 
04251 //===============================================================================
04252 // Function   : shape_to_bodySM
04253 // Member Type: PRIVATE
04254 // Description: After imprint, update shape list to bodySM_list
04255 // Author     : Jane Hu
04256 // Date       : 06/08
04257 //===============================================================================
04258 void OCCModifyEngine::shape_to_bodySM( DLIList<TopoDS_Shape*> shape_list,
04259                                        DLIList<BodySM*>& new_body_list)const
04260 {
04261   for(int j = 0; j < shape_list.size(); j ++)
04262   {
04263     DLIList<TopologyBridge*> tbs;
04264     TopoDS_Shape* shape = shape_list.get_and_step();
04265     if (shape->ShapeType() == TopAbs_COMPOUND)
04266     {
04267       if(!OCCQueryEngine::instance()->OCCMap->IsBound(*shape))
04268       {
04269         TopExp_Explorer Ex;
04270         for (Ex.Init(*shape, TopAbs_SOLID);Ex.More(); Ex.Next())
04271         {
04272           TopoDS_Shape subshape = Ex.Current();
04273           tbs += OCCQueryEngine::instance()->populate_topology_bridge(subshape);
04274           new_body_list.append_unique(CAST_TO(tbs.get(),BodySM));
04275         }
04276       }
04277     }
04278     else
04279     {
04280       tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape);
04281       BodySM* body = CAST_TO(tbs.get(),BodySM);
04282       if(body != NULL)
04283         new_body_list.append_unique(body);
04284     }
04285   }
04286 }
04287 
04288 //===============================================================================
04289 // Function   : imprint
04290 // Member Type: PUBLIC
04291 // Description: Imprints locations to bodies (for splitting curves, there's
04292 //              no known ways to put hard points on surfaces in OCC, so I just
04293 //              add free_vertex on OCCSurface definition, mesh should look on
04294 //              this structure).   
04295 // Author     : Jane Hu
04296 // Date       : 06/08
04297 //===============================================================================
04298 CubitStatus     OCCModifyEngine::imprint( DLIList<BodySM*> &body_list,
04299                                           DLIList<CubitVector> &vector_list,
04300                                           DLIList<BodySM*>& new_body_list,
04301                                           bool keep_old,
04302                                           DLIList<TopologyBridge*>* new_tbs,
04303                                           DLIList<TopologyBridge*>* att_tbs,
04304                                           double *tol_in ,
04305                                           bool clean_up_slivers ) const
04306 {
04307   DLIList<TopoDS_Shape*> shape_list;
04308   DLIList<CubitBoolean> is_vo;
04309   double tol = 0.1;
04310   if(tol_in)
04311     tol = *tol_in;
04312   CubitStatus stat = get_shape_list(body_list, shape_list, is_vo, keep_old);
04313   if(!stat)
04314     return stat;
04315 
04316   for (int i = 0; i < body_list.size(); i++)
04317   {
04318     OCCBody* body = CAST_TO(body_list.get_and_step(), OCCBody);
04319     TopoDS_Shape* from_shape = shape_list.get();
04320     if (!body)
04321       continue;
04322     DLIList<OCCSurface*> surfaces;
04323     DLIList<OCCCurve*> curves;
04324 
04325     body->get_all_surfaces(surfaces);
04326     body->get_all_curves(curves);
04327     
04328     CubitBoolean on_vertex = CUBIT_FALSE;
04329     CubitBoolean on_curve = CUBIT_FALSE;
04330     for (int j = 0; j < vector_list.size(); j ++)
04331     {
04332       CubitVector& v = vector_list[j];
04333       for (int k = 0;  k < curves.size(); k ++)
04334       {
04335          OCCCurve* curve = curves.get_and_step();
04336          CubitPointContainment pc = curve->point_containment(v);
04337          if(pc == CUBIT_PNT_BOUNDARY)
04338          {
04339            on_vertex = CUBIT_TRUE;
04340            break;
04341          }
04342 
04343          else if( pc == CUBIT_PNT_INSIDE)
04344          {
04345            on_curve = CUBIT_TRUE;
04346            //first make sure it won't generate a sliver curve
04347            //with respect to tol.
04348            if(clean_up_slivers)
04349            {
04350              double u = curve->u_from_position(v);
04351              double u_min, u_max;
04352              curve->get_param_range(u_min, u_max);
04353              double l1 = curve->length_from_u(u_min, u);
04354              double l2 = curve->measure() - l1;
04355              if(l1 <= tol || l2 <= tol)
04356                break;
04357            }
04358 
04359            const CubitVector location = v;
04360            DLIList<Curve*> created_curves;
04361            stat = split_shape_by_location(from_shape, (Curve*)curve, location, 
04362                                           created_curves);
04363            shape_list.change_to(from_shape);
04364            if(new_tbs)
04365              for(int ic=0; ic < created_curves.size(); ic++)
04366                new_tbs->append(created_curves.get_and_step());
04367 
04368            curves.remove(curve);
04369            for(int ic = 0; ic < created_curves.size(); ic++)
04370              curves.append(CAST_TO(created_curves.get_and_step(), OCCCurve));
04371            break;
04372          }  
04373        } 
04374        if(on_vertex || on_curve)
04375          continue;
04376 
04377        //check possible on surface
04378        for(int n = 0; n < surfaces.size(); n ++)
04379        {
04380           OCCSurface* surface = surfaces.get_and_step();
04381           if(!surface->is_position_on(v))
04382             continue;
04383            
04384           CubitPointContainment ps = surface->point_containment(v);
04385           if(ps == CUBIT_PNT_INSIDE)
04386           {
04387              TBPoint* p = make_Point(v);
04388              if(p)
04389              {
04390                surface->add_hardpoint(CAST_TO(p, OCCPoint));
04391                if(new_tbs)
04392                  new_tbs->append(p);
04393              }
04394              break;
04395           }
04396        }
04397     }
04398     shape_list.step();
04399   }       
04400 
04401   shape_to_bodySM(shape_list, new_body_list);
04402   
04403   DLIList<OCCSurface*> surfaces;
04404   DLIList<OCCCurve*>   curves;
04405   DLIList<OCCPoint*>   points;
04406   for (int i = 0; i < new_body_list.size(); i++)
04407   {
04408     OCCBody * body = CAST_TO(new_body_list.get_and_step(), OCCBody);
04409     body->get_all_surfaces(surfaces);
04410     body->get_all_curves(curves);
04411     body->get_all_points(points);
04412   }
04413 
04414   get_att_tbs(surfaces, curves, points, "COMPOSITE_GEOM", att_tbs);
04415 
04416   return stat;
04417 }
04418 
04419 
04420 //===============================================================================
04421 // Function   : imprint_projected_edges
04422 // Member Type: PUBLIC
04423 // Description: Projects a list of Curves on to a list of Surfaces
04424 //              and imprint the faces with the new Curves
04425 // Author     : Jane Hu
04426 // Date       : 06/08
04427 //===============================================================================
04428 CubitStatus     
04429 OCCModifyEngine::imprint_projected_edges( DLIList<Surface*> &ref_face_list,
04430                                           DLIList<Curve*> &ref_edge_list,
04431                                           DLIList<BodySM*>& new_body_list,
04432                                           DLIList<Curve*>& kept_free_edges,
04433                                           bool keep_old_body,
04434                                           bool keep_free_edges) const
04435 {
04436   DLIList<Curve*> projected_curves;
04437   CubitStatus 
04438      stat = project_edges(ref_face_list, ref_edge_list, projected_curves);
04439   if(!stat)
04440     return stat;
04441 
04442   // imprint Surface with curves
04443   DLIList<TopologyBridge*> temp_bridges;
04444   stat = imprint(ref_face_list, projected_curves, temp_bridges, new_body_list, keep_old_body );
04445 
04446   if(keep_free_edges)
04447   {
04448      kept_free_edges += projected_curves;
04449      return  stat;
04450   }
04451 
04452   PRINT_INFO( "Removing projected curves \n");
04453   for(int i=0; i< projected_curves.size();i++)
04454   {
04455     // Now delete this Curve and its underlying solid model entities
04456 
04457     Curve* curve = projected_curves.get_and_step();
04458     stat = OCCQueryEngine::instance()->delete_solid_model_entities( curve );
04459     if (stat == CUBIT_FAILURE)
04460     {
04461        PRINT_ERROR("In OCCQueryEngine::delete_geometry\n"
04462                  "       Could not delete OCCCurve.\n"
04463                  "       The Model database is likely corrupted "
04464                  "due to\n       this unsuccessful deletion.\n" );
04465     }
04466   } 
04467   return stat;
04468 }
04469 //===============================================================================
04470 // Function   : project_edges
04471 // Member Type: PUBLIC
04472 // Description: Projects a list of Curves on to a list of Surfaces
04473 // Author     : Jane Hu
04474 // Date       : 06/08
04475 //===============================================================================
04476 CubitStatus OCCModifyEngine::project_edges( DLIList<Surface*> &ref_face_list,
04477                                             DLIList<Curve*> &ref_edge_list,
04478                                             DLIList<Curve*> &projected_curves,
04479                                             bool print_error ) const
04480 
04481 {
04482   CubitVector* v = NULL;
04483   Curve* projected_curve = NULL;
04484   DLIList<TBPoint*> points;
04485   //project curves onto surfaces.
04486   for(int i = 0; i < ref_edge_list.size(); i++)
04487   {
04488     OCCCurve* curve = CAST_TO(ref_edge_list.get_and_step(), OCCCurve);
04489     if(!curve)
04490        continue;
04491 
04492     for (int j = 0; j < ref_face_list.size(); j++)
04493     {
04494       OCCSurface* surface = CAST_TO(ref_face_list.get_and_step(), OCCSurface); 
04495       if(!surface)
04496         continue;
04497       if(surface->is_closed_in_U() || surface->is_closed_in_V())
04498       {
04499         if(print_error)
04500           PRINT_ERROR("This function can't project curves on closed surfaces.\n");
04501         return CUBIT_FAILURE;
04502       }
04503       
04504       projected_curve = NULL;
04505       projected_curve = curve->project_curve(surface, points, CUBIT_FALSE, v);
04506       if(projected_curve)
04507         projected_curves.append_unique(projected_curve);
04508     }
04509   }
04510   while(points.size() > 0)
04511     delete points.pop();
04512   return CUBIT_SUCCESS;
04513 }
04514 
04515 //===============================================================================
04516 // Function   : imprint_projected_edges
04517 // Member Type: PUBLIC
04518 // Description: Projects a list of curves on to a list of surfaces
04519 //              and imprint the bodies with the new curves
04520 // Author     : Jane Hu
04521 // Date       : 06/08
04522 //===============================================================================
04523 CubitStatus 
04524 OCCModifyEngine::imprint_projected_edges(DLIList<Surface*> &ref_face_list,
04525                                          DLIList<BodySM*> &body_list,
04526                                          DLIList<Curve*> &ref_edge_list,
04527                                          DLIList<BodySM*>& new_body_list,
04528                                          bool keep_old,
04529                                          bool keep_free_edges) const
04530 {
04531   DLIList<Curve*> projected_curves;
04532   CubitStatus
04533      stat = project_edges(ref_face_list, ref_edge_list, projected_curves);
04534   if(!stat)
04535     return stat; 
04536   return CUBIT_FAILURE;
04537 
04538   // imprint bodies with curves
04539   DLIList<TopologyBridge*> temp_bridges;
04540   stat = imprint(body_list,projected_curves, new_body_list, temp_bridges, keep_old);
04541 
04542   if (keep_free_edges)
04543         return  stat;
04544 
04545   PRINT_INFO( "Removing projected curves \n");
04546   for(int i=0; i< projected_curves.size();i++)
04547   {
04548     // Now delete this Curve 
04549     Curve* curve = projected_curves.get_and_step();
04550     stat = OCCQueryEngine::instance()->
04551           delete_solid_model_entities( curve );
04552     if (stat == CUBIT_FAILURE)
04553     {
04554        PRINT_ERROR("In OCCModifyEngine::delete_geometry\n"
04555                    "       Could not delete Curve.\n"
04556                    "       The Model database is likely corrupted "
04557                    "due to\n       this unsuccessful deletion.\n" );
04558     }
04559   }
04560   return stat; 
04561 }
04562 
04563 //===============================================================================
04564 // Function   : intersect
04565 // Member Type: PUBLIC
04566 // Description: intersect boolean operation of body with list of bodies.
04567 // Author     : Jane Hu
04568 // Date       : 06/08
04569 //===============================================================================
04570 CubitStatus OCCModifyEngine::intersect(BodySM*  tool_body_ptr,
04571                                        DLIList<BodySM*>  &from_bodies,
04572                                        DLIList<BodySM*>  &new_bodies,
04573                                        bool  keep_old,
04574                                        bool preview) const
04575 {
04576   DLIList<BodySM*> tool_bodies;
04577   DLIList<TopoDS_Shape*> tool_shapes;
04578   DLIList<CubitBoolean> is_tool_volume, is_volume;
04579   
04580   tool_bodies.append(tool_body_ptr);
04581   //get tool_body's underlying shape, copy it, so boolean wouldn't touch it.
04582   CubitStatus stat = 
04583        get_shape_list(tool_bodies, tool_shapes, is_tool_volume, CUBIT_TRUE); 
04584   if(!stat)
04585     return stat;
04586 
04587   DLIList<TopoDS_Shape*> shape_list;
04588   stat =  get_shape_list(from_bodies, shape_list, is_volume, keep_old);
04589   if(!stat)
04590   {
04591     for (int i = 0; i < tool_shapes.size(); i++)
04592     {
04593        TopoDS_Shape* shape = tool_shapes.get_and_step();
04594        delete shape;
04595        shape = NULL; 
04596     }
04597     tool_shapes.clean_out();
04598     return CUBIT_FAILURE;
04599   }
04600 
04601   TopoDS_Shape* tool_shape = tool_shapes.get();
04602   CubitBoolean has_changed;
04603   DLIList<TopologyBridge*> tbs;
04604   DLIList<TopoDS_Shape*> preview_list;
04605   for (int i = 0; i < shape_list.size(); i++)
04606   { 
04607     TopoDS_Shape* from_shape = shape_list.get_and_step();
04608     BodySM* from_body = from_bodies.get_and_step();
04609     BRepAlgoAPI_Common intersector(*from_shape, *tool_shape);
04610 
04611     TopTools_ListOfShape shapes;
04612     shapes.Assign(intersector.Modified(*tool_shape));
04613     
04614     if ( shapes.Extent() > 1)
04615     {
04616       PRINT_ERROR("Tool has multiple intersection with the shape, make it simpler. \n");
04617       continue;
04618     }
04619     TopoDS_Shape common_shape;
04620     if (shapes.IsEmpty())
04621       common_shape = intersector.Shape();
04622     else 
04623       common_shape = shapes.First();
04624 
04625     if (!common_shape.IsNull())
04626     {
04627       TopExp_Explorer Ex(common_shape, TopAbs_SOLID);
04628       if(!Ex.More() && is_volume[i] == CUBIT_TRUE && 
04629          common_shape.ShapeType() > TopAbs_SOLID)
04630       {
04631         has_changed = CUBIT_TRUE;
04632         *from_shape = common_shape;
04633       }
04634       
04635       else if (is_volume[i] == CUBIT_FALSE && 
04636                common_shape.ShapeType() > TopAbs_FACE) 
04637       {
04638         Ex.Init(common_shape, TopAbs_SHELL, TopAbs_SOLID);
04639         if(!Ex.More())
04640           Ex.Init(common_shape, TopAbs_FACE);
04641         if(!Ex.More() && is_volume[i] == CUBIT_FALSE)
04642         {
04643           has_changed = CUBIT_TRUE;
04644           *from_shape = common_shape;
04645         }
04646       }
04647       else
04648       {
04649         double after_mass = 0.0;
04650         GProp_GProps myProps;
04651         if(is_volume[i])
04652           BRepGProp::VolumeProperties(common_shape, myProps);
04653         
04654         else
04655           BRepGProp::SurfaceProperties(common_shape, myProps);
04656         after_mass = myProps.Mass();
04657         if(after_mass > TOL)
04658           check_operation(common_shape, from_shape, is_volume[i], has_changed,
04659                     &intersector, keep_old);
04660         else
04661         {
04662           if(!keep_old)
04663             OCCQueryEngine::instance()->delete_solid_model_entities(from_body); 
04664           from_shape = NULL;
04665         }
04666       }
04667     }
04668 
04669     if(from_shape == NULL || from_shape->IsNull() )
04670     {
04671       PRINT_INFO("The %d body did not have common part with the tool_body.\n", i+1);
04672     }
04673     else
04674     {
04675       if(preview)
04676       {
04677         TopoDS_Shape* p_shape = new TopoDS_Shape(common_shape);
04678         preview_list.append(p_shape);
04679       }
04680       else
04681         tbs += OCCQueryEngine::instance()->populate_topology_bridge(*from_shape);
04682     }
04683   }
04684 
04685   if(preview)
04686   {
04687     GfxPreview::clear();
04688     for(int i = 0; i < preview_list.size(); i++)
04689     {
04690       TopoDS_Shape* new_shape = preview_list.get_and_step();
04691       // Draw this face
04692       OCCDrawTool::instance()->draw_TopoDS_Shape( new_shape, CUBIT_BLUE_INDEX,
04693                                                   CUBIT_FALSE, CUBIT_TRUE );
04694       delete new_shape;
04695     }
04696   }
04697   
04698   for (int i = 0; i< tbs.size(); i++)
04699   {
04700     BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM);
04701     if (bodysm)
04702       new_bodies.append(bodysm);
04703   }
04704   
04705   //if(tbs.size() == 0)
04706   //  stat = CUBIT_FAILURE;
04707     
04708   //ok, we're done with all cuts, delete unnecessaries.
04709   if(!keep_old)
04710     OCCQueryEngine::instance()->delete_solid_model_entities(tool_body_ptr);   
04711 
04712   for(int i = 0; i < tool_shapes.size(); i++)
04713   {
04714     TopoDS_Shape* shape = tool_shapes.get_and_step();
04715     shape->Nullify();
04716     delete shape;
04717     shape = NULL;
04718   }
04719 
04720   if(keep_old)
04721   {
04722     int size  = shape_list.size();
04723     for (int i = 0; i < size; i++)
04724     {
04725       TopoDS_Shape* shape = shape_list.pop();
04726       shape->Nullify();
04727       delete shape;
04728       shape = NULL;
04729     }
04730   }
04731   if(!stat)
04732     return stat;
04733   return CUBIT_SUCCESS;
04734 }
04735 
04736 //===============================================================================
04737 // Function   : check_operation
04738 // Member Type: PRIVATE
04739 // Description: check and update the from_shape according to type of the body.
04740 // Author     : Jane Hu
04741 // Date       : 06/08
04742 //===============================================================================
04743 void OCCModifyEngine::check_operation(TopoDS_Shape& cut_shape,
04744                                       TopoDS_Shape*& from_shape, //output
04745                                       CubitBoolean  is_volume,
04746                                       CubitBoolean& has_changed, //output
04747                                       BRepAlgoAPI_BooleanOperation* op,
04748                                       CubitBoolean keep_old) const
04749 {
04750    //compare to see if the from_shape has gotten cut.
04751    if(is_volume)
04752    {
04753      GProp_GProps myProps;
04754      BRepGProp::VolumeProperties(*from_shape, myProps);
04755      double orig_mass = myProps.Mass();
04756      TopTools_IndexedMapOfShape M;
04757      TopExp::MapShapes(cut_shape, TopAbs_SOLID, M);
04758      double after_mass = 0.0;
04759      CubitBoolean no_volume = CUBIT_FALSE;
04760      if(M.Extent() > 0)
04761      {
04762        BRepGProp::VolumeProperties(cut_shape, myProps);
04763        after_mass = myProps.Mass();
04764      }
04765      else
04766        no_volume = CUBIT_TRUE;
04767  
04768      if(fabs(-after_mass + orig_mass) <= TOL)
04769      {
04770         has_changed= CUBIT_FALSE; //common is itself
04771         return;
04772      }
04773 
04774      //got cut. Update the entities
04775      if(after_mass < TOL || no_volume) //no common section
04776        cut_shape.Nullify();
04777      has_changed = CUBIT_TRUE;
04778      TopExp_Explorer Ex;
04779      int num_solid = 0;
04780      Ex.Init(*from_shape, TopAbs_SOLID);
04781      TopoDS_Solid old_solid;
04782      for(; Ex.More(); Ex.Next())
04783      {
04784        num_solid ++;
04785        old_solid = TopoDS::Solid(Ex.Current());
04786      }
04787      if(num_solid == 1)
04788        OCCLump::update_OCC_entity(old_solid , cut_shape, op);
04789      
04790      else if(num_solid > 1)
04791        OCCBody::update_OCC_entity(*from_shape, cut_shape, op);
04792    }
04793    else
04794    {
04795      GProp_GProps myProps;
04796      BRepGProp::SurfaceProperties(*from_shape, myProps);
04797      double orig_mass = myProps.Mass();
04798      BRepGProp::SurfaceProperties(cut_shape, myProps);
04799      double after_mass = myProps.Mass();
04800      if(fabs(-after_mass + orig_mass) <= TOL)
04801      {
04802        has_changed= CUBIT_FALSE; //common is itself, or not cut
04803        return;
04804      }
04805      //got cut. Update the entities
04806      if(after_mass < TOL)//no common section
04807        cut_shape.Nullify();
04808      has_changed = CUBIT_TRUE;
04809      if(from_shape->ShapeType() == TopAbs_SHELL)
04810      {
04811        TopoDS_Shell old_shell = TopoDS::Shell(*from_shape);
04812        OCCShell::update_OCC_entity(old_shell,cut_shape, op);
04813      }
04814      else
04815      {
04816        TopoDS_Face old_face = TopoDS::Face(*from_shape);
04817        OCCSurface::update_OCC_entity(old_face,cut_shape, op);
04818      }
04819   }
04820 //  if(keep_old) - Must not be deleted, causes random failure on OSX
04821 //    delete from_shape;
04822   from_shape = new TopoDS_Shape(cut_shape);
04823 }
04824 
04825 //===============================================================================
04826 // Function   : chop
04827 // Member Type: PUBLIC
04828 // Description: chop boolean operation between OCC-based bodies
04829 //              bodies has a size() = 2, a blank body and a tool body.
04830 //              chops the blank with the  tool, returing the body formed
04831 //              by subtracting the tool from the blank, and the body formed
04832 //              by intersecting the tool with the blank, simultaneously.
04833 // Author     : Jane Hu
04834 // Date       : 06/08
04835 //===============================================================================
04836 CubitStatus  OCCModifyEngine::chop(DLIList<BodySM*>& bodies, 
04837                                    DLIList<BodySM*> &intersectBodies, 
04838                                    DLIList<BodySM*> &outsideBodies,
04839                                    BodySM*& leftoversBody,
04840                                    bool keep_old ,
04841                                    bool nonreg) const
04842 {
04843   //according to  chop function, leftoverBody = 0;
04844   leftoversBody = 0;
04845 
04846   //there's no effect of nonreg. keep_old mean if to keep the tool_body
04847   if(bodies.size() != 2)
04848   {
04849     PRINT_WARNING("Chop operation works only on two bodies. Nothing modified\n");  
04850     return CUBIT_FAILURE; 
04851   }
04852   
04853   //outsideBodies keeps the surface, curve ids if keep_old is false.
04854   BodySM* blank_body = bodies.get();
04855   
04856   //copy blank_body for intersect operation, because it will get changed.
04857   DLIList<BodySM*> tool_bodies, from_bodies;
04858   from_bodies.append(blank_body);
04859   BodySM* tool_body = bodies.step_and_get();
04860   tool_bodies.append(tool_body);
04861   
04862   CubitStatus stat = intersect(tool_body, from_bodies, 
04863                                intersectBodies, CUBIT_TRUE);
04864 
04865   if(!stat)
04866     return CUBIT_FAILURE;
04867 
04868   stat = subtract(tool_bodies, from_bodies, outsideBodies, 
04869                   CUBIT_FALSE, keep_old);
04870   
04871   return stat;
04872 }
04873 
04874 //===============================================================================
04875 // Function   : unite
04876 // Member Type: PUBLIC
04877 // Description: unite boolean operation between OCC-based bodies
04878 // Author     : Jane Hu
04879 // Date       : 06/08
04880 //===============================================================================
04881 CubitStatus     OCCModifyEngine::unite(DLIList<BodySM*> &bodies, 
04882                                        DLIList<BodySM*> &newBodies,
04883                                        bool keep_old) const
04884 {
04885   if(bodies.size() < 2)
04886   {
04887     newBodies = bodies;
04888     return CUBIT_SUCCESS;
04889   }
04890 
04891   //In order to distinguish bodies who are not intersecting each other to 
04892   //avoid doing the boolean, check the minimum distance of the bodies first.
04893   DLIList<BodySM*> revised_bodies;
04894   DLIList<BodySM*> overlaped_bodies;
04895   DLIList<TopoDS_Shape*> overlap_shapes;
04896   DLIList<TopoDS_Shape*> shape_list;
04897   DLIList<TopoDS_Shape*> revised_shapes;
04898   DLIList<CubitBoolean> is_volume;
04899   CubitStatus stat =
04900         get_shape_list(bodies, shape_list, is_volume, keep_old); 
04901 
04902   if( !stat )
04903     return CUBIT_FAILURE;
04904 
04905   while(bodies.size() > 0)
04906   {
04907     TopoDS_Shape *shape1 = shape_list.pop();
04908     BodySM* first_body = bodies.pop();
04909     CubitBoolean intersect = false; 
04910     shape_list.reset();
04911     int size = shape_list.size();
04912 
04913     overlaped_bodies.clean_out();
04914     overlap_shapes.clean_out();
04915     for (int k = 0 ; k < size; k++)
04916     {
04917       TopoDS_Shape *shape2 = shape_list.get();
04918       BodySM* sec_body = bodies.get();
04919       BRepExtrema_DistShapeShape dist(*shape1, *shape2);
04920       //dist.Perform();
04921       if(dist.IsDone() && dist.Value() < TOL)
04922       {
04923         overlaped_bodies.append(sec_body);
04924         overlap_shapes.append(shape2);
04925         bodies.change_to(NULL);
04926         shape_list.change_to(NULL);
04927         intersect = true;
04928       }
04929       bodies.step();
04930       shape_list.step();
04931     }
04932     bodies.remove_all_with_value(NULL);
04933     shape_list.remove_all_with_value(NULL);
04934     if (intersect != true)
04935     {
04936       revised_bodies.append(first_body);
04937       revised_shapes.append(shape1);
04938     }
04939     else
04940     {
04941       overlaped_bodies.append(first_body);
04942       overlap_shapes.append(shape1); 
04943 
04944       //find a non-sheet body to be the first shape
04945       TopoDS_Shape* first_shape;
04946       TopoDS_Shape* second_shape;
04947       CubitBoolean first_is_volume = false;
04948       for(int i = 0; i < overlap_shapes.size(); i++)
04949       {
04950         
04951         first_shape = overlap_shapes.get();
04952         if(first_shape->ShapeType() < TopAbs_SHELL)
04953         {
04954           first_is_volume = true;
04955           break;
04956         }
04957         overlap_shapes.step();
04958         overlaped_bodies.step();
04959       }
04960       overlap_shapes.remove(first_shape);
04961       BodySM* body1 = overlaped_bodies.remove();
04962       BodySM* body2 = NULL;
04963       overlap_shapes.reset();
04964       overlaped_bodies.reset();
04965       for(int i = 0; i < overlap_shapes.size(); i++)
04966       {
04967         second_shape = overlap_shapes.get_and_step();
04968         body2 = overlaped_bodies.get_and_step(); 
04969         BRepAlgoAPI_Fuse fuser(*first_shape, *second_shape);
04970         TopoDS_Shape new_shape = fuser.Shape();
04971 
04972         CubitBoolean has_changed;
04973         TopTools_IndexedMapOfShape M1, M2, M_new;
04974         TopExp::MapShapes(*first_shape, TopAbs_SOLID, M1); 
04975         TopExp::MapShapes(*second_shape, TopAbs_SOLID, M2);
04976         TopExp::MapShapes(new_shape, TopAbs_SOLID, M_new);
04977         if(M_new.Extent() == 1 && M1.Extent() > 1 && M2.Extent() == 1)
04978         {
04979           check_operation(new_shape,second_shape, is_volume[i], has_changed, &fuser, keep_old);
04980           check_operation(new_shape, first_shape, first_is_volume, has_changed, &fuser, keep_old);
04981         }
04982  
04983         else if(M_new.Extent() == 1 && M1.Extent() > 1 && M2.Extent() > 1)
04984         //two compound bodies unite into one solid lump body
04985         {
04986           OCCQueryEngine::instance()->copy_attributes(*first_shape, new_shape);
04987           OCCQueryEngine::instance()->copy_attributes(*second_shape, new_shape);
04988           first_shape = new TopoDS_Shape(new_shape);
04989           OCCQueryEngine::instance()->delete_solid_model_entities(body1);
04990           OCCQueryEngine::instance()->delete_solid_model_entities(body2);
04991         } 
04992         else
04993         {
04994           check_operation(new_shape, first_shape, first_is_volume, has_changed, &fuser, keep_old);
04995 
04996           check_operation(new_shape,second_shape, is_volume[i], has_changed, &fuser, keep_old);
04997         }
04998       }
04999       //ok, we're done with all unites, construct new Body'
05000       DLIList<TopologyBridge*> tbs;
05001       tbs += OCCQueryEngine::instance()->populate_topology_bridge(*first_shape);
05002 
05003       BodySM* bodysm = CAST_TO(tbs.get(), BodySM);
05004       if (bodysm)
05005       {
05006         CAST_TO(bodysm, OCCBody)->get_TopoDS_Shape(first_shape);
05007         revised_bodies.append(bodysm);
05008         revised_shapes.append(first_shape);
05009       }
05010     } 
05011   }
05012 
05013   if (revised_bodies.size() > 1)
05014   {
05015     revised_shapes.clean_out();
05016     is_volume.clean_out();
05017     stat =
05018         get_shape_list(revised_bodies, revised_shapes, is_volume, true);
05019 
05020     //simply make all bodies into a compound
05021     TopoDS_Compound Co ;
05022     BRep_Builder B;
05023     B.MakeCompound(Co);
05024     for(int i = 0; i < revised_shapes.size(); i++)
05025       B.Add(Co, *revised_shapes.get_and_step());
05026 
05027     BodySM* body = OCCQueryEngine::instance()->populate_topology_bridge(Co);
05028     if(body)
05029       newBodies.append(body);
05030 
05031     //delete all other individial bodies
05032     if(keep_old == false)
05033       for(int i = 0; i < revised_bodies.size(); i++)
05034         OCCQueryEngine::instance()->
05035           delete_solid_model_entities(revised_bodies.get_and_step());
05036     revised_bodies.clean_out();
05037   }
05038 
05039   else if(revised_bodies.size() == 1)
05040     newBodies = revised_bodies;
05041   return CUBIT_SUCCESS; 
05042 }
05043 
05044 CubitStatus OCCModifyEngine::thicken( DLIList<BodySM*>& bodies,
05045                                       DLIList<BodySM*>& new_bodies,
05046                                       double depth,
05047                                       CubitBoolean both) const
05048 {
05049   PRINT_ERROR("Option not supported for OCC based geometry.\n");
05050   return CUBIT_FAILURE;
05051 }
05052 
05053 //===============================================================================
05054 // Function   : hollow
05055 // Member Type: PUBLIC
05056 // Description: Hollow existing solid body by remove one or several surfaces 
05057 //              Can only take one body at a time.
05058 //              depth > 0, thick body going outside bodies
05059 //              depth < 0, thick body going inside bodies
05060 // Author     : Jane Hu 
05061 // Date       : 06/08
05062 //===============================================================================
05063 CubitStatus OCCModifyEngine::hollow( DLIList<BodySM*>& bodies, 
05064                                      DLIList<Surface*>& surfs_to_remove,
05065                                      DLIList<BodySM*>& new_bodies,
05066                                      double depth) const
05067 {
05068   if(bodies.size() != 1 || surfs_to_remove.size() < 1)
05069   {
05070     PRINT_ERROR("Making thick solid in OCC will take one body and at least one surface at a time.\n"); 
05071     return CUBIT_FAILURE;
05072   }
05073 
05074   DLIList<TopoDS_Shape*> shape_list;
05075   DLIList<CubitBoolean> is_volume;
05076   CubitStatus stat = get_shape_list(bodies, shape_list, is_volume, CUBIT_FALSE);
05077 
05078   if(!stat)
05079     return stat;
05080 
05081   if(!is_volume.get())//sheet body
05082   {
05083     PRINT_ERROR("Making thick solid in OCC needs an initial solid body to hollow with.\n");
05084     return CUBIT_FAILURE;
05085   }
05086 
05087   //make sure the body to be hollowed has only one lump
05088   OCCBody* occ_body = CAST_TO(bodies.get(), OCCBody);
05089   DLIList<Lump*> lumps;
05090   DLIList<OCCSurface*> surfaces;
05091   DLIList<OCCShell*> shells;
05092   surfaces = occ_body->my_sheet_surfaces();
05093   shells = occ_body->shells();
05094   lumps = occ_body->lumps();
05095   if(lumps.size()!=1 || surfaces.size() != 0 || shells.size() != 0)
05096   {
05097     PRINT_ERROR("bodies with more than one lump can't be hollowed to make a thick body.\n");
05098     return CUBIT_FAILURE;
05099   }
05100 
05101   //make sure surfs_to_remove are all in bodies
05102   TopTools_ListOfShape face_shapes;
05103   occ_body->get_all_surfaces(surfaces);
05104   for(int i = 0; i < surfs_to_remove.size(); i++)
05105   {
05106     OCCSurface* occ_surf = CAST_TO(surfs_to_remove.get(), OCCSurface);
05107     if(!occ_surf)
05108       continue;
05109     if(!surfaces.is_in_list(occ_surf))
05110       continue;
05111     TopoDS_Face * face = occ_surf->get_TopoDS_Face();
05112     face_shapes.Append(*face); 
05113   }
05114 
05115   if(face_shapes.IsEmpty())
05116   {
05117     PRINT_ERROR("The surfaces provided should be from the body to be hollowed.\n");
05118     return CUBIT_FAILURE;
05119   }
05120   
05121   double dTOL = 1.e-3; //hard coded for now, can be changed by application
05122   TopoDS_Shape* solid = shape_list.get();
05123   BRepOffsetAPI_MakeThickSolid hollower(*solid, face_shapes, depth, dTOL,
05124                                         BRepOffset_Skin, Standard_False,
05125                                         Standard_False, GeomAbs_Intersection);
05126   TopoDS_Shape new_shape = hollower.Shape();
05127   if(solid->ShapeType() == TopAbs_SOLID)
05128   {
05129     TopoDS_Solid old_solid = TopoDS::Solid(*solid);
05130     OCCLump::update_OCC_entity(old_solid , new_shape, &hollower); 
05131   }
05132   else if(solid->ShapeType() == TopAbs_COMPOUND)
05133     OCCBody::update_OCC_entity(*solid, new_shape, &hollower);
05134  
05135   //ok, we're done with all hollowing, construct new Body'
05136   DLIList<TopologyBridge*> tbs;
05137   tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
05138 
05139   for (int i = 0; i< tbs.size(); i++)
05140   {
05141     BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM);
05142     if (bodysm)
05143       new_bodies.append(bodysm);
05144   }
05145 
05146   return CUBIT_SUCCESS;
05147 }
05148 
05149 
05150 //===============================================================================
05151 // Function   : flip_normals
05152 // Member Type: PUBLIC
05153 // Description: 
05154 // Author     : Jane Hu
05155 // Date       : 06/08
05156 //===============================================================================
05157 CubitStatus OCCModifyEngine :: flip_normals( DLIList<Surface*>& face_list ) const
05158 {
05159   return CUBIT_FAILURE;
05160 /*
05161   DLIList<Surface*> surface_list;
05162   while (face_list.size())
05163   {
05164     OCCSurface* occ_surface = CAST_TO(face_list.pop(), OCCSurface);
05165     OCCShell* occ_shell = occ_surface->my_shell();
05166     DLIList<OCCSurface*> surfaces;
05167     surfaces.append(occ_surface);
05168     if(occ_shell) //find all surfaces in face_list that belong to this shell
05169     {
05170       int size = face_list.size();
05171       for ( int i = 0; i < size; i++)
05172       {
05173         occ_surface = CAST_TO(face_list.get(), OCCSurface); 
05174         if(occ_shell == occ_surface->my_shell())
05175           surfaces.append(CAST_TO(face_list.remove(),OCCSurface));
05176         else
05177           face_list.step();
05178       } 
05179       
05180       if (!occ_shell->is_sheet())
05181       {
05182         DLIList<OCCSurface*> memberSurfs = occ_shell->getMemberSurfaces();
05183         for (int i = 0; i < memberSurfs.size(); ++i)
05184         {
05185           occ_surface = memberSurfs.get_and_step();
05186           if(surfaces.is_in_list(occ_surface))
05187           {
05188             // would need to implement flipping the normal here
05189             surface_list.append(occ_surface);
05190           }
05191         }
05192       }
05193     }        
05194     if(!occ_shell || occ_shell->is_sheet()) //sheet body 
05195     {
05196       // would need to implement flipping the normal here
05197       surface_list.append(occ_surface);
05198       PRINT_INFO( "Modified volume\n" );
05199     }
05200   }
05201   face_list = surface_list;
05202   return CUBIT_SUCCESS;
05203 */
05204 }
05205 
05206 
05207 //===============================================================================
05208 // Function   : sweep_translational
05209 // Member Type: PUBLIC
05210 // Description: 
05211 // Author     : Jane Hu
05212 // Date       : 09/08
05213 //===============================================================================
05214 CubitStatus OCCModifyEngine::sweep_translational(
05215   DLIList<GeometryEntity*>& ref_ent_list,
05216   DLIList<BodySM*>& result_body_list,
05217   const CubitVector& sweep_vector,
05218   double draft_angle, //in Radius
05219   int draft_type, //RightCorner=1 or RoundCorner =2
05220   bool switchside,//not used, shell and surfaces are one sided, not like
05221   bool rigid, //not used here, in , it means whether the end surface is
05222               // parallel to the starting surface, or perpendicular to the path
05223   bool anchor_entity, //not used in OCC
05224   bool keep_old) const
05225 {
05226   //in OCC, there's no sweep surface with draft option, this can be done by
05227   //creating draft shell then make solid to achieve.
05228   //while if draft_angle is 0, directly use sweep functions.
05229 
05230   gp_Dir adir(sweep_vector.x(), sweep_vector.y(), sweep_vector.z());
05231   gp_Vec aVec(sweep_vector.x(), sweep_vector.y(), sweep_vector.z());
05232  
05233   for (int i = ref_ent_list.size(); i > 0; i--)
05234   {
05235     GeometryEntity *ref_ent = ref_ent_list.get_and_step();
05236     //Make copy of the surface for later to build solid.
05237     OCCSurface* surface = CAST_TO(ref_ent, OCCSurface);
05238     TopoDS_Shape toposhape ;
05239     if(surface != NULL)
05240     {
05241       CubitStatus stat = get_sweepable_toposhape(surface, &sweep_vector, toposhape);   
05242       if(!stat)
05243         continue;
05244     }
05245     OCCCurve* curve = CAST_TO(ref_ent, OCCCurve);
05246     if(curve != NULL)
05247     {
05248       CubitStatus stat = get_sweepable_toposhape(curve, toposhape);
05249       if(!stat)
05250         continue;
05251     }
05252   
05253     DLIList<TopologyBridge*> tbs;
05254     //create the draft or the sweep
05255     BodySM* bodysm = NULL;
05256     if( draft_angle == 0.)
05257     {
05258       BRepSweep_Prism swept(toposhape, aVec);
05259       TopoDS_Shape new_shape = swept.Shape();
05260 
05261       tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
05262       assert(tbs.size() == 1);
05263 
05264       bodysm = CAST_TO(tbs.get(), BodySM); 
05265     }
05266 
05267     else
05268     {
05269       BRepOffsetAPI_MakeDraft draft(toposhape, adir, draft_angle);
05270       BRepBuilderAPI_TransitionMode Cornertype;
05271       if(draft_type == 1)
05272         Cornertype = BRepBuilderAPI_RightCorner;
05273       else 
05274         Cornertype = BRepBuilderAPI_RoundCorner;
05275 
05276       draft.SetOptions(Cornertype);
05277       draft.Perform(sweep_vector.length());
05278       TopoDS_Shape new_shape = draft.Shape();
05279 
05280       tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
05281 
05282       assert(tbs.size() == 1);
05283 
05284       bodysm = CAST_TO(tbs.get(), BodySM);
05285       if(bodysm && surface != NULL) //only gets swept side and original surfaces
05286       {
05287          //get surfaces from the shell body and create a top surface to
05288          //make a swept solid.
05289          DLIList<OCCShell*> shells = CAST_TO(bodysm, OCCBody)->shells();
05290          if(shells.size() == 0)
05291          {
05292            PRINT_WARNING("Sweep surface failed inside OCC engine.\n");
05293            return CUBIT_FAILURE;
05294          }
05295          assert(shells.size() == 1);
05296          DLIList<OCCSurface*> memberSurfaces =
05297              shells.get()->getMemberSurfaces();
05298          DLIList<Surface*> surface_list;
05299          for (int i = 0; i < memberSurfaces.size(); ++i)
05300            surface_list.append(memberSurfaces.get_and_step());
05301 
05302          //create the top surface from edges.
05303          DLIList<OCCCoEdge*> coedges;
05304          for(int i = 0; i < surface_list.size(); i++)
05305            CAST_TO(surface_list.get_and_step(), OCCSurface)->get_coedges(coedges);
05306          for(int i = 0; i < coedges.size(); i++)
05307          {
05308            OCCCoEdge* coedge = coedges[i];
05309            if(coedge == NULL)
05310              continue;
05311            for(int j = i+1; j < coedges.size(); j++)
05312            {
05313               OCCCoEdge* temp_coedge = coedges[j];
05314               if(temp_coedge == NULL)
05315                 continue; 
05316               if(coedge->curve() == temp_coedge->curve()) //Since the shell 
05317               // is open, the sense of curve can be either the same or opposite. 
05318               {
05319                 coedges.move_to(coedge);
05320                 coedges.change_to((OCCCoEdge*)NULL);
05321                 coedges.move_to(temp_coedge);
05322                 coedges.change_to((OCCCoEdge*)NULL);
05323               }
05324            }
05325          } 
05326          coedges.remove_all_with_value(NULL);
05327          assert(coedges.size() > 0);
05328          DLIList<Curve*> curves;
05329          for(int i = 0; i < coedges.size(); i++)
05330            curves.append(coedges.get_and_step()->curve());
05331 
05332          Surface* surf = make_Surface(PLANE_SURFACE_TYPE, curves);
05333          if(!surf)
05334            surf = make_Surface(BEST_FIT_SURFACE_TYPE, curves);
05335          if(!surf)
05336          {
05337            PRINT_ERROR("Can't calculate for the top surface.\n");
05338            continue;
05339          }
05340          surface_list.append(surf);
05341          DLIList<BodySM*> bodies;
05342          create_solid_bodies_from_surfs(surface_list, bodies);
05343 
05344          if(bodies.size() == 1)
05345            bodysm = bodies.get();
05346          else
05347          {
05348            PRINT_WARNING("Sweep surface failed in creating solid.\n");
05349            return CUBIT_FAILURE;
05350          }
05351        }
05352     }
05353     if(bodysm && !keep_old && surface != NULL)
05354     {
05355       //have to unite the new geometry with the old one.
05356       DLIList<BodySM*> bodies;
05357       DLIList<OCCBody*> occ_bodies;
05358       surface->get_bodies(occ_bodies);
05359       if(occ_bodies.size() == 1)
05360       {
05361         OCCBody* old_body = occ_bodies.get();
05362         //delete sheet body if surface is standalong.
05363         if (old_body->is_sheet_body())
05364         {
05365           OCCQueryEngine::instance()->delete_solid_model_entities(old_body);
05366           result_body_list.append(bodysm);
05367         }
05368         else
05369         {
05370           bodies.append(CAST_TO(old_body, BodySM));
05371           bodies.append(bodysm);
05372           DLIList<BodySM*> newBodies;
05373           bool keep_old = CUBIT_FALSE;
05374           CubitStatus stat = unite(bodies, newBodies, keep_old);
05375           if(stat)
05376             result_body_list.append(newBodies.get());
05377         }
05378       }
05379     }
05380     else if (bodysm)
05381       result_body_list.append(bodysm);
05382   }
05383   return CUBIT_SUCCESS; 
05384 }
05385 
05386 CubitStatus OCCModifyEngine::get_sweepable_toposhape(OCCCurve*& curve,
05387                                               TopoDS_Shape& toposhape)const
05388 {
05389   TopoDS_Edge *edge = curve->get_TopoDS_Edge( );
05390   BRepBuilderAPI_Copy api_copy(*edge);
05391   toposhape = api_copy.ModifiedShape(*edge);
05392   TopoDS_Edge new_edge = TopoDS::Edge(toposhape);
05393   toposhape = BRepBuilderAPI_MakeWire(new_edge);
05394 
05395   return CUBIT_SUCCESS; 
05396 }
05397 
05398 CubitStatus OCCModifyEngine::get_sweepable_toposhape(OCCSurface*& surface,
05399                                                   const CubitVector* sweep_v_p,
05400                                                   TopoDS_Shape& toposhape)const
05401 {
05402   GeometryEntity* ref_ent = surface;
05403 
05404   if(surface != NULL)
05405   {
05406     //Make copy of the surface's topo_shape.
05407     TopoDS_Shape* toposhape_prt =
05408           OCCQueryEngine::instance()->get_TopoDS_Shape_of_entity(ref_ent);
05409 
05410     if(!toposhape_prt)
05411     {
05412       PRINT_WARNING("GeometryEntity without TopoDS_Shape found.\n");
05413       return CUBIT_FAILURE;
05414     }
05415 
05416     BRepBuilderAPI_Copy api_copy(*toposhape_prt);
05417     toposhape = api_copy.ModifiedShape(*toposhape_prt);
05418     if(sweep_v_p)
05419     {
05420       CubitVector center = surface->center_point();
05421       CubitVector normal;
05422       surface->closest_point(center,NULL,&normal);
05423       CubitVector sweep_vector = *sweep_v_p;
05424       // TODO: Determine where there might be need to have the normal vector
05425       // in the opposite direction if normal % sweep_vector > 0
05426       if (normal % sweep_vector == 0)
05427       {
05428         PRINT_ERROR("Sweeping direction should not be on the surface.\n");
05429         return CUBIT_FAILURE;
05430       }
05431     }
05432   }
05433   return CUBIT_SUCCESS;
05434 }
05435 //===============================================================================
05436 // Member Type: PUBLIC
05437 // Description: 
05438 // Author     : Jane Hu
05439 // Date       : 10/08
05440 //===============================================================================
05441 CubitStatus OCCModifyEngine::sweep_perpendicular(
05442   DLIList<GeometryEntity*>& ref_ent_list,
05443   DLIList<BodySM*>& result_body_list,
05444   double distance,
05445   double draft_angle,
05446   int draft_type,
05447   bool switchside, //has no effect
05448   bool rigid, //has no effect
05449   bool anchor_entity, //not used in OCC
05450   bool keep_old) const
05451 {
05452   //find the vector perpendicular to the ref_ent normal, and sweep_translate
05453   //the 'distance' along this vector
05454   DLIList<GeometryEntity*> edge_list;
05455   CubitVector vec;
05456   for(int i = 0; i < ref_ent_list.size(); i++)
05457   {
05458      GeometryEntity *ref_ent = ref_ent_list.get_and_step();
05459      Surface *face = CAST_TO(ref_ent, Surface);
05460      Curve* edge = CAST_TO(ref_ent, Curve);
05461      DLIList<GeometryEntity*> face_list;
05462      if(face != NULL)
05463      {
05464         OCCSurface* occ_face = CAST_TO(face, OCCSurface);
05465         CubitVector center = occ_face->center_point();
05466         CubitVector closest_p, unit_normal;
05467         CubitStatus stat = 
05468                     occ_face->closest_point(center, &closest_p, &unit_normal);
05469         if(stat)
05470         {
05471           vec = distance * unit_normal;
05472           face_list.append(ref_ent);
05473           stat = sweep_translational(face_list, result_body_list, vec, 
05474                                      draft_angle, draft_type, switchside,
05475                                      rigid, anchor_entity, keep_old);
05476        }
05477      }
05478      else if (edge != NULL)
05479      {
05480         edge_list.append(ref_ent);
05481      }
05482   }
05483   if(edge_list.size())
05484     PRINT_ERROR("Curves cannot be swept perpendicularly, please use the vector sweep.\n");
05485 
05486   return CUBIT_SUCCESS;
05487 }
05488 
05489 //===============================================================================
05490 // Function   : sweep_rotational
05491 // Member Type: PUBLIC
05492 // Description: 
05493 // Author     : Jane Hu 
05494 // Date       : 10/08
05495 //===============================================================================
05496 CubitStatus OCCModifyEngine:: sweep_rotational(
05497   DLIList<GeometryEntity*>& ref_ent_list,
05498   DLIList<BodySM*>& result_body_list,
05499   const CubitVector& point,
05500   const CubitVector& direction,
05501   double angle, //in radians
05502   int steps,  //not used
05503   double draft_angle, //not used
05504   int draft_type,  //not used
05505   bool switchside, //not used
05506   bool make_solid,
05507   bool rigid,  //not used
05508   bool anchor_entity, //not used
05509   bool keep_old ) const  
05510 {
05511   gp_Dir adir(direction.x(), direction.y(), direction.z()); 
05512   gp_Pnt pt = gp_Pnt( point.x(), point.y(), point.z());
05513   gp_Ax1 axis = gp_Ax1(pt, adir);
05514 
05515   gp_Lin line = gp_Lin(axis);
05516   TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(line);
05517   OCCCurve* acurve = CAST_TO(OCCQueryEngine::instance()->populate_topology_bridge(edge, CUBIT_TRUE), OCCCurve);
05518   assert(acurve);
05519 
05520   CubitVector start;
05521   CubitVector end;
05522 
05523   for (int i = ref_ent_list.size(); i > 0; i--)
05524   {
05525     GeometryEntity *ref_ent = ref_ent_list.get_and_step();
05526     //Make copy of the surface or curve for later to build solid.
05527     OCCSurface* surface = CAST_TO(ref_ent, OCCSurface);
05528     OCCCurve* curve = CAST_TO(ref_ent, OCCCurve);
05529     TopoDS_Shape toposhape ;
05530     if(surface != NULL)
05531     {
05532       CubitStatus stat = get_sweepable_toposhape(surface, (CubitVector*)NULL, toposhape);
05533       if(!stat)
05534         continue;
05535       //only non-intersecting of surface and axis can be swept.
05536       DLIList<CubitVector> intersect_pts;
05537       OCCQueryEngine::instance()->get_intersections(acurve, surface,
05538                                     intersect_pts, CUBIT_TRUE);
05539       if(intersect_pts.size() > 0)
05540       { 
05541         PRINT_ERROR("Only surfaces with no intersection point with the axis can be revolve-swept.\n");
05542         continue;
05543       } 
05544     }
05545     else if(curve != NULL)
05546     {
05547       CubitStatus stat = get_sweepable_toposhape(curve, toposhape);
05548       if(!stat)
05549         continue;
05550       //closed curve can't intersect with the axis, while open curve can only
05551       //intersect the axis at the end points. 
05552       //only curve not intersecting with axis in curve's middle locations
05553       //can be revolved
05554       DLIList<CubitVector> intersect_pts;
05555       OCCQueryEngine::instance()->get_intersections(curve, acurve,
05556                                   intersect_pts, CUBIT_TRUE, CUBIT_TRUE);
05557       if(!toposhape.Closed())
05558       {
05559         //get start and end points
05560         DLIList<OCCPoint*> point_list;
05561         curve->get_points(point_list);
05562         assert(2 == point_list.size());
05563         GeometryType type = curve->geometry_type();
05564         start = point_list.get_and_step()->coordinates();
05565         end = point_list.get()->coordinates();
05566         CubitBoolean start_int = CUBIT_FALSE;
05567         CubitBoolean end_int = CUBIT_FALSE;
05568         if(intersect_pts.size() > 0)
05569         {
05570           CubitBoolean non_int = CUBIT_FALSE;
05571           for(int i = 0; i < intersect_pts.size(); i++)
05572           {
05573              CubitVector &prt = intersect_pts.get_and_step();
05574              if(prt.distance_between(start) > TOL &&
05575                 prt.distance_between(end) > TOL)
05576              {
05577                 non_int = CUBIT_TRUE;
05578                 PRINT_ERROR("Only curves with no intersection point with the axis can be revolve-swept.\n");
05579                 break;
05580              }
05581              else if(prt.distance_between(start) <= TOL)
05582                 start_int = CUBIT_TRUE;
05583              else if(prt.distance_between(end) <= TOL)
05584                 end_int = CUBIT_TRUE;
05585           }
05586           if(non_int)
05587             continue;
05588           if(start_int && end_int && type == STRAIGHT_CURVE_TYPE)
05589           {
05590             PRINT_ERROR("Sweep along curve itself is not allowed.\n");
05591             continue;
05592           } 
05593         }
05594       }
05595       else
05596       {
05597         if(intersect_pts.size() > 0)
05598         {
05599           PRINT_ERROR("Only curves with no intersection point with the axis can be revolve-swept.\n");
05600           continue;
05601         }  
05602       }
05603     } 
05604     else
05605     {
05606       PRINT_ERROR("Only surface or curve can be revolve-swept.\n");
05607       continue;
05608     }
05609     TopoDS_Shape new_shape;
05610     DLIList<TopologyBridge*> tbs;
05611     if(make_solid && curve != NULL )
05612     //giving an open wire and want a solid
05613     {
05614       if(!toposhape.Closed())
05615       {
05616         //project the start and end points onto the axis
05617         CubitBoolean start_closed = CUBIT_FALSE;
05618         CubitBoolean end_closed = CUBIT_FALSE;
05619         if(acurve->point_containment(start) != CUBIT_PNT_OFF)
05620           start_closed = CUBIT_TRUE;
05621         if(acurve->point_containment(end) != CUBIT_PNT_OFF)
05622           end_closed = CUBIT_TRUE; 
05623         CubitVector start_proj, end_proj;
05624         TopoDS_Edge edge1, edge2;
05625         BRepBuilderAPI_MakeWire m_wire;
05626         if(!start_closed)
05627         {
05628           acurve->closest_point(start, start_proj);
05629           gp_Pnt pt1 = gp_Pnt( start.x(), start.y(), start.z()); 
05630           gp_Pnt pt2 = gp_Pnt( start_proj.x(), start_proj.y(), start_proj.z());
05631           edge1 = BRepBuilderAPI_MakeEdge(pt1, pt2);
05632           m_wire.Add(edge1);
05633           m_wire.Add(TopoDS::Wire(toposhape));
05634         }
05635         else
05636         {
05637           m_wire.Add(TopoDS::Wire(toposhape));
05638           start_proj = start;
05639         }
05640  
05641         if(!end_closed)
05642         {
05643           acurve->closest_point(end,end_proj);
05644           gp_Pnt pt1 = gp_Pnt( end.x(), end.y(), end.z());
05645           gp_Pnt pt2 = gp_Pnt( end_proj.x(), end_proj.y(), end_proj.z());
05646           edge2 = BRepBuilderAPI_MakeEdge(pt1, pt2);
05647           m_wire.Add(edge2);
05648         }
05649       
05650         else
05651           end_proj = end;
05652         
05653         gp_Pnt pt1 = gp_Pnt( end_proj.x(), end_proj.y(), end_proj.z());
05654         gp_Pnt pt2 = gp_Pnt( start_proj.x(), start_proj.y(), start_proj.z());
05655         TopoDS_Edge edge3 = BRepBuilderAPI_MakeEdge(pt2, pt1);
05656         m_wire.Add(edge3);
05657       
05658         TopoDS_Wire wire = m_wire.Wire();
05659         toposhape = BRepBuilderAPI_MakeFace(wire);
05660       }
05661       else //closed
05662       {
05663         TopoDS_Wire wire = TopoDS::Wire(toposhape);
05664         toposhape = BRepBuilderAPI_MakeFace(wire);
05665       }
05666     }
05667     BRepSweep_Revol revol(toposhape, axis, angle);
05668     new_shape = revol.Shape();
05669 
05670     tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
05671     assert(tbs.size() == 1);
05672 
05673     BodySM* bodysm = CAST_TO(tbs.get(), BodySM);
05674 
05675     if(bodysm && !keep_old && surface != NULL)
05676     {
05677       //have to unite the new geometry with the old one.
05678       DLIList<BodySM*> bodies; 
05679       DLIList<OCCBody*> occ_bodies;
05680       surface->get_bodies(occ_bodies);
05681       if(occ_bodies.size() == 1)
05682       {
05683         OCCBody* old_body = occ_bodies.get();
05684         //delete sheet body if surface is standalong.
05685         if (old_body->is_sheet_body())
05686         {
05687           OCCQueryEngine::instance()->delete_solid_model_entities(old_body);
05688           result_body_list.append(bodysm);
05689         }
05690         else
05691         {
05692           bodies.append(CAST_TO(old_body, BodySM));
05693           bodies.append(bodysm);
05694           DLIList<BodySM*> newBodies;
05695           CubitStatus stat = unite(bodies, newBodies, CUBIT_FALSE);
05696           if(stat)
05697             result_body_list.append(newBodies.get());
05698         }
05699       }
05700     }
05701     else if (bodysm)
05702       result_body_list.append(bodysm);
05703     continue;
05704   }
05705   OCCQueryEngine::instance()->delete_solid_model_entities(acurve);
05706   if(result_body_list.size()>0)
05707     return CUBIT_SUCCESS;
05708   else 
05709     return CUBIT_FAILURE;
05710 }
05711 
05712 //===============================================================================
05713 // Function   : sweep_along_curve
05714 // Member Type: PUBLIC
05715 // Description: The ref_edge_list must provide a list of curves which are
05716 //              connected, and making G1 continuous wire.
05717 // Author     : Jane Hu
05718 // Date       : 10/08
05719 //===============================================================================
05720 CubitStatus OCCModifyEngine::sweep_along_curve(
05721   DLIList<GeometryEntity*>& ref_ent_list,
05722   DLIList<BodySM*>& result_body_list,
05723   DLIList<Curve*>& ref_edge_list,
05724   double draft_angle, //only used for straight curve case
05725   int draft_type, //only used for straight curve case
05726   bool rigid, //not used
05727   bool anchor_entity, //not used
05728   bool keep_old) const 
05729 {
05730   //make wire out of ref_edge_list
05731   BRepBuilderAPI_MakeWire awire;
05732   TopTools_ListOfShape L;
05733   OCCCurve* occ_curve = NULL;
05734   GeometryType type = UNDEFINED_CURVE_TYPE;
05735   int num_curve = 0;
05736   for(int i = 0; i < ref_edge_list.size(); i++)
05737   {
05738     Curve* curve = ref_edge_list.get_and_step();
05739     occ_curve = CAST_TO(curve, OCCCurve);
05740     if(!occ_curve)
05741       continue;
05742     TopoDS_Edge* topoedge = occ_curve->get_TopoDS_Edge( );
05743     BRepBuilderAPI_Copy api_copy(*topoedge);
05744     TopoDS_Shape newShape = api_copy.ModifiedShape(*topoedge);
05745     L.Append(newShape);
05746     type = occ_curve->geometry_type();
05747     num_curve++;
05748   }
05749   if(L.IsEmpty())
05750   {
05751     PRINT_ERROR("There's no valid sweeping path.\n");
05752     return CUBIT_FAILURE;
05753   }
05754   
05755   if(num_curve == 1 && type == STRAIGHT_CURVE_TYPE && draft_angle != 0.0)
05756   {
05757     DLIList<OCCPoint*> point_list;
05758     occ_curve->get_points(point_list);
05759     CubitVector v1 = point_list.get_and_step()->coordinates();
05760     CubitVector v2 = point_list.get()->coordinates();
05761     CubitVector sweep_vector = v2-v1;
05762     return sweep_translational(ref_ent_list,result_body_list,sweep_vector,
05763                                draft_angle, draft_type, CUBIT_FALSE, 
05764                                rigid, anchor_entity, keep_old); 
05765   }
05766   awire.Add(L);
05767   TopoDS_Wire wire;
05768   wire = awire.Wire();
05769 
05770   BRepTools_WireExplorer it(wire);
05771   int num_edges = 0;
05772   for(; it.More(); it.Next())
05773     num_edges++; 
05774   
05775   BRepLib_FuseEdges fuser(wire);
05776   fuser.SetConcatBSpl();
05777   fuser.Perform();
05778   TopoDS_Shape  spline = fuser.Shape();
05779   wire = TopoDS::Wire(spline);
05780 
05781   DLIList<TopologyBridge*> tbs;
05782   for (int i = ref_ent_list.size(); i > 0; i--)
05783   {
05784     GeometryEntity *ref_ent = ref_ent_list.get_and_step();
05785     //Make copy of the surface or curve for later to build solid.
05786     OCCSurface* surface = CAST_TO(ref_ent, OCCSurface);
05787     OCCCurve* curve = CAST_TO(ref_ent, OCCCurve);
05788     TopoDS_Shape toposhape ;
05789     if(surface != NULL)
05790     {
05791       CubitStatus stat = get_sweepable_toposhape(surface, (CubitVector*)NULL, toposhape);
05792       if(!stat)
05793         continue;
05794     } 
05795     else if(curve != NULL)
05796     {
05797       CubitStatus stat = get_sweepable_toposhape(curve, toposhape);
05798       if(!stat)
05799         continue;
05800     }
05801 
05802     //sweep along the wire
05803     BRepOffsetAPI_MakePipe maker(wire, toposhape);
05804     if(!maker.IsDone())
05805     {
05806       PRINT_ERROR("Can't sweep along the provided curve(s).\n");
05807       continue;
05808     }
05809     TopoDS_Shape newShape = maker.Shape();
05810     
05811     tbs += OCCQueryEngine::instance()->populate_topology_bridge(newShape);
05812     assert(tbs.size() == 1);
05813 
05814     BodySM* bodysm = CAST_TO(tbs.get(), BodySM);
05815 
05816     if(bodysm && !keep_old && surface != NULL)
05817     {
05818       //have to unite the new geometry with the old one.
05819       DLIList<BodySM*> bodies;
05820       DLIList<OCCBody*> occ_bodies;
05821       surface->get_bodies(occ_bodies);
05822       if(occ_bodies.size() == 1)
05823       {
05824         OCCBody* old_body = occ_bodies.get();
05825         //delete sheet body if surface is standalong.
05826         if (old_body->is_sheet_body())
05827         {
05828           OCCQueryEngine::instance()->delete_solid_model_entities(old_body);
05829           result_body_list.append(bodysm);
05830         }
05831         else
05832         {
05833           bodies.append(CAST_TO(old_body, BodySM));
05834           bodies.append(bodysm);
05835           DLIList<BodySM*> newBodies;
05836           CubitStatus stat = unite(bodies, newBodies, CUBIT_FALSE);
05837           if(stat)
05838             result_body_list.append(newBodies.get());
05839         }
05840       }
05841     }
05842     else if (bodysm)
05843       result_body_list.append(bodysm);
05844   }
05845   return CUBIT_SUCCESS;
05846 }
05847 
05848 CubitStatus OCCModifyEngine::sweep_to_body(
05849                                    DLIList<Curve*> curve_list,
05850                                    BodySM *target_body,
05851                                    CubitVector sweep_vector,
05852                                    DLIList<BodySM*> &new_bodies,
05853                                    bool unite) const
05854 {
05855   TopoDS_Shape *stop_shape = NULL;
05856   OCCBody* occ_body = CAST_TO(target_body, OCCBody);
05857   occ_body->get_TopoDS_Shape(stop_shape);
05858 
05859   gp_Dir adir(sweep_vector.x(), sweep_vector.y(), sweep_vector.z());
05860 
05861   DLIList<BodySM*> swept_bodies;
05862   for(int i = 0; i < curve_list.size(); i++)
05863   {
05864     OCCCurve* curve = CAST_TO(curve_list.get_and_step(), OCCCurve);
05865     TopoDS_Shape toposhape ;
05866     CubitStatus stat = get_sweepable_toposhape(curve, toposhape);
05867     if(!stat)
05868       continue;
05869     BRepOffsetAPI_MakeDraft draft(toposhape, adir, 0.0);
05870     draft.Perform(*stop_shape);
05871     TopoDS_Shape new_shape = draft.Shape();
05872     DLIList<TopologyBridge*> tbs;
05873     tbs = OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
05874     assert(tbs.size() == 1); 
05875     BodySM* bodysm = CAST_TO(tbs.get(), BodySM);
05876     if (bodysm)
05877       swept_bodies.append(bodysm);
05878   }
05879   if(unite)
05880     return this->unite(swept_bodies, new_bodies, CUBIT_FALSE);
05881   new_bodies += swept_bodies;
05882   return CUBIT_SUCCESS; 
05883 }
05884 
05885 CubitStatus OCCModifyEngine::sweep_to_body(
05886                                    Surface  *source_surface,
05887                                    BodySM *target_body,
05888                                    CubitVector sweep_vector,
05889                                    DLIList<BodySM*> &new_bodies ) const
05890 {
05891   TopoDS_Shape *stop_shape = NULL;
05892   OCCBody* occ_body = CAST_TO(target_body, OCCBody);
05893   occ_body->get_TopoDS_Shape(stop_shape);
05894 
05895   gp_Dir adir(sweep_vector.x(), sweep_vector.y(), sweep_vector.z());
05896 
05897   DLIList<BodySM*> swept_bodies;
05898   OCCSurface* surf = CAST_TO(source_surface, OCCSurface);
05899   TopoDS_Shape toposhape ;
05900   CubitStatus stat = get_sweepable_toposhape(surf, &sweep_vector, toposhape); 
05901   if(!stat)
05902     return CUBIT_FAILURE;
05903   BRepOffsetAPI_MakeDraft draft(toposhape, adir, 0.0);
05904   draft.Perform(*stop_shape);
05905   TopoDS_Shape new_shape = draft.Shape();
05906   DLIList<TopologyBridge*> tbs;
05907   tbs = OCCQueryEngine::instance()->populate_topology_bridge(new_shape);
05908   assert(tbs.size() == 1);
05909   BodySM* bodysm = CAST_TO(tbs.get(), BodySM);
05910   //get surfaces from the shell body and create a top surface to
05911   //make a swept solid.
05912   DLIList<OCCShell*> shells = CAST_TO(bodysm, OCCBody)->shells();
05913   if(shells.size() == 0)
05914   {
05915     PRINT_WARNING("Sweep surface failed inside OCC engine.\n");
05916     return CUBIT_FAILURE;
05917   }
05918   assert(shells.size() == 1);
05919   DLIList<OCCSurface*> memberSurfaces = shells.get()->getMemberSurfaces();
05920   DLIList<Surface*> surface_list;
05921   for (int i = 0; i < memberSurfaces.size(); ++i)
05922     surface_list.append(memberSurfaces.get_and_step());
05923 
05924   //create the top surface from edges.
05925   DLIList<OCCCoEdge*> coedges;
05926   for(int i = 0; i < surface_list.size(); i++)
05927     CAST_TO(surface_list.get_and_step(), OCCSurface)->get_coedges(coedges);
05928   for(int i = 0; i < coedges.size(); i++)
05929   {
05930     OCCCoEdge* coedge = coedges[i];
05931     if(coedge == NULL)
05932       continue;
05933     for(int j = i+1; j < coedges.size(); j++)
05934     {
05935       OCCCoEdge* temp_coedge = coedges[j];
05936       if(temp_coedge == NULL)
05937         continue;
05938       if(coedge->curve() == temp_coedge->curve()) //Since the shell
05939       // is open, the sense of curve can be either the same or opposite.
05940       {
05941          coedges.move_to(coedge);
05942          coedges.change_to((OCCCoEdge*)NULL);
05943          coedges.move_to(temp_coedge);
05944          coedges.change_to((OCCCoEdge*)NULL);
05945        }
05946     }
05947   }
05948   coedges.remove_all_with_value(NULL);
05949   assert(coedges.size() > 0);
05950   DLIList<Curve*> curves;
05951   for(int i = 0; i < coedges.size(); i++)
05952     curves.append(coedges.get_and_step()->curve());
05953 
05954   Surface* surface = make_Surface(PLANE_SURFACE_TYPE, curves);
05955   if(!surface)
05956     surface = make_Surface(BEST_FIT_SURFACE_TYPE, curves);
05957   if(!surface)
05958   {
05959     PRINT_ERROR("Can't calculate for the top surface.\n");
05960     return CUBIT_FAILURE;
05961   }
05962   surface_list.append(surface);
05963   DLIList<BodySM*> bodies;
05964     create_solid_bodies_from_surfs(surface_list, bodies);
05965 
05966   if(bodies.size() == 1)
05967     bodysm = bodies.get();
05968   else
05969   {
05970     PRINT_WARNING("Sweep surface failed in creating solid.\n");
05971     return CUBIT_FAILURE;
05972   }
05973   if (bodysm)
05974     new_bodies.append(bodysm);
05975   return CUBIT_SUCCESS;
05976 }
05977 
05978 //HEADER- Webcut-related functions
05979 
05980 //===============================================================================
05981 // Function   : webcut
05982 // Member Type: PUBLIC
05983 // Description: 
05984 // Author     : Jane Hu
05985 // Date       : 12/08
05986 //===============================================================================
05987 CubitStatus OCCModifyEngine::webcut(DLIList<BodySM*>& webcut_body_list,
05988                               const CubitVector &v1,
05989                               const CubitVector &v2,
05990                               const CubitVector &v3,
05991                               DLIList<BodySM*>& neighbor_imprint_list,
05992                               DLIList<BodySM*>& results_list,
05993                               ImprintType imprint_type,
05994                               bool preview ) const
05995 {
05996   CubitStatus stat;
05997   DLIList<BodySM*> new_BodySMs;
05998 
05999   if(preview)
06000   {
06001     TopoDS_Face* p_face;
06002     stat = get_3_point_plane(v1, v2, v3, p_face);
06003     if(!stat)
06004       return stat;
06005     GfxPreview::clear();
06006     OCCDrawTool::instance()->draw_TopoDS_Shape(p_face, CUBIT_BLUE_INDEX, CUBIT_TRUE);
06007     delete p_face;
06008     p_face = NULL;
06009     return CUBIT_SUCCESS;
06010   }
06011 
06012   stat = OCCModifyEngine::instance()->section(webcut_body_list, v1, v2, v3, new_BodySMs, true, true,false);
06013   if(stat == CUBIT_FAILURE)
06014   {
06015     PRINT_ERROR("Can't webcut the bodies using a plane determined by 3 points.\n");
06016     return stat;
06017   }
06018   
06019   stat = OCCModifyEngine::instance()->section(webcut_body_list, v1, v2, v3, new_BodySMs, false, false, false);
06020   if(stat == CUBIT_FAILURE)
06021   {
06022     PRINT_ERROR("Can't webcut the bodies using a plane determined by 3 points.\n");
06023     return stat;
06024   }
06025 
06026   BodySM* new_body1, *new_body2;
06027   if(imprint_type > NO_IMPRINT)
06028   {
06029     for(int i = 0; i < new_BodySMs.size()-1; i ++)
06030     {
06031       BodySM* body1 = new_BodySMs[i];
06032       for(int j = i+1; j < new_BodySMs.size(); j++)
06033       {
06034         BodySM* body2 = new_BodySMs[j];
06035         stat =  this->imprint( body1, body2, new_body1, new_body2, false);
06036         if(new_body1 && body1 != new_body1)
06037           new_BodySMs[i] = new_body1;
06038         if(new_body2 && body2 != new_body2)
06039           new_BodySMs[j] = new_body2; 
06040       }
06041     }
06042   }
06043 
06044   results_list = new_BodySMs;
06045 
06046   //now imprint with the neighbors
06047   if( imprint_type == INCLUDE_NEIGHBORS  )
06048   {
06049     // Loop over all the neighboring Bodies
06050     DLIList<TopoDS_Shape*> shape_list1, shape_list2;
06051     DLIList<CubitBoolean> is_volume;
06052     stat = get_shape_list(neighbor_imprint_list,shape_list1,is_volume,false);
06053     if (!stat)
06054     {
06055         PRINT_WARNING("Can't imprint using neighouring bodies.\n");
06056         return CUBIT_SUCCESS;
06057     }    
06058     is_volume.clean_out();
06059 
06060     stat = get_shape_list(new_BodySMs,shape_list2,is_volume,false);
06061     { 
06062         PRINT_WARNING("Can't imprint using neighouring bodies.\n");
06063         return CUBIT_SUCCESS;
06064     }
06065     // Loop over all the neighboring shapes
06066     DLIList<TopoDS_Face*> face_list;
06067     for (int i=shape_list1.size(); i--;)
06068     {
06069       TopoDS_Shape *neighbor_shape = shape_list1.get_and_step() ;
06070       for(int j = 0; j < shape_list2.size(); j ++)
06071       {
06072         TopoDS_Shape* shape2 = shape_list2[j];
06073         int result =  this->imprint_toposhapes( shape2, neighbor_shape,
06074                       face_list);
06075         if(result == 0)
06076           shape_list2[j] = shape2;   
06077       }
06078     }
06079 
06080     DLIList<TopologyBridge*> tbs;
06081     results_list.clean_out();
06082     for(int j = 0; j < shape_list2.size(); j ++)
06083     {
06084       TopoDS_Shape* shape2 = shape_list2[j];
06085         
06086       tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape2);
06087       BodySM* newBody1 = CAST_TO(tbs.get(),BodySM);
06088       results_list.append(newBody1);    
06089     }
06090   }
06091 
06092   return CUBIT_SUCCESS;  
06093 }
06094 
06095 //===============================================================================
06096 // Function   : webcuts a list of bodies using another Body as the tool.
06097 // Member Type: PUBLIC
06098 // Description: 
06099 // Author     : Jane Hu
06100 // Date       : 01/09
06101 //===============================================================================
06102 CubitStatus    OCCModifyEngine::webcut(DLIList<BodySM*>& webcut_body_list,
06103                                 BodySM const* tool_body,
06104                                 DLIList<BodySM*>& neighbor_imprint_list,
06105                                 DLIList<BodySM*>& results_list,
06106                                 ImprintType imprint_type,
06107                                 bool preview ) const
06108 {
06109   // tool_body and webct_body_list will be kept and webcut result is in 
06110   //results_list.
06111   //tool_body is a const pointer points to varible BodySM object
06112   //here trying to create a non-const pointer points to the same BodySM object.
06113 
06114   BodySM *body = const_cast<BodySM*>(tool_body);
06115   CubitStatus stat;
06116   DLIList<BodySM*> tool_bodies;
06117   if(preview)
06118     tool_bodies.append(body);
06119 
06120   BodySM *copy_tool = copy_body(body);
06121  
06122   if(!preview)
06123     tool_bodies.append(copy_tool);
06124 
06125   // preview the tool
06126   if (preview)
06127   {
06128     DLIList<TopoDS_Shape*> shape_list;
06129     DLIList<CubitBoolean> is_volume;
06130     stat = get_shape_list(tool_bodies,shape_list,is_volume,false);
06131     if(!stat)
06132     {
06133         PRINT_WARNING("tool_body is not an OCC body.\n");
06134         return CUBIT_FAILURE;
06135     }
06136     GfxPreview::clear();
06137     OCCDrawTool::instance()->draw_TopoDS_Shape(shape_list.get(), 
06138                              CUBIT_BLUE_INDEX, CUBIT_TRUE);
06139 
06140     return CUBIT_SUCCESS;
06141   }
06142 
06143   //if the tool_body is a volume, use intersect & subtract,
06144   //if it's a shell or face body, use section then.
06145   OCCBody* occ_body = CAST_TO(body, OCCBody);
06146   DLIList<Lump*> lumps;
06147   lumps = occ_body->lumps();
06148   DLIList<OCCShell*> shells;
06149   shells = occ_body->shells();
06150   DLIList<OCCSurface*> surfaces;
06151   surfaces = occ_body->my_sheet_surfaces();
06152 
06153   if(lumps.size() == 0 && (shells.size()==1 || surfaces.size() == 1))
06154   {
06155     OCCSurface * surface = NULL;
06156     TopoDS_Shell* topo_shell = NULL;
06157     TopoDS_Face *topo_face = NULL;
06158     if(shells.size() == 1)
06159     {
06160       OCCShell* shell = shells.get();
06161       surface = shell->getMemberSurfaces().get();
06162       topo_shell = shell->get_TopoDS_Shell();
06163     }
06164     else
06165     {
06166       surface = surfaces.get();
06167       topo_face = surface->get_TopoDS_Face();
06168     }
06169     CubitVector point_1, normal ;
06170     CubitStatus rsl = surface->get_point_normal(point_1, normal);
06171     assert(rsl);
06172 
06173     //compare the tool body's location with the webcut_body_list, to see if
06174     //one side of the normal will totally cover one or more volumes
06175     //while the other side cut through one volume, with no whole volume
06176     //covered. Make sure the tool body's normal direct to single cut-
06177     //through volume to make sure the boolean operation won't destory
06178     //webcut_body_list and create a new body.
06179     CubitBoolean reversed = CUBIT_FALSE;
06180     if(webcut_body_list.size() == 1)
06181     {
06182       DLIList<OCCSurface*> cut_surfaces;
06183       OCCSurface* cut_face = NULL;
06184       if(surfaces.size() == 1)
06185       {
06186         cut_surfaces = occ_body->my_sheet_surfaces();
06187         cut_face = cut_surfaces.get();
06188       }
06189       else
06190       {
06191         DLIList<OCCShell*> shells;
06192         shells = occ_body->shells();
06193         cut_face = shells.get()->my_surface();
06194       }
06195       if(cut_face != NULL)
06196       {
06197         CubitVector center = cut_face->center_point();
06198         CubitVector normal;
06199         cut_face->get_point_normal(center, normal);
06200         DLIList<Lump*> lumps;
06201         BodySM *from_body = webcut_body_list.get();
06202         from_body->lumps(lumps);
06203         int right = 0, left = 0;
06204         for(int kk = 0; kk < lumps.size(); kk++)
06205         {
06206           CubitBox box = lumps.get_and_step()->bounding_box();
06207           if(box <= center) //center outside of box
06208           {
06209             CubitVector v = box.center() - center;
06210             if(v%normal > 0)
06211               left ++;
06212             else
06213               right++;
06214           }
06215         }
06216         if(right > 0 && left == 0)
06217           reversed = CUBIT_TRUE;
06218       }
06219     }
06220     gp_Pnt pt = gp_Pnt( point_1.x(), point_1.y(), point_1.z());
06221     gp_Dir normal_dir(normal.x(), normal.y(), normal.z());
06222     gp_Vec vec(normal_dir);
06223     if(reversed)
06224       vec = -vec;
06225     pt =  pt.Translated(vec);
06226 
06227     TopoDS_Solid solid;
06228     if(shells.size() == 1)
06229       solid = BRepPrimAPI_MakeHalfSpace(*topo_shell, pt);
06230     else
06231       solid = BRepPrimAPI_MakeHalfSpace(*topo_face,pt);
06232 
06233     DLIList<CubitBoolean> is_tool_volume;
06234     is_tool_volume.append(CUBIT_TRUE);
06235     DLIList<CubitBox*> tool_boxes ;
06236     Bnd_Box box;
06237     BRepBndLib::Add(solid, box);
06238     double min[3], max[3];
06239     box.Get(min[0], min[1], min[2], max[0], max[1], max[2]);
06240     CubitBox* cBox = new CubitBox(min, max);
06241 
06242     tool_boxes.append(cBox);
06243     DLIList<TopoDS_Shape*> solids;
06244     solids.append(&solid);
06245     rsl = do_subtract(webcut_body_list, solids, is_tool_volume,
06246                      &tool_boxes, results_list, CUBIT_TRUE) ;
06247     delete cBox;
06248     if(!rsl)
06249     {
06250       PRINT_ERROR("Failed to webcut the bodies.\n");
06251       return CUBIT_FAILURE;
06252     }
06253     gp_Vec vec2 =  -2 * vec;
06254     pt = pt.Translated(vec2);
06255     if(shells.size() == 1)
06256       solid = BRepPrimAPI_MakeHalfSpace(*topo_shell, pt);
06257     else
06258       solid = BRepPrimAPI_MakeHalfSpace(*topo_face,pt);
06259     Bnd_Box box2;
06260     BRepBndLib::Add(solid, box2);
06261     box2.Get(min[0], min[1], min[2], max[0], max[1], max[2]);
06262     cBox = new CubitBox(min, max);
06263     tool_boxes.clean_out();
06264     tool_boxes.append(cBox);
06265     solids.clean_out();
06266     solids.append(&solid);
06267     rsl = do_subtract(webcut_body_list, solids, is_tool_volume,
06268                      &tool_boxes, results_list, CUBIT_FALSE) ;
06269     //make sure the original body's pointer is the first.
06270     results_list.reverse();
06271     delete cBox;
06272     return rsl;
06273   }
06274 
06275   stat = intersect(body, webcut_body_list, results_list,
06276                                CUBIT_TRUE);
06277  
06278   if(!stat)
06279   { 
06280     PRINT_ERROR("Failed to webcut the bodies.\n"); 
06281     return CUBIT_FAILURE;
06282   }
06283 
06284   bool imprint = CUBIT_TRUE;
06285   if(imprint_type == NO_IMPRINT)
06286     imprint = CUBIT_FALSE;
06287 
06288   stat = subtract(tool_bodies, webcut_body_list, results_list, imprint, 
06289                   CUBIT_FALSE);
06290 
06291   //intersect doesn't have to imprint option, so first do this imprint.
06292   BodySM* new_body1, *new_body2;
06293   if(imprint_type > NO_IMPRINT)
06294   {
06295     for(int i = 0; i < results_list.size()-1; i ++)
06296     {
06297       BodySM* body1 = results_list[i];
06298       for(int j = i+1; j < results_list.size(); j++)
06299       {
06300         BodySM* body2 = results_list[j];
06301         stat =  this->imprint( body1, body2, new_body1, new_body2, false);
06302         if(new_body1 && body1 != new_body1)
06303           results_list[i] = new_body1;
06304         if(new_body2 && body2 != new_body2)
06305           results_list[j] = new_body2;
06306       }
06307     }
06308   }
06309 
06310   //now imprint with the neighbors
06311   if( imprint_type == INCLUDE_NEIGHBORS  )
06312   {
06313     // Loop over all the neighboring Bodies
06314     DLIList<TopoDS_Shape*> shape_list1, shape_list2;
06315     DLIList<CubitBoolean> is_volume;
06316     stat = get_shape_list(neighbor_imprint_list,shape_list1,is_volume,false);
06317     if (!stat)
06318     {
06319         PRINT_WARNING("Can't imprint using neighouring bodies.\n");
06320         return CUBIT_SUCCESS;
06321     }
06322     is_volume.clean_out();
06323 
06324     stat = get_shape_list(results_list,shape_list2,is_volume,false);
06325     {
06326         PRINT_WARNING("Can't imprint using neighouring bodies.\n");
06327         return CUBIT_SUCCESS;
06328     }
06329     // Loop over all the neighboring shapes
06330     DLIList<TopoDS_Face*> face_list;
06331     for (int i=shape_list1.size(); i--;)
06332     {
06333       TopoDS_Shape *neighbor_shape = shape_list1.get_and_step() ;
06334       for(int j = 0; j < shape_list2.size(); j ++)
06335       {
06336         TopoDS_Shape* shape2 = shape_list2[j];
06337         int result =  this->imprint_toposhapes( shape2, neighbor_shape, face_list);
06338         if(result == 0)
06339           shape_list2[j] = shape2;
06340       }
06341     }
06342 
06343     DLIList<TopologyBridge*> tbs;
06344     results_list.clean_out();
06345     for(int j = 0; j < shape_list2.size(); j ++)
06346     {
06347       TopoDS_Shape* shape2 = shape_list2[j];
06348 
06349       tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape2);
06350       BodySM* newBody1 = CAST_TO(tbs.get(),BodySM);
06351       results_list.append(newBody1);
06352     }
06353   } 
06354   return stat;
06355 }
06356 
06357 //Dummy functions to fulfill the pure virtural functions in parents, should
06358 //not be called.       ---Jane Hu, 02/17/2012 
06359 CubitStatus OCCModifyEngine::webcut_with_sheet(
06360                                     DLIList<BodySM*>& webcut_body_list,
06361                                     BodySM *sheet_body,
06362                                     DLIList<BodySM*>& neighbor_imprint_list,
06363                                     DLIList<BodySM*> &new_bodies,
06364                                     ImprintType imprint_type ,
06365                                     bool preview )
06366 {
06367   return CUBIT_FAILURE;                     
06368 }
06369 
06370 CubitStatus OCCModifyEngine::webcut_with_extended_sheet(
06371                                     DLIList<BodySM*> &webcut_body_list,
06372                                     DLIList<Surface*> &surface_list,
06373                                     DLIList<BodySM*>& neighbor_imprint_list,
06374                                     DLIList<BodySM*> &new_bodies,
06375                                     int &num_cut,
06376                                     ImprintType imprint_type ,
06377                                     bool preview )
06378 {
06379   PRINT_ERROR("This feature is not implemented.\n");
06380   return CUBIT_FAILURE;
06381 } 
06382 
06383 CubitStatus OCCModifyEngine::webcut_with_sweep_curves(
06384                             DLIList<BodySM*> &blank_bodies,
06385                             DLIList<Curve*> &curves,
06386                             const CubitVector& sweep_vector,
06387                             bool through_all,
06388                             Surface *stop_surf,
06389                             Curve *curve_to_sweep_along,
06390                             DLIList<BodySM*>& neighbor_imprint_list,
06391                             DLIList<BodySM*> &results_list,
06392                             ImprintType imprint_type, 
06393                             CubitBoolean preview )
06394 {
06395   return CUBIT_FAILURE;
06396 }
06397 
06398 CubitStatus OCCModifyEngine::webcut_with_sweep_curves_rotated(
06399                             DLIList<BodySM*> &blank_bodies,
06400                             DLIList<Curve*> &curves,
06401                             const CubitVector &point,
06402                             const CubitVector &sweep_axis,
06403                             double angle,
06404                             Surface *stop_surf,
06405                             DLIList<BodySM*>& neighbor_imprint_list,
06406                             DLIList<BodySM*> &results_list,
06407                             ImprintType imprint_type,
06408                             CubitBoolean preview )
06409 {
06410   return CUBIT_FAILURE;
06411 }
06412 
06413 CubitStatus OCCModifyEngine::webcut_with_sweep_surfaces_rotated(
06414                             DLIList<BodySM*> &blank_bodies,
06415                             DLIList<Surface*> &surfaces,
06416                             const CubitVector &point,
06417                             const CubitVector &sweep_axis,
06418                             double angle,
06419                             Surface *stop_surf,
06420                             bool up_to_next,
06421                             DLIList<BodySM*>& neighbor_imprint_list,
06422                             DLIList<BodySM*> &results_list,
06423                             ImprintType imprint_type ,
06424                             CubitBoolean preview )
06425 {
06426   return CUBIT_FAILURE;
06427 }
06428 
06429 CubitStatus OCCModifyEngine::webcut_with_sweep_surfaces(
06430                             DLIList<BodySM*> &blank_bodies,
06431                             DLIList<Surface*> &surfaces,
06432                             const CubitVector& sweep_vector,
06433                             bool sweep_perp,
06434                             bool through_all,
06435                             bool outward,
06436                             bool up_to_next,
06437                             Surface *stop_surf,
06438                             Curve *curve_to_sweep_along,
06439                             DLIList<BodySM*>& neighbor_imprint_list,
06440                             DLIList<BodySM*> &results_list,
06441                             ImprintType imprint_type ,
06442                             CubitBoolean preview )
06443 {
06444   return CUBIT_FAILURE;
06445 }
06446 
06447 CubitStatus OCCModifyEngine::webcut_with_cylinder(
06448                                         DLIList<BodySM*> &webcut_body_list,
06449                                         double radius,
06450                                         const CubitVector &axis,
06451                                         const CubitVector &center,
06452                                         DLIList<BodySM*>& neighbor_imprint_list,
06453                                         DLIList<BodySM*>& results_list,
06454                                         ImprintType imprint_type ,
06455                                         CubitBoolean preview )
06456 {
06457   return CUBIT_FAILURE;
06458 }
06459 
06460 CubitStatus OCCModifyEngine::webcut_with_brick(
06461                                      DLIList<BodySM*>& webcut_body_list,
06462                                      const CubitVector &center,
06463                                      const CubitVector axes[3],
06464                                      const CubitVector &extension,
06465                                      DLIList<BodySM*>& neighbor_imprint_list,
06466                                      DLIList<BodySM*> &results_list,
06467                                      ImprintType imprint_type ,
06468                                      CubitBoolean preview )
06469 {
06470   return CUBIT_FAILURE;
06471 }
06472 
06473 CubitStatus OCCModifyEngine::webcut_with_planar_sheet(
06474                                             DLIList<BodySM*>& webcut_body_list,
06475                                             const CubitVector &center,
06476                                             const CubitVector axes[2],
06477                                             double width, double height,
06478                                             DLIList<BodySM*>& neighbor_imprint_list,
06479                                             DLIList<BodySM*> &results_list,
06480                                             ImprintType imprint_type ,
06481                                             bool preview )
06482 {
06483   return CUBIT_FAILURE;
06484 }
06485 
06486 CubitStatus OCCModifyEngine::webcut_with_curve_loop(
06487                                          DLIList<BodySM*> &webcut_body_list,
06488                                          DLIList<Curve*> &ref_edge_list,
06489                                          DLIList<BodySM*>& neighbor_imprint_list,
06490                                          DLIList<BodySM*>& results_list,
06491                                          ImprintType imprint_type ,
06492                                          bool preview )
06493 {
06494   return CUBIT_FAILURE;
06495 }
06496 
06497 //===============================================================================
06498 // Function   : separate_surfaces
06499 // Member Type: PUBLIC
06500 // Description: separate surfaces in shells or compounds into independent ones,
06501 //              still keep the original shell.
06502 // Author     : Jane Hu
06503 // Date       : 02/11
06504 //===============================================================================
06505 CubitStatus OCCModifyEngine::separate_surfaces( DLIList<Surface*> &surf_list,
06506                                          DLIList<BodySM*> &new_bodies )
06507 {
06508   DLIList<OCCSurface*> surf_need_work;
06509   //find out the complexity that the surf_list involves.
06510   for (int i = 0; i < surf_list.size(); i++)
06511   {
06512     Surface* surf = surf_list.get_and_step();
06513     OCCSurface *surface = CAST_TO(surf, OCCSurface);
06514     OCCBody* body = surface->my_body();
06515     if(body != NULL) //either a single surface body or a compound body
06516     {
06517       DLIList<Lump*> lumps;
06518       body->lumps(lumps);
06519       if (lumps.size() > 0) //compound body
06520       {
06521         surf_need_work.append(surface);
06522         continue;
06523       }
06524       DLIList< OCCShell*> shells;
06525       body->shells(shells);
06526       if(shells.size() > 0) //compound body
06527         surf_need_work.append(surface);
06528       continue;
06529     }
06530 
06531     OCCShell* shell;
06532     shell = surface->my_shell();
06533     if(shell != NULL && shell->my_surface() == NULL) //sheet body
06534     {
06535       surf_need_work.append(surface);
06536       continue;
06537     }
06538   }
06539   
06540   //create sheet body for surf_need_work list.
06541   for(int i = 0; i < surf_need_work.size(); i++)
06542   {
06543     Surface* copy_surf = make_Surface(surf_need_work.get_and_step());
06544     if (copy_surf == NULL)
06545     {
06546        PRINT_ERROR("Cannot create an OCC sheet bodySM from the given bodySM.\n");
06547        return CUBIT_FAILURE;
06548     }
06549 
06550     OCCSurface* occ_surf = CAST_TO(copy_surf, OCCSurface);
06551     if(occ_surf != NULL)
06552      new_bodies.append( occ_surf->my_body() );
06553   }
06554   return CUBIT_SUCCESS;
06555 }
06556 //===============================================================================
06557 // Function   : section
06558 // Member Type: PUBLIC
06559 // Description: 
06560 // Author     : Jane Hu
06561 // Date       : 11/08
06562 //===============================================================================
06563 CubitStatus OCCModifyEngine::section( DLIList<BodySM*> &section_body_list,
06564                                       const CubitVector &point_1,
06565                                       const CubitVector &point_2,
06566                                       const CubitVector &point_3,
06567                                       DLIList<BodySM*>& new_body_list,
06568                                       bool keep_normal_side,
06569                                       bool keep_old,
06570                                       bool keep_both_sides)
06571 {
06572   if (keep_both_sides == CUBIT_TRUE )
06573   {
06574      PRINT_ERROR("Please use webcut to for keep both sides option.\n");
06575      return CUBIT_FAILURE;
06576   }
06577  
06578   //Calculate normal of the section plan
06579   CubitVector v1, v2, normal;
06580   v1 = point_2 - point_1;
06581   v2 = point_3 - point_1; 
06582   normal = ~(v1 * v2); 
06583   if(fabs(normal.length() - 1) > TOL)
06584   {
06585      PRINT_ERROR("The three points are co-linear, and can't be used as a cutting plane.\n");
06586      return CUBIT_FAILURE;
06587   }
06588   
06589   if(keep_normal_side)
06590     normal *= -1;
06591 
06592   gp_Pnt pt = gp_Pnt( point_1.x(), point_1.y(), point_1.z());
06593   gp_Dir normal_dir(normal.x(), normal.y(), normal.z()); 
06594   gp_Pln plane(pt, normal_dir);
06595   gp_Vec vec(normal_dir);
06596   pt =  pt.Translated(vec);
06597 
06598   TopoDS_Face face = BRepBuilderAPI_MakeFace(plane);
06599   TopoDS_Solid solid = BRepPrimAPI_MakeHalfSpace(face, pt);
06600    
06601   DLIList<CubitBoolean> is_tool_volume;
06602   is_tool_volume.append(CUBIT_TRUE);
06603   DLIList<CubitBox*> tool_boxes ;
06604   Bnd_Box box;
06605   BRepBndLib::Add(solid, box);
06606   double min[3], max[3];
06607   box.Get(min[0], min[1], min[2], max[0], max[1], max[2]);
06608   CubitBox* cBox = new CubitBox(min, max);
06609   
06610   tool_boxes.append(cBox);
06611   DLIList<TopoDS_Shape*> solids;
06612   solids.append(&solid);
06613   CubitStatus stat = do_subtract(section_body_list, solids, is_tool_volume,
06614                      &tool_boxes, new_body_list, keep_old) ;
06615   delete cBox;
06616   return stat;
06617 }
06618 
06619 //===============================================================================
06620 // Function   : split_body
06621 // Member Type: PUBLIC
06622 // Description: Splits multiple lumps in one body into separate bodies
06623 // Author     : Jane Hu 
06624 // Date       : 12/08
06625 //===============================================================================
06626 CubitStatus OCCModifyEngine::split_body( BodySM *body_ptr,
06627                                          DLIList<BodySM*> &new_bodies )
06628 {
06629   OCCBody* occ_body = CAST_TO(body_ptr, OCCBody);
06630   if(!occ_body)
06631   {
06632      PRINT_ERROR("This is not an OCC body to be split.\n");
06633      return CUBIT_FAILURE;
06634   }
06635   DLIList<Lump*> lumps = occ_body->lumps();
06636   if(lumps.size() == 1) 
06637   {
06638     new_bodies.append(body_ptr);
06639     return CUBIT_SUCCESS;
06640   }
06641   for(int i = 0; i < lumps.size(); i++)
06642   {
06643     Lump* lump = lumps.get_and_step();
06644     OCCLump* occ_lump = CAST_TO(lump, OCCLump);
06645     OCCSurface* occ_surface = occ_lump->my_sheet_surface();
06646     //first delete the body which bounds all the stuff.
06647     if (i == 0)
06648       OCCQueryEngine::instance()->unhook_BodySM_from_OCC(body_ptr, CUBIT_FALSE);
06649     if(occ_surface) 
06650     {
06651       TopoDS_Face* face = occ_surface->get_TopoDS_Face();
06652       Surface* surface = 
06653         OCCQueryEngine::instance()->populate_topology_bridge(*face,
06654                                                              CUBIT_TRUE);
06655       new_bodies.append(CAST_TO(surface, OCCSurface)->my_body()); 
06656       continue;
06657     }
06658     OCCShell* occ_shell = occ_lump->my_shell();
06659     if(occ_shell) 
06660     {
06661       TopoDS_Shell* shell = occ_shell->get_TopoDS_Shell();
06662       OCCShell* ashell = 
06663          OCCQueryEngine::instance()->populate_topology_bridge(*shell,
06664                                                               CUBIT_TRUE);
06665       new_bodies.append(ashell->my_body());
06666       continue;
06667     }
06668     else
06669     {
06670       TopoDS_Solid* solid = occ_lump->get_TopoDS_Solid();
06671       Lump* alump = 
06672         OCCQueryEngine::instance()->populate_topology_bridge(*solid,
06673                                                              CUBIT_TRUE);
06674       new_bodies.append(CAST_TO(alump,OCCLump)->get_body());
06675       continue;
06676     }
06677   }
06678   
06679   if(lumps.size() > 1)
06680     delete body_ptr;
06681   return CUBIT_SUCCESS;
06682 }
06683 
06684 
06685 //===============================================================================
06686 // Function   : reverse_body
06687 // Member Type: PUBLIC
06688 // Description: Turn body inside-out
06689 // Author     : Jane Hu
06690 // Date       : 03/03/09
06691 //===============================================================================
06692 CubitStatus OCCModifyEngine::reverse_body( BodySM* body_ptr )
06693 {
06694   OCCBody* occ_body = CAST_TO(body_ptr, OCCBody);
06695   if (!occ_body)
06696   {
06697      PRINT_ERROR("Cannot reverse a non-OCC bodySM .\n"
06698                  "Possible incompatible geometry engines.\n");
06699      return CUBIT_FAILURE;
06700   }
06701 
06702   TopoDS_Shape* orig_S;
06703   TopoDS_Shape S;
06704   BRep_Builder B;
06705   occ_body->get_TopoDS_Shape(orig_S);
06706   S = orig_S->EmptyCopied();
06707   TopoDS_Iterator it(*orig_S);
06708   while (it.More()) {
06709     B.Add(S,it.Value().Reversed());
06710     it.Next();
06711   } 
06712   occ_body->set_TopoDS_Shape(TopoDS::Compound(S));  
06713   //Bind the new shape and its underlining sub-shapes.
06714   TopExp_Explorer Ex_orig, Ex;
06715   int k = -1;
06716   Ex.Init(S, TopAbs_COMPOUND);
06717   Ex_orig.Init(*orig_S, TopAbs_COMPOUND);
06718   for (; Ex_orig.More(), Ex.More(); Ex_orig.Next(), Ex.Next())
06719   {
06720     if(OCCQueryEngine::instance()->OCCMap->IsBound(Ex.Current()))
06721     {
06722       k = OCCQueryEngine::instance()->OCCMap->Find(Ex_orig.Current());   
06723       OCCQueryEngine::instance()->OCCMap->UnBind(Ex_orig.Current());
06724       OCCQueryEngine::instance()->OCCMap->Bind(Ex.Current(), k);
06725       TopExp_Explorer Ex_old_solid, Ex_solid;
06726       Ex_old_solid.Init(*orig_S,TopAbs_SOLID);
06727       Ex_solid.Init(S, TopAbs_SOLID);
06728       DLIList<Lump*> lumps = occ_body->lumps();
06729       for (; Ex_old_solid.More(), Ex_solid.More(); Ex_old_solid.Next(), Ex_solid.Next())
06730       {
06731         k = OCCQueryEngine::instance()->OCCMap->Find(Ex_old_solid.Current());
06732         OCCQueryEngine::instance()->OCCMap->UnBind(Ex_old_solid.Current());
06733         OCCQueryEngine::instance()->OCCMap->Bind(Ex_solid.Current(), k);
06734         OCCLump* occ_lump = CAST_TO(lumps.get_and_step(), OCCLump);
06735         occ_lump->set_TopoDS_Solid(TopoDS::Solid(Ex_solid.Current()));
06736       }
06737     } 
06738     
06739     else
06740     {
06741       Lump *lump = occ_body->lumps().get();
06742       OCCLump* occ_lump = CAST_TO(lump, OCCLump);
06743       TopoDS_Solid solid = *(occ_lump->get_TopoDS_Solid());
06744       k = OCCQueryEngine::instance()->OCCMap->Find(solid);
06745       OCCQueryEngine::instance()->OCCMap->UnBind(solid);
06746       TopExp_Explorer Ex_local;
06747       Ex_local.Init(S, TopAbs_SOLID);
06748       OCCQueryEngine::instance()->OCCMap->Bind(Ex_local.Current(), k);
06749       occ_lump->set_TopoDS_Solid(TopoDS::Solid(Ex_local.Current())); 
06750     }
06751   }  
06752       
06753   Ex.Init(S, TopAbs_SHELL);
06754   Ex_orig.Init(*orig_S, TopAbs_SHELL);
06755   for (; Ex_orig.More(), Ex.More(); Ex_orig.Next(), Ex.Next())
06756   {
06757     k = OCCQueryEngine::instance()->OCCMap->Find(Ex_orig.Current());
06758     OCCQueryEngine::instance()->OCCMap->UnBind(Ex_orig.Current());
06759     OCCQueryEngine::instance()->OCCMap->Bind(Ex.Current(), k);
06760     OCCShell *shell = (OCCShell*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
06761     shell->set_TopoDS_Shell(TopoDS::Shell(Ex.Current())); 
06762   }
06763 
06764   Ex.Init(S, TopAbs_FACE);
06765   Ex_orig.Init(*orig_S, TopAbs_FACE);
06766   for (; Ex_orig.More(), Ex.More(); Ex_orig.Next(), Ex.Next())
06767   {
06768     k = OCCQueryEngine::instance()->OCCMap->Find(Ex_orig.Current());
06769     OCCQueryEngine::instance()->OCCMap->UnBind(Ex_orig.Current());
06770     OCCQueryEngine::instance()->OCCMap->Bind(Ex.Current(), k);
06771     OCCSurface *surface = (OCCSurface *)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
06772     TopoDS_Face face = TopoDS::Face(Ex.Current());
06773     surface->set_TopoDS_Face(face);
06774   }
06775 
06776   Ex.Init(S, TopAbs_WIRE);
06777   Ex_orig.Init(*orig_S, TopAbs_WIRE);
06778   for (; Ex_orig.More(), Ex.More(); Ex_orig.Next(), Ex.Next())
06779   {
06780     k = OCCQueryEngine::instance()->OCCMap->Find(Ex_orig.Current());
06781     OCCQueryEngine::instance()->OCCMap->UnBind(Ex_orig.Current());
06782     OCCQueryEngine::instance()->OCCMap->Bind(Ex.Current(), k);
06783     OCCLoop* wire = (OCCLoop*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
06784     wire->set_TopoDS_Wire(TopoDS::Wire(Ex.Current()));
06785   }
06786 
06787   Ex.Init(S, TopAbs_EDGE);
06788   Ex_orig.Init(*orig_S, TopAbs_EDGE);
06789   for (; Ex_orig.More(), Ex.More(); Ex_orig.Next(), Ex.Next())
06790   {
06791     k = OCCQueryEngine::instance()->OCCMap->Find(Ex_orig.Current());
06792     OCCQueryEngine::instance()->OCCMap->UnBind(Ex_orig.Current());
06793     OCCQueryEngine::instance()->OCCMap->Bind(Ex.Current(), k);
06794     OCCCurve* edge = (OCCCurve*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
06795     edge->set_TopoDS_Edge(TopoDS::Edge(Ex.Current()));
06796   }
06797 
06798   Ex.Init(S, TopAbs_VERTEX);
06799   Ex_orig.Init(*orig_S, TopAbs_VERTEX);
06800   for (; Ex_orig.More(), Ex.More(); Ex_orig.Next(), Ex.Next())
06801   {
06802     k = OCCQueryEngine::instance()->OCCMap->Find(Ex_orig.Current());
06803     OCCQueryEngine::instance()->OCCMap->UnBind(Ex_orig.Current());
06804     OCCQueryEngine::instance()->OCCMap->Bind(Ex.Current(), k);
06805     OCCPoint* point = (OCCPoint*)(OCCQueryEngine::instance()->OccToCGM->find(k))->second;
06806     point->set_TopoDS_Vertex(TopoDS::Vertex(Ex.Current()));
06807   }
06808   return CUBIT_SUCCESS;
06809 }
06810     
06811 
06812 
06813 //===============================================================================
06814 // Function   : split_periodic
06815 // Member Type: PUBLIC
06816 // Description: 
06817 // Author     : John Fowler
06818 // Date       : 10/02
06819 //===============================================================================
06820 CubitStatus OCCModifyEngine::split_periodic( BodySM * /*body_ptr*/,
06821                                                BodySM *& /*new_body*/ )
06822 {
06823   return CUBIT_FAILURE;
06824 }
06825 
06826 //===============================================================================
06827 // Function   : regularize_body
06828 // Member Type: PUBLIC
06829 // Description: 
06830 // Author     : John Fowler
06831 // Date       : 10/02
06832 //===============================================================================
06833 CubitStatus    OCCModifyEngine::regularize_body( BodySM * /*body_ptr*/,
06834                                                    BodySM *& /*new_body_ptr*/ )
06835 {
06836   PRINT_ERROR("Option not supported for OCC based geometry.\n");
06837   return CUBIT_FAILURE;
06838 }
06839 
06840 //===============================================================================
06841 // Function   : regularize_refentity
06842 // Member Type: PUBLIC
06843 // Description: 
06844 // Author     : John Fowler
06845 // Date       : 10/02
06846 //===============================================================================
06847 CubitStatus  OCCModifyEngine::regularize_entity( GeometryEntity * /*old_entity_ptr*/,  
06848                                                       BodySM *& /*new_body_ptr*/ )
06849 {
06850   PRINT_ERROR("Option not supported for OCC based geometry.\n");
06851   return CUBIT_FAILURE;
06852 }
06853 
06854 //===============================================================================
06855 // Function   : offset_curves
06856 // Member Type: PUBLIC
06857 // Description: 
06858 // Author     : Jane Hu
06859 // Date       : 12/08
06860 //===============================================================================
06861 CubitStatus OCCModifyEngine::offset_curves( DLIList<Curve*>& curves, 
06862                                             DLIList<Curve*>& new_curves,
06863                                             double offset_distance,
06864                                             const CubitVector& offset_direction, 
06865                                             int gap_type )
06866 {
06867   //gap_type has no effect here.
06868   if( curves.size() == 1 && (offset_direction.x() ||
06869         offset_direction.y() || offset_direction.z()) )
06870   {
06871     gp_Dir offset(offset_direction.x(), offset_direction.y(), offset_direction.z());
06872     //check if the curve is straight, error out for non-straight curve.
06873     Curve* curve = curves.get();
06874     OCCCurve* occ_curve = CAST_TO(curve, OCCCurve);
06875     if(occ_curve->geometry_type() == STRAIGHT_CURVE_TYPE)
06876     {
06877       //based on the definitions of the offset curve on OCC, calculate the
06878       //offset direction to make it consistant with
06879       double u1, u2;
06880       occ_curve->get_param_range(u1, u2);
06881       CubitVector p1, p2, tangent;
06882       occ_curve->position_from_u(u1, p1);
06883       occ_curve->position_from_u(u2, p2);
06884       tangent = p2 -p1;
06885       CubitVector cal_offset_dir =  offset_direction * tangent;
06886       gp_Dir offset(cal_offset_dir.x(), cal_offset_dir.y(), cal_offset_dir.z()); 
06887       TopoDS_Edge * edge = occ_curve->get_TopoDS_Edge();
06888       Standard_Real first;
06889       Standard_Real last;
06890       Handle(Geom_Curve) myCurve = BRep_Tool::Curve(*edge, first, last);
06891       Handle(Geom_OffsetCurve) new_curve =
06892         new Geom_OffsetCurve(myCurve,offset_distance, offset);
06893       if(!new_curve)
06894       {
06895         TopologyEntity *entity = curve->topology_entity();
06896         BasicTopologyEntity *bte = CAST_TO(entity, BasicTopologyEntity);
06897         PRINT_ERROR("Can't create offset curve for curve %d.\n", bte->id());
06898         return CUBIT_FAILURE;
06899       }
06900       TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(new_curve, u1, u2);
06901       Curve* offset_curve = OCCQueryEngine::instance()->populate_topology_bridge(new_edge, CUBIT_TRUE);
06902       new_curves.append(offset_curve);
06903       return CUBIT_SUCCESS;
06904     }
06905     else
06906       PRINT_WARNING( "Direction qualifier ignored - only valid for one straight curve\n" );
06907   }
06908 
06909   else if( offset_direction.x() || offset_direction.y() || offset_direction.z() )
06910       PRINT_WARNING( "Direction qualifier ignored - only valid for one straight curve\n" );
06911 
06912   else if (offset_direction.x() == 0.0 && offset_direction.y() == 0.0 &&
06913            offset_direction.z() == 0.0)
06914   {
06915     for(int i = 0 ; i < curves.size(); i++)
06916     {
06917       Curve* curve = curves.get_and_step();
06918       OCCCurve* occ_curve = CAST_TO(curve, OCCCurve);
06919       if(occ_curve->geometry_type() == STRAIGHT_CURVE_TYPE)
06920       {
06921         // TODO: Remove this condition?
06922         // A planar nonlinear wire consisting of straight curves can be offset
06923         // but it isn't clear that the intent was to offset a wire instead
06924         // of each curve individually.
06925         PRINT_ERROR("Must have an offset direction for any straight curve.\n");
06926         return CUBIT_FAILURE;
06927       }
06928     }
06929   }
06930   //make wire out of ref_edge_list
06931   BRepBuilderAPI_MakeWire awire;
06932   TopTools_ListOfShape L;
06933   OCCCurve* occ_curve = NULL;
06934   BRepBuilderAPI_Copy shapeCopier;
06935   for(int i = 0 ; i < curves.size(); i++)
06936   {
06937     Curve* curve = curves.get_and_step();
06938     occ_curve = CAST_TO(curve, OCCCurve);
06939     if(!occ_curve)
06940       continue;
06941     shapeCopier.Perform(*(occ_curve->get_TopoDS_Edge()));
06942     L.Append(shapeCopier.Shape());
06943   }
06944 
06945   awire.Add(L);
06946   if(awire.Error())
06947   {
06948     PRINT_ERROR("Curves must form a planar chain in order for offset to work.\n");
06949     return CUBIT_FAILURE;
06950   }
06951   TopoDS_Wire wire;
06952   wire = awire.Wire();
06953 
06954 #if OCC_VERSION_MAJOR < 6 || (OCC_VERSION_MAJOR == 6 && OCC_VERSION_MINOR < 8)
06955   CubitBoolean closed = wire.Closed();
06956   BRepOffsetAPI_MakeOffset offCurveBuilder(wire);
06957   offCurveBuilder.Perform(offset_distance);
06958   offCurveBuilder.Build();
06959 
06960   // Prior to OCC version 6.8 / OCE version 0.17
06961   // For an open wire:
06962   // It returns a closed wire, with two connecting curves and a positive offset
06963   // curve list and a negative offset curve list.
06964   // For a closed wire:
06965   // It returns a closed wire outside the original one if offset_distance > 0
06966   // It returns a closed wire inside the original one if offset_distance < 0
06967 
06968   TopoDS_Shape offWireShape = offCurveBuilder.Shape();
06969   wire = TopoDS::Wire(offWireShape);
06970 
06971   if (!closed)
06972   {
06973     int num_curves = countEdges(wire);
06974     if (num_curves != (2 + 2*curves.size()) )
06975     {
06976       PRINT_ERROR("Opencascade can't calculate one offset curve for each"
06977                   " input curve. It's a limitation, try to use another type"
06978                   " of curve to offset.\n");
06979       return CUBIT_FAILURE;
06980     }
06981 
06982     BRepTools_WireExplorer Ex(wire);
06983     Ex.Next(); // omit the initial cap/connecting curve
06984     for (int i = 0; i < curves.size(); ++i)
06985     {
06986       TopoDS_Edge new_edge = Ex.Current();
06987       Curve* curve = curves.get_and_step();
06988       Curve* offset_curve = OCCQueryEngine::instance()->
06989           populate_topology_bridge(new_edge, CUBIT_TRUE);
06990       // double check here to make sure we get the correct offset curve
06991       // which is if the offset_distance is positive, the new curve should
06992       // be longer than the original curve.
06993       if (i == 0)
06994       {
06995         double d_offset = offset_curve->measure();
06996         double d_orig = curve->measure();
06997         if ((offset_distance > 0 && d_offset < d_orig) ||
06998             (offset_distance < 0 && d_offset > d_orig))
06999         {
07000           for (int j = 0; j < curves.size(); ++j)
07001           {
07002             Ex.Next();
07003           }
07004           Ex.Next();
07005         }
07006         new_edge = Ex.Current();
07007         offset_curve = OCCQueryEngine::instance()->
07008             populate_topology_bridge(new_edge, CUBIT_TRUE);
07009       }
07010       new_curves.append(offset_curve);
07011       Ex.Next();
07012     }
07013 
07014     // successful offset of open wire
07015     return CUBIT_SUCCESS;
07016   }
07017 
07018   // if wire is closed
07019   for (BRepTools_WireExplorer Ex(wire); Ex.More(); Ex.Next())
07020   {
07021     TopoDS_Edge new_edge = Ex.Current();
07022     Curve* offset_curve = OCCQueryEngine::instance()->
07023         populate_topology_bridge(new_edge, CUBIT_TRUE);
07024     new_curves.append(offset_curve);
07025   }
07026 
07027   // successful offset of closed wire
07028   return CUBIT_SUCCESS;
07029 
07030 #else
07031 
07032   // The behavior changed as of OCC 6.8 and OCE 0.17.
07033   // Not all cases have been tested.
07034   // Documentation in BRepFill_OffsetWire, which is used by
07035   // BRepOffsetAPI_MakeOffset, says that an offset will be "to the left"
07036   // of the spine wire, with each point at the specified offset from the
07037   // the closest point on the original wire.
07038   // Negative offsets are "to the right."
07039   // "Left" and "right" imply a normal direction on the face that contains
07040   // the wire.
07041   // The contract for this method in CGM is not documented well, but the
07042   // previous implementation suggests that a negative offset is intended
07043   // to return the shorter of the two open offset curves.  That may not be
07044   // well defined, and is hard to interpret when there are multiple
07045   // edges in the wire.
07046   //
07047   // When testing the offset functionality in a recent release version of
07048   // Cubit, it seemed that the direction of the offset depends on
07049   // how the wire turns.  If a closed wire has a positive turning number or
07050   // an open wire has what might be called a positive turning angle, then
07051   // the positive offset is to the right.  If the turning angle was
07052   // negative, then the positive offset was consistently to the left.
07053   // This behavior is independent of normal direction, since what appears
07054   // to be right and positive turning angle from one normal direction becomes
07055   // left and negative turning angle when the normal direction is flipped.
07056 
07057   // The current implementation here returns the result only if the number of
07058   // offset curves matches the number of input curves for both the
07059   // positive and negative offset.  In that situation, both the positive
07060   // and negative offsets are computed, the length of each wire is
07061   // computed, and the shorter result is returned if the offset is
07062   // negative.  The longer result is returned if the offset is positive.
07063   // If the lengths are equal then the curve(s) that OCC computed for the
07064   // offset with the same sign as the input offset are used.  This is
07065   // quite different from the behavior of Cubit, but passes the previously
07066   // existing offset_curves test and agrees with the local in-method
07067   // documentation that existed prior to OCC 6.8.
07068 
07069   // The WireExplorer is used in this method, which may miss some edges
07070   // if the result wire does not have all edges connected end to end.
07071 
07072   double positiveOffset = fabs(offset_distance);
07073   BRepOffsetAPI_MakeOffset posOffCurveBldr(wire);
07074   // Using an open offset, as in the following line, seems to produce results
07075   // closer to the original intent of this method, but the original behavior is
07076   // preserved better with the default Standard_False closed offset.
07077 //  BRepOffsetAPI_MakeOffset posOffCurveBldr(wire, GeomAbs_Arc, Standard_True);
07078   posOffCurveBldr.Perform(positiveOffset);
07079   TopoDS_Shape posOffShape = posOffCurveBldr.Shape();
07080   TopoDS_Wire posOffWire = TopoDS::Wire(posOffShape);
07081   if (countEdges(posOffWire) != curves.size())
07082   {
07083       PRINT_ERROR("The number of positive offset curves computed by the OCE"
07084                   " geometry engine does not equal the number of curves in"
07085                   " the input.\n");
07086       // Remark: It appears to be possible to match curves in the output
07087       // to curves in the input by calling BRepOffsetAPI_MakeOffset::Generated.
07088       // One could also directly use BRepFill_OffsetWire.
07089       // Perhaps compounds curves could be constructed to make the
07090       // result curves match the input.
07091       return CUBIT_FAILURE;
07092   }
07093 
07094   double negativeOffset = -1.0*positiveOffset;
07095   BRepOffsetAPI_MakeOffset negOffCurveBldr(wire);
07096   // Using an open offset, as in the following line, seems to produce results
07097   // closer to the original intent of this method, but the original behavior is
07098   // preserved better with the default Standard_False closed offset.
07099 //  BRepOffsetAPI_MakeOffset negOffCurveBldr(wire, GeomAbs_Arc, Standard_True);
07100   negOffCurveBldr.Perform(negativeOffset);
07101   TopoDS_Shape negOffShape = negOffCurveBldr.Shape();
07102   TopoDS_Wire negOffWire = TopoDS::Wire(negOffShape);
07103   if (countEdges(negOffWire) != curves.size())
07104   {
07105       PRINT_ERROR("The number of negative offset curves computed by the OCE"
07106                   " geometry engine does not equal the number of curves in"
07107                   " the input.\n");
07108       return CUBIT_FAILURE;
07109   }
07110 
07111   // compute wire lengths and choose which wire to return
07112   TopoDS_Wire* wirePtrs[2];
07113   double wireLengths[2];
07114   wirePtrs[0] = &posOffWire;
07115   wirePtrs[1] = &negOffWire;
07116   wireLengths[0] = wireLengths[1] = 0.0;
07117 
07118   for (int wireIndex = 0; wireIndex < 2; ++wireIndex)
07119   {
07120     TopoDS_Wire* wirePtr = wirePtrs[wireIndex];
07121     double wireLen = 0.0;
07122     for (BRepTools_WireExplorer Ex(*wirePtr); Ex.More(); Ex.Next())
07123     {
07124       GProp_GProps edgeProps;
07125       BRepGProp::LinearProperties(Ex.Current(), edgeProps);
07126       wireLen += edgeProps.Mass();
07127     }
07128     wireLengths[wireIndex] = wireLen;
07129   }
07130 
07131   TopoDS_Wire* chosenWirePtr = wirePtrs[0];
07132   if (offset_distance >= 0)
07133   {
07134     if (wireLengths[1] > wireLengths[0])
07135       chosenWirePtr = wirePtrs[1];
07136   }
07137   else if (wireLengths[1] <= wireLengths[0])
07138     chosenWirePtr = wirePtrs[1];
07139 
07140   for (BRepTools_WireExplorer Ex(*chosenWirePtr); Ex.More(); Ex.Next())
07141   {
07142     Curve* offset_curve = OCCQueryEngine::instance()->
07143         populate_topology_bridge(Ex.Current(), CUBIT_TRUE);
07144     new_curves.append(offset_curve);
07145   }
07146   return CUBIT_SUCCESS;
07147 #endif
07148 }
07149 
07150 //=============================================================================
07151 // Function   : countEdges
07152 // Member Type: private
07153 // Description: Count the number of edges encountered by a
07154 //     BRepTools_WireExplorer exploration of the specified wire.
07155 //=============================================================================
07156 int OCCModifyEngine::countEdges(TopoDS_Wire &wire)
07157 {
07158   int numEdges = 0;
07159   for (BRepTools_WireExplorer Ex(wire); Ex.More(); Ex.Next())
07160     ++numEdges;
07161   return numEdges;
07162 }
07163 
07164 //===============================================================================
07165 // Function   : trim_curve
07166 // Member Type: PUBLIC
07167 // Description: 
07168 // Author     : Jane Hu
07169 // Date       : 12/08
07170 //===============================================================================
07171 Curve* OCCModifyEngine::trim_curve( Curve* trim_curve, 
07172                                     const CubitVector& trim_vector,
07173                                     const CubitVector& keep_vector,
07174                                     bool keep )
07175 {
07176   OCCCurve* occ_crv = CAST_TO(trim_curve, OCCCurve);
07177   if(!occ_crv) 
07178   {
07179     PRINT_ERROR("This is not a OCC curve to be trimmed.\n");
07180     return (Curve*)NULL;
07181   }
07182   
07183   //Determine the trimmed curve's parameter range.
07184   double u1, u2;
07185   occ_crv->get_param_range(u1, u2);
07186   double trim_u = occ_crv->u_from_position(trim_vector);
07187   double keep_u = occ_crv->u_from_position(keep_vector);
07188   if(trim_u > u2+TOL || trim_u < u1 - TOL)
07189   {
07190     PRINT_ERROR("The trim_vector is outside of the curve range.\n");
07191     return (Curve*)NULL;
07192   }
07193  
07194   if(keep_u > trim_u )
07195      u1 =  trim_u;
07196   else if(keep_u < trim_u)
07197      u2 = trim_u;
07198 
07199   else
07200   {
07201     PRINT_ERROR("Can't determine which part of the curve to be kept.\n");
07202     return (Curve*)NULL;
07203   }
07204   //get the Geom_Curve of the OCCCurve
07205   TopoDS_Edge * edge = occ_crv->get_TopoDS_Edge();
07206   Standard_Real first;
07207   Standard_Real last;
07208   Handle(Geom_Curve) myCurve = BRep_Tool::Curve(*edge, first, last);
07209  
07210   //Trim the curve
07211   TopoDS_Edge t_edge = BRepBuilderAPI_MakeEdge(myCurve, u1, u2);
07212   Curve* t_curve = OCCQueryEngine::instance()->populate_topology_bridge(t_edge, CUBIT_TRUE);  
07213   if(!keep)
07214   {
07215     DLIList<OCCLoop*> loops = occ_crv->loops();
07216     if(loops.size() == 0)
07217       OCCQueryEngine::instance()->delete_solid_model_entities(trim_curve);
07218   }
07219   return t_curve;
07220 }
07221 
07222 //===============================================================================
07223 // Function   : create_body_from_surfs
07224 // Member Type: PUBLIC
07225 // Description:
07226 // Author     : Jane Hu
07227 // Date       : 4/22/08
07228 //===============================================================================
07229 CubitStatus OCCModifyEngine::create_solid_bodies_from_surfs(DLIList<Surface*> & ref_face_list,
07230                                           DLIList<BodySM*>& new_bodies,
07231                                           bool keep_old,
07232                                           bool heal,
07233                                           bool sheet) const
07234 {
07235   //keep_old and heal are ignored, always delete old.
07236   //all surfaces should be stand along surface bodies or shell bodies' surface
07237   CubitStatus stat = CUBIT_SUCCESS;
07238   if(!sheet)
07239   {
07240     Lump* lump = make_Lump(ref_face_list);
07241     if (!lump)
07242       return CUBIT_FAILURE;
07243   
07244     new_bodies.append(CAST_TO(lump, OCCLump)->get_body());
07245   }
07246  
07247   else
07248   {
07249     DLIList<BodySM*> bodies;
07250     for(int i = 0 ; i < ref_face_list.size(); i++)
07251     {
07252       OCCSurface* surf = CAST_TO(ref_face_list.get_and_step(), OCCSurface);
07253       BodySM* body = surf->my_body();
07254       if(body)
07255         bodies.append_unique(body);
07256     }
07257     stat = unite(bodies, new_bodies, keep_old); 
07258   }
07259   return stat;
07260 }
07261 
07262 //===============================================================================
07263 // Function   : create_arc_three
07264 // Member Type: PUBLIC
07265 // Description: 
07266 // Author     : Jane Hu
07267 // Date       : 12/08
07268 //===============================================================================
07269 Curve* OCCModifyEngine::create_arc_three( TBPoint* pt1, 
07270                                           TBPoint* pt2,
07271                                           TBPoint* pt3, 
07272                                           bool full,
07273                                           bool preview )
07274 { 
07275   Curve* new_curve = NULL;
07276   if(!full)
07277   {
07278     CubitVector v2(pt2->coordinates());
07279     new_curve = const_cast<OCCModifyEngine*> (this)->
07280                   make_Curve(ARC_CURVE_TYPE,pt1,pt3, &v2);
07281   }
07282   else
07283   {
07284     CubitVector v1(pt1->coordinates());
07285     CubitVector v2(pt2->coordinates());
07286     CubitVector v3(pt3->coordinates());
07287 
07288     gp_Pnt gp_pt1(v1.x(),v1.y(), v1.z());
07289     gp_Pnt gp_pt2(v2.x(),v2.y(), v2.z());
07290     gp_Pnt gp_pt3(v3.x(),v3.y(), v3.z());
07291 
07292     Handle(Geom_Circle) curve_ptr;
07293     curve_ptr = GC_MakeCircle(gp_pt1,gp_pt2,gp_pt3); 
07294 
07295     OCCPoint* occ_pt1 = CAST_TO(const_cast<TBPoint*>(pt1),OCCPoint);
07296     TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex();
07297     TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt1);
07298     new_curve = OCCQueryEngine::instance()->populate_topology_bridge(new_edge,
07299                                                                    CUBIT_TRUE);
07300   }
07301   if(preview)
07302   {
07303     GfxPreview::clear();
07304     OCCCurve* occ_curve = CAST_TO(new_curve, OCCCurve);
07305     TopoDS_Edge* h_edge = occ_curve->get_TopoDS_Edge();
07306     // Draw this edge
07307     OCCDrawTool::instance()->draw_EDGE( h_edge, CUBIT_BLUE_INDEX, CUBIT_TRUE );
07308      
07309     OCCQueryEngine::instance()->delete_solid_model_entities(new_curve);
07310     return (Curve*) NULL;
07311   }
07312   else
07313     return new_curve;
07314 }
07315 
07316 //===============================================================================
07317 // Function   : create_arc_three
07318 // Member Type: PUBLIC
07319 // Description: 
07320 // Author     : Jane Hu
07321 // Date       : 12/08
07322 //===============================================================================
07323 Curve* OCCModifyEngine::create_arc_three( Curve* curve1, 
07324                                           Curve* curve2,
07325                                           Curve* curve3, 
07326                                           bool full, 
07327                                           bool preview  )
07328 { 
07329   OCCCurve* occ_crv1 = CAST_TO(curve1, OCCCurve);
07330   OCCCurve* occ_crv2 = CAST_TO(curve2, OCCCurve);
07331   OCCCurve* occ_crv3 = CAST_TO(curve3, OCCCurve);
07332   GeometryType type1 = occ_crv1->geometry_type();
07333   GeometryType type2 = occ_crv2->geometry_type();
07334   GeometryType type3 = occ_crv3->geometry_type();
07335   if(type1 != STRAIGHT_CURVE_TYPE || type2 != STRAIGHT_CURVE_TYPE ||
07336      type3 != STRAIGHT_CURVE_TYPE)
07337   {
07338     PRINT_WARNING("Need three straight curves to calculate incenter.\n");
07339     return (Curve*) NULL;
07340   } 
07341   
07342   //0.check that non of the curves are parallel of each other.
07343   DLIList<CubitVector> intscts;
07344   CubitVector vt1, vt2, vt3;
07345   CubitBoolean none = CUBIT_FALSE;
07346   OCCQueryEngine::instance()->get_intersections(curve1, curve2, intscts,none,none);
07347   vt1 = intscts.get();
07348   intscts.clean_out();
07349   OCCQueryEngine::instance()->get_intersections(curve2,curve3, intscts,none,none);
07350   vt2 = intscts.get();
07351   intscts.clean_out();
07352   OCCQueryEngine::instance()->get_intersections(curve3, curve1, intscts,none,none);
07353   vt3 = intscts.get();
07354 
07355   double u11, u12, u21, u22, u31, u32;
07356   occ_crv1->get_param_range(u11, u12);
07357   occ_crv2->get_param_range(u21, u22);
07358   occ_crv3->get_param_range(u31, u32);
07359 
07360   CubitVector tangent1, tangent2, tangent3;
07361   occ_crv1->get_tangent(vt1, tangent1);
07362   occ_crv2->get_tangent(vt2, tangent2);
07363   occ_crv3->get_tangent(vt3, tangent3); 
07364 
07365   CubitVector normal1 = tangent1 * tangent2;
07366   CubitVector normal2 = tangent2 * tangent3;
07367   CubitVector normal3 = tangent3 * tangent1;
07368   if( normal1.length()< TOL || normal2.length()< TOL ||
07369       normal3.length() < TOL )
07370   {
07371     PRINT_WARNING("Three curves must be able to form a triangle.\n");
07372     return (Curve*) NULL;
07373   }
07374 
07375   //normals must parallel to each other, meaning all curves must be on
07376   //the same plane.
07377   normal1.normalize();
07378   normal2.normalize();
07379   normal3.normalize();
07380   
07381   CubitVector parallel1 = normal1 * normal2;
07382   CubitVector parallel2 = normal2 * normal3;
07383   CubitVector parallel3 = normal3 * normal1;
07384   if(parallel1.length() > TOL || parallel2.length() > TOL ||
07385      parallel3.length() > TOL)
07386   {
07387     PRINT_WARNING("Three curves must be able to form a triangle.\n");
07388     return (Curve*) NULL;
07389   }
07390   //1.find the angle between each of the two curves
07391   double angle1, angle2, angle3;
07392   angle1 = tangent1.interior_angle(tangent2);
07393   angle2 = tangent2.interior_angle(tangent3);
07394   angle3 = tangent3.interior_angle(tangent1);
07395 
07396   //2.create curves to bisection each of the angle passing through the
07397   // vertices of the triangle
07398   CubitVector t_curve11 = 
07399          vectorRotate(angle1/2.0, normal1, tangent1);  
07400   t_curve11.normalize();
07401   CubitVector p11 = vt1+t_curve11;
07402 
07403   CubitVector t_curve12 = 
07404          vectorRotate(90.0 - angle1/2.0, -normal1, tangent1);
07405   t_curve12.normalize();
07406   CubitVector p12 = vt1 + t_curve12;
07407 
07408   CubitVector t_curve21 =
07409          vectorRotate(angle2/2.0, normal2, tangent2);
07410   t_curve21.normalize();
07411   CubitVector p21 = vt2 + t_curve21;
07412 
07413   CubitVector t_curve22 = 
07414          vectorRotate(90.0 - angle2/2.0, -normal2, tangent2);
07415   t_curve22.normalize();
07416   CubitVector p22 = vt2 + t_curve22;
07417 
07418   CubitVector t_curve31 = 
07419          vectorRotate(angle3/2.0, normal3, tangent3);
07420   t_curve31.normalize();
07421 
07422   CubitVector t_curve32 =
07423          vectorRotate(90.0 - angle3/2.0, -normal3, tangent3);
07424   t_curve32.normalize();
07425 
07426   //3. find the three intersection points which when connected with the vertices,
07427   //intersect at same point.
07428   CubitVector line_p[4], c_p[4], c_ptemp;
07429   double sc, tc;
07430 
07431   IntersectionTool int_tool;
07432   for(int i = 0; i < 4; i++)
07433   {
07434     if( i == 0)
07435     {
07436       line_p[0] = vt1;
07437       line_p[1] = p11;
07438       line_p[2] = vt2;
07439       line_p[3] = p21;
07440     } 
07441     else if(i == 1)
07442       line_p[3] = p22;
07443     else if(i == 2)
07444       line_p[1] = p12;
07445     else
07446       line_p[3] = p21;  
07447     int_tool.closest_points_on_segments(line_p[0], line_p[1], line_p[2],
07448                     line_p[3], c_ptemp, c_p[i], sc, tc);
07449         
07450     //check if the closeset point from c_p[i] to three curves are on three curves
07451     CubitVector closest1, closest2, closest3;
07452     occ_crv1->closest_point(c_p[i], closest1);
07453     double u = occ_crv1->u_from_position(closest1);
07454     if(u > u11-TOL && u < u12 + TOL)
07455     {
07456       occ_crv2->closest_point(c_p[i], closest2);
07457       u = occ_crv2->u_from_position(closest2);
07458       if(u > u21 - TOL && u < u22 + TOL)
07459       {
07460         occ_crv3->closest_point(c_p[i], closest3);
07461         u = occ_crv3->u_from_position(closest3);
07462         if(u > u31 - TOL && u < u32 + TOL)
07463         {
07464         //4. use the 3 intersection points to find the arc or circle.
07465           OCCPoint occ_p1(closest1);
07466           OCCPoint occ_p2(closest2);     
07467           OCCPoint occ_p3(closest3);
07468           return create_arc_three(&occ_p1, &occ_p2, &occ_p3, full, preview);
07469         } 
07470       }
07471     }
07472   }
07473   PRINT_ERROR("Can't find the tangent points to create circle.\n");
07474   return (Curve*) NULL;
07475 } 
07476 
07477 //===============================================================================
07478 // Function   : create_arc_center_edge
07479 // Member Type: PUBLIC
07480 // Description: 
07481 // Author     : Jane Hu
07482 // Date       : 12/08
07483 //===============================================================================
07484 Curve* OCCModifyEngine::create_arc_center_edge( TBPoint* pt1, 
07485                                                 TBPoint* pt2,
07486                                                 TBPoint* pt3,
07487                                                 const CubitVector& normal, 
07488                                                 double radius,
07489                                                 bool full,
07490                                                 bool preview ) 
07491 { 
07492   CubitVector vec1 = pt1->coordinates(); // Center of arc
07493   CubitVector vec2 = pt2->coordinates(); // Position on arc
07494   CubitVector vec3 = pt3->coordinates(); // Position on arc
07495 
07496   CubitVector dir1( vec1, vec2 );
07497   CubitVector dir2( vec1, vec3 );
07498   // Re-adjust vec2, vec3 if radius was given
07499   if( radius != CUBIT_DBL_MAX )
07500   {
07501      CubitVector vec;
07502      vec1.next_point( dir1, radius, vec );
07503      if(vec.distance_between(vec2) > TOL)
07504      {
07505        vec2 = vec;
07506        pt2 = new OCCPoint(vec);
07507      }
07508      vec1.next_point( dir2, radius, vec );
07509      if(vec.distance_between(vec3) > TOL)
07510      {
07511        vec3 = vec;
07512        pt3 = new OCCPoint(vec);
07513      }
07514   }
07515  
07516   else
07517   {
07518     radius = vec1.distance_between(vec2);
07519     CubitVector vec;
07520     vec1.next_point( dir2, radius, vec );
07521     if(vec.distance_between(vec3) > TOL)
07522     {
07523        vec3 = vec;
07524        pt3 = new OCCPoint(vec);
07525     }
07526   }
07527  
07528   CubitVector normal_dir = normal;
07529   if(normal_dir.length() > TOL)
07530   {
07531     normal_dir.normalize();
07532     //verify sense
07533     if((dir1 * dir2) % normal_dir < 0.0)
07534     {
07535       TBPoint* p = pt2;
07536       pt2 = pt3;
07537       pt3 = p;
07538     }
07539     else if((dir1 * dir2) % normal_dir == 0.0)
07540     {
07541       PRINT_ERROR("Normal can't be on the plan of the arc.\n");
07542       return (Curve*) NULL;
07543     }
07544   } 
07545   else 
07546   {
07547     normal_dir = dir1 * dir2;
07548     normal_dir.normalize();
07549   }
07550  
07551   Handle(Geom_Circle) curve_ptr;
07552   gp_Dir norm(normal_dir.x(), normal_dir.y(), normal_dir.z());
07553   gp_Pnt center = gp_Pnt( vec1.x(), vec1.y(), vec1.z());
07554   curve_ptr = GC_MakeCircle(center,norm,radius);
07555 
07556   OCCPoint* occ_pt1 = CAST_TO(const_cast<TBPoint*>(pt2),OCCPoint);
07557   TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex();
07558   TopoDS_Edge new_edge;
07559   if(full)
07560     new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt1);
07561   
07562   else
07563   {
07564     Handle(Geom_TrimmedCurve) arc;
07565     gp_Pnt on_arc1 = gp_Pnt( vec2.x(), vec2.y(), vec2.z());
07566     gp_Pnt on_arc2 = gp_Pnt( vec3.x(), vec3.y(), vec3.z());
07567     arc = GC_MakeArcOfCircle(curve_ptr->Circ(), on_arc1, on_arc2, Standard_True);
07568     OCCPoint* occ_pt2 = CAST_TO(const_cast<TBPoint*>(pt3),OCCPoint); 
07569     TopoDS_Vertex * vt2 = occ_pt2->get_TopoDS_Vertex();
07570     new_edge = BRepBuilderAPI_MakeEdge(arc, *vt1, *vt2);
07571   } 
07572 
07573   if(preview)
07574   {
07575     GfxPreview::clear();
07576     // Draw this edge
07577     OCCDrawTool::instance()->draw_EDGE( &new_edge, CUBIT_BLUE_INDEX, CUBIT_TRUE );
07578     return (Curve*) NULL;
07579   }
07580   return OCCQueryEngine::instance()->populate_topology_bridge(new_edge);
07581 }
07582 
07583 //===============================================================================
07584 // Function   : create_curve_combine
07585 // Member Type: PUBLIC
07586 // Description: create a curve of combination of several curves.  
07587 // Author     : Jane Hu 
07588 // Date       : 03/09
07589 //===============================================================================
07590 
07591 CubitStatus 
07592 OCCModifyEngine::create_curve_combine( DLIList<Curve*>& curve_list, 
07593                                     Curve *&new_curve_ptr )
07594 {
07595   int i;
07596 
07597   DLIList<OCCCurve*> occ_curves(curve_list.size());
07598   CAST_LIST( curve_list, occ_curves, OCCCurve );
07599   if (curve_list.size() != occ_curves.size())
07600   {
07601     PRINT_ERROR("In OCCModifyEngine::create_curve_combine\n"
07602                 "       Not all input curves are OCC Curves.\n");
07603     return CUBIT_FAILURE;
07604   }
07605   
07606   BRepBuilderAPI_MakeWire aWire(*(occ_curves.get_and_step()->get_TopoDS_Edge()));
07607   for(i =1 ; i < curve_list.size(); i++)
07608   {
07609     OCCCurve* curve = occ_curves.get_and_step();
07610     TopoDS_Edge* edge = curve->get_TopoDS_Edge();
07611       aWire.Add(*edge);
07612     if(!aWire.IsDone())
07613     {
07614       PRINT_ERROR("In OCCModifyEngine::create_curve_combine\n"
07615                 "       The curves are not all connected.\n");
07616       return CUBIT_FAILURE;
07617     }
07618   }
07619   TopoDS_Wire wire = aWire.Wire(); 
07620   BRepAdaptor_CompCurve comp_curve(wire);
07621   GeomAbs_CurveType type = comp_curve.GetType();
07622   GeomAbs_Shape cont = comp_curve.Continuity();
07623   if(cont < GeomAbs_G1)
07624   {
07625     PRINT_ERROR("In OCCModifyEngine::create_curve_combine\n"
07626                 "       The combined curve is not G1 continued.\n");
07627     return CUBIT_FAILURE;
07628   }
07629 
07630   //find the start/end vertices for the combined curve.
07631   double first_u = comp_curve.FirstParameter();
07632   double last_u = comp_curve.LastParameter();
07633   gp_Pnt first = comp_curve.Value(first_u);
07634   gp_Pnt last = comp_curve.Value(last_u);
07635   CubitVector first_v(first.X(), first.Y(), first.Z());
07636   CubitVector last_v(last.X(), last.Y(), last.Z());
07637   if(first_v.about_equal(last_v))
07638     comp_curve.SetPeriodic(Standard_True);
07639 
07640   DLIList<CubitVector> v_list;
07641   v_list.append(first_v);
07642   v_list.append(last_v);
07643   v_list.reset();
07644 
07645   DLIList<gp_Pnt*> V_list;
07646   for(int j = 0; j < 2; j++)
07647   {
07648     DLIList<TopologyBridge*> children;
07649     if (j == 0)
07650       occ_curves.reset();
07651     else
07652       occ_curves.last();
07653     occ_curves.get()->get_children_virt(children);
07654     CubitVector v = v_list.get_and_step();
07655     for(i = 0 ; i < children.size(); i++)
07656     {
07657       OCCPoint* vertex = CAST_TO(children.get_and_step(), OCCPoint); 
07658       CubitVector xyz = vertex->coordinates();
07659       if(xyz.about_equal(v))
07660       {
07661         gp_Pnt p ( v.x(), v.y(), v.z());
07662         V_list.append(&p);
07663         break;
07664       }
07665     }
07666   }
07667    
07668   V_list.reset();
07669   TopoDS_Edge topo_edge; 
07670   gp_Lin line;
07671   gp_Circ circle;
07672   gp_Elips ellip;
07673   gp_Hypr hypr;
07674   gp_Parab parab;
07675   Handle_Geom_BezierCurve bezier;
07676   Handle_Geom_BSplineCurve spline;
07677   switch(type)
07678   {
07679     case GeomAbs_Line:
07680       line = comp_curve.Line();
07681       topo_edge = BRepBuilderAPI_MakeEdge(line,*V_list.get_and_step(), *V_list.get() );
07682       break;
07683     case GeomAbs_Circle:
07684       circle = comp_curve.Circle();
07685       topo_edge = BRepBuilderAPI_MakeEdge(circle,*V_list.get_and_step(), *V_list.get() );
07686       break;
07687     case GeomAbs_Ellipse:
07688       ellip = comp_curve.Ellipse();
07689       topo_edge = BRepBuilderAPI_MakeEdge(ellip,*V_list.get_and_step(), *V_list.get() );
07690       break;
07691     case GeomAbs_Hyperbola:
07692       hypr = comp_curve.Hyperbola();
07693       topo_edge = BRepBuilderAPI_MakeEdge(hypr,*V_list.get_and_step(), *V_list.get() );
07694       break;
07695     case GeomAbs_Parabola:
07696       parab = comp_curve.Parabola();
07697       topo_edge = BRepBuilderAPI_MakeEdge(parab,*V_list.get_and_step(), *V_list.get() );
07698       break;
07699     case GeomAbs_BezierCurve:
07700       bezier = comp_curve.Bezier();
07701       topo_edge = BRepBuilderAPI_MakeEdge(bezier,*V_list.get_and_step(), *V_list.get() );
07702       break;
07703     case GeomAbs_BSplineCurve:
07704       spline = comp_curve.BSpline();
07705       topo_edge = BRepBuilderAPI_MakeEdge(spline,*V_list.get_and_step(), *V_list.get() );
07706       break;
07707     default:
07708       PRINT_ERROR("In OCCModifyEngine::create_curve_combine\n"
07709                 "       The combined curve is not G1 continued.\n");
07710       return CUBIT_FAILURE;
07711   }
07712   TopoDS_Edge *topo_edge_ptr = new TopoDS_Edge(topo_edge);
07713   OCCCurve* occ_c = new OCCCurve(topo_edge_ptr);
07714   new_curve_ptr = occ_c;
07715   return CUBIT_SUCCESS;
07716 }
07717 
07718 //===============================================================================
07719 // Function   : get_gqe
07720 // Member Type: PUBLIC
07721 // Description: get the facet geometry query engince instance pointer
07722 // Author     : John Fowler
07723 // Date       : 10/02
07724 //===============================================================================
07725 GeometryQueryEngine *OCCModifyEngine::get_gqe()
07726 {
07727   return OCCQueryEngine::instance();
07728 }
07729 
07730 //===============================================================================
07731 // Function   : is_modify_engine
07732 // Member Type: PUBLIC
07733 // Description: return CUBIT_TRUE if the tb_ptr belongs to this modify engine
07734 // Author     : John Fowler
07735 // Date       : 10/02
07736 //===============================================================================
07737 CubitBoolean OCCModifyEngine::is_modify_engine(const TopologyBridge *tb_ptr) const 
07738 {
07739   return tb_ptr->get_geometry_query_engine() == OCCQueryEngine::instance();
07740 }
07741 
07742 //===============================================================================
07743 // Function   : get_offset_intersections
07744 // Member Type: PUBLIC
07745 // Description: 
07746 // Author     : Jane Hu
07747 // Date       : 03/09
07748 //===============================================================================
07749 CubitStatus OCCModifyEngine::get_offset_intersections( Curve* curve1, 
07750                                               Curve* curve2,
07751                                               DLIList<CubitVector>& out_list,
07752                                               double offset,
07753                                               CubitBoolean ext_first ) 
07754 {
07755   //offset the curve1 in both directions of normal direction of two curves at
07756   //center points.
07757     
07758   return CUBIT_SUCCESS;
07759 }
07760 
07761 //===============================================================================
07762 // Function   : get_offset_intersections
07763 // Member Type: PUBLIC
07764 // Description: 
07765 // Author     : Jane Hu
07766 // Date       : 03/09
07767 //===============================================================================
07768 CubitStatus OCCModifyEngine::get_offset_intersections( Curve* curve1, 
07769                                            Surface* face_ptr,
07770                                            DLIList<CubitVector> & out_list,
07771                                            double offset,
07772                                            CubitBoolean ext_surf )
07773 {
07774   Surface* new_surface = face_ptr;
07775   if(ext_surf)
07776     new_surface = make_Surface(face_ptr, CUBIT_TRUE);
07777 
07778   BodySM* bodysm = NULL;
07779   CubitStatus status = CUBIT_SUCCESS;
07780   status = create_offset_surface(new_surface, bodysm, offset); 
07781   if(status == CUBIT_FAILURE)
07782   {
07783     PRINT_ERROR("Can't offset surface. \n");
07784     return status;
07785   }
07786   DLIList<OCCSurface*> surfaces = CAST_TO(bodysm, OCCBody)->my_sheet_surfaces();
07787   OCCSurface* surface = surfaces.get();
07788   status = OCCQueryEngine::instance()->get_intersections(curve1, surface, out_list);
07789   
07790   if(ext_surf || offset)
07791     OCCQueryEngine::instance()->delete_solid_model_entities(surface);
07792  
07793   //offset surface in opposite direction
07794   if(!offset)
07795     return status;
07796 
07797   status = create_offset_surface(new_surface, bodysm, -offset);
07798   if(status == CUBIT_FAILURE)
07799   {
07800     PRINT_ERROR("Can't offset surface. \n");
07801     return status;
07802   }
07803   surfaces.clean_out();
07804   surfaces = CAST_TO(bodysm, OCCBody)->my_sheet_surfaces();
07805   surface = surfaces.get();
07806   status = OCCQueryEngine::instance()->get_intersections(curve1, surface, out_list);
07807   OCCQueryEngine::instance()->delete_solid_model_entities(surface);
07808   if(ext_surf)
07809     OCCQueryEngine::instance()->delete_solid_model_entities(new_surface);
07810   return status;
07811 }
07812 
07813 //===============================================================================
07814 // Function   : surface_intersection
07815 // Member Type: PUBLIC
07816 // Description: 
07817 // Author     : Jane Hu  
07818 // Date       : 03/09
07819 //===============================================================================
07820 CubitStatus OCCModifyEngine::surface_intersection( Surface * surface1,
07821                                                    Surface * surface2,
07822                                                    DLIList<Curve*> &intscts,
07823                                                    const double tol) const
07824 {
07825   OCCSurface *occ_surface1 =  CAST_TO(surface1, OCCSurface);
07826   if (occ_surface1 == NULL)
07827     {
07828       PRINT_ERROR("Option not supported for non-occ based geometry.\n");
07829       return CUBIT_FAILURE;
07830     }
07831 
07832   OCCSurface *occ_surface2 =  CAST_TO(surface2, OCCSurface);
07833   if (occ_surface2 == NULL)
07834     {
07835       PRINT_ERROR("Option not supported for non-occ based geometry.\n");
07836       return CUBIT_FAILURE;
07837     }
07838   
07839   //currently, there's no effect on 'closest' argument or bounded.
07840   BRepExtrema_DistShapeShape distShapeShape(*(occ_surface1->get_TopoDS_Face()),
07841                                             *(occ_surface2->get_TopoDS_Face()));
07842 
07843   //distShapeShape.Perform();
07844   if (!distShapeShape.IsDone())
07845     {
07846       PRINT_ERROR("Cannot calculate the intersection points for the input curve and surface.\n");
07847       return CUBIT_FAILURE;
07848     }
07849 
07850   if (distShapeShape.Value() < tol) //intersect
07851     {
07852       int numSol = distShapeShape.NbSolution();
07853       for (int i = 1; i <= numSol; i++)
07854         {
07855           TopoDS_Shape shape = distShapeShape.SupportOnShape1(i);
07856           if(shape.ShapeType() != TopAbs_EDGE)
07857             continue;
07858 
07859           TopoDS_Edge* edge = new TopoDS_Edge(TopoDS::Edge(shape));
07860           OCCCurve* cv = new OCCCurve(edge);
07861           intscts.append(cv);
07862         }
07863     }
07864 
07865   return CUBIT_SUCCESS;
07866 }
07867 
07868 //===============================================================================
07869 // Function   : get_3_point_plane
07870 // Member Type: PUBLIC
07871 // Description:
07872 // Author     : Jane Hu
07873 // Date       : 01/11
07874 //===============================================================================
07875 CubitStatus OCCModifyEngine::get_3_point_plane( const CubitVector & point_1,
07876                                             const CubitVector & point_2,
07877                                             const CubitVector & point_3,
07878                                             TopoDS_Face*& p_face)const
07879 {
07880   //Calculate normal of the plane
07881   CubitVector v1, v2, normal;
07882   v1 = point_2 - point_1;
07883   v2 = point_3 - point_1;
07884   normal = ~(v1 * v2);
07885   if(fabs(normal.length() - 1) > TOL)
07886   {
07887      PRINT_ERROR("The three points are co-linear, and can't be used as a cutting plane.\n");
07888      return CUBIT_FAILURE;
07889   }
07890 
07891   gp_Pnt pt = gp_Pnt( point_1.x(), point_1.y(), point_1.z());
07892   gp_Dir normal_dir(normal.x(), normal.y(), normal.z());
07893   gp_Pln plane(pt, normal_dir);
07894 
07895   TopoDS_Face face = BRepBuilderAPI_MakeFace(plane);
07896   p_face = new TopoDS_Face(face);
07897   return CUBIT_SUCCESS;
07898 }
07899 
07900 //===============================================================================
07901 // Function   : get_mid_plane
07902 // Member Type: PUBLIC
07903 // Description: 
07904 // Author     : Jane Hu
07905 // Date       : 01/09
07906 //===============================================================================
07907 CubitStatus OCCModifyEngine::get_mid_plane( const CubitVector & point_1,
07908                                             const CubitVector & point_2,
07909                                             const CubitVector & point_3,
07910                                             BodySM * body_to_trim_to,
07911                                             BodySM *& result_body ) const
07912 {
07913   //Calculate normal of the mid  plane
07914   CubitVector v1, v2, normal;
07915   v1 = point_2 - point_1;
07916   v2 = point_3 - point_1;
07917   normal = ~(v1 * v2);
07918   if(fabs(normal.length() - 1) > TOL)
07919   {
07920      PRINT_ERROR("The three points are co-linear, and can't be used as a cutting plane.\n");
07921      return CUBIT_FAILURE;
07922   }
07923  
07924   gp_Pnt pt = gp_Pnt( point_1.x(), point_1.y(), point_1.z());
07925   gp_Dir normal_dir(normal.x(), normal.y(), normal.z());
07926   gp_Pln plane(pt, normal_dir);
07927 
07928   TopoDS_Face face = BRepBuilderAPI_MakeFace(plane);
07929   Surface *surf = OCCQueryEngine::instance()->populate_topology_bridge(face,
07930                                                CUBIT_TRUE);
07931   if(!surf)
07932   {
07933     PRINT_ERROR("Can't create cutting plane.\n");
07934     return CUBIT_FAILURE;
07935   }
07936   
07937   BodySM* tool = CAST_TO(surf, OCCSurface)->my_body();
07938   DLIList<BodySM*> from_bodies;
07939   from_bodies.append(body_to_trim_to);
07940   DLIList<BodySM*> midplane_bodies;
07941   CubitStatus stat = intersect(tool, from_bodies, midplane_bodies, 
07942                                CUBIT_TRUE);
07943   OCCQueryEngine::instance()->delete_solid_model_entities(tool);
07944   if (midplane_bodies.size() == 1)
07945     result_body = midplane_bodies.get();
07946   else {
07947     for (int i = 0; i < midplane_bodies.size(); ++i)
07948       OCCQueryEngine::instance()->delete_solid_model_entities(midplane_bodies.get_and_step());
07949     stat = CUBIT_FAILURE;
07950   }
07951   return stat;
07952 }
07953 
07954 //=============================================================================
07955 // Function   : get_spheric_mid_surface
07956 // Member Type: PUBLIC
07957 // Description: Calculates a mid-surface between 2 spheric surfaces.
07958 // Author     : Jane Hu
07959 // Date       : 01/09
07960 //=============================================================================
07961 CubitStatus OCCModifyEngine::get_spheric_mid_surface( Surface* surface_ptr1,
07962                                     Surface* surface_ptr2,
07963                                     BodySM* body_to_trim_to,
07964                                     BodySM*& result_body ) const
07965 {
07966   OCCSurface* occ_surf1 = CAST_TO(surface_ptr1, OCCSurface);
07967   OCCSurface* occ_surf2 = CAST_TO(surface_ptr2, OCCSurface);
07968   if(occ_surf1->geometry_type() != SPHERE_SURFACE_TYPE ||
07969      occ_surf2->geometry_type() != SPHERE_SURFACE_TYPE)
07970   {
07971     PRINT_ERROR( "Both surfaces provided should be sphere type.\n");
07972     return CUBIT_FAILURE;
07973   }
07974  
07975   BRepAdaptor_Surface asurface1(*occ_surf1->get_TopoDS_Face());
07976   BRepAdaptor_Surface asurface2(*occ_surf2->get_TopoDS_Face());
07977 
07978   gp_Sphere sphere1 = asurface1.Sphere();
07979   gp_Sphere sphere2 = asurface2.Sphere();
07980 
07981   gp_Pnt center1 = sphere1.Location();
07982   gp_Pnt center2 = sphere2.Location();
07983 
07984   if(!center1.IsEqual(center2, TOL))
07985   {
07986     PRINT_ERROR( "Spheres need to have the same center.\n");
07987     return CUBIT_FAILURE;
07988   }
07989 
07990   double radius = sphere1.Radius()/2.0 + sphere2.Radius()/2.0;
07991   BodySM* tool = sphere(radius);
07992   CubitVector center(center1.X(), center1.Y(), center1.Z());
07993   OCCQueryEngine::instance()->translate(tool, center);
07994 
07995   //get the tool surfaces as the tool
07996   DLIList<Surface*> surfaces;
07997   tool->surfaces(surfaces);
07998   assert (surfaces.size() == 1);
07999   tool = make_BodySM(surfaces.get());
08000 
08001   DLIList<BodySM*> from_bodies, midsurface_bodies;
08002   from_bodies.append(body_to_trim_to);
08003 
08004   CubitStatus stat = intersect(tool, from_bodies, midsurface_bodies,
08005                                CUBIT_TRUE);
08006   OCCQueryEngine::instance()->delete_solid_model_entities(tool);
08007   if (midsurface_bodies.size() == 1)
08008     result_body = midsurface_bodies.get();
08009   else {
08010     for (int i = 0; i < midsurface_bodies.size(); ++i)
08011       OCCQueryEngine::instance()->delete_solid_model_entities(midsurface_bodies.get_and_step());
08012     stat = CUBIT_FAILURE;
08013   }
08014 
08015   return stat;  
08016 }
08017 
08018 //=============================================================================
08019 // Function   : get_conic_mid_surface
08020 // Member Type: PUBLIC
08021 // Description: Calculates a mid-surface between 2 conic surfaces.
08022 // Author     : Jane Hu
08023 // Date       : 01/09
08024 //=============================================================================
08025 CubitStatus OCCModifyEngine::get_conic_mid_surface( Surface* surface_ptr1,
08026                                     Surface* surface_ptr2,
08027                                     BodySM* body_to_trim_to,
08028                                     BodySM*& result_body ) const
08029 {
08030   OCCSurface* occ_surf1 = CAST_TO(surface_ptr1, OCCSurface);
08031   OCCSurface* occ_surf2 = CAST_TO(surface_ptr2, OCCSurface);
08032   if(occ_surf1->geometry_type() != CONE_SURFACE_TYPE ||
08033      occ_surf2->geometry_type() != CONE_SURFACE_TYPE)
08034   {
08035     PRINT_ERROR( "Both surfaces provided should be conic type.\n");
08036     return CUBIT_FAILURE;
08037   }  
08038 
08039   BRepAdaptor_Surface asurface1(*occ_surf1->get_TopoDS_Face());
08040   BRepAdaptor_Surface asurface2(*occ_surf2->get_TopoDS_Face());
08041 
08042   GeomAbs_SurfaceType  type1 = asurface1.GetType();
08043   GeomAbs_SurfaceType  type2 = asurface2.GetType();
08044   if(type1 != type2)
08045   {
08046     PRINT_ERROR( "Both surfaces provided should be both cylinder or cone type.\n");
08047     return CUBIT_FAILURE;
08048   }
08049 
08050   CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box();
08051   double height = (bounding_box.diagonal()).length();
08052   OCCBody* body = CAST_TO(body_to_trim_to, OCCBody);
08053   CubitVector centroid;
08054   double volume;
08055   body->mass_properties(centroid, volume);
08056   BodySM* tool;
08057   if(type1 == GeomAbs_Cylinder)
08058   {
08059     gp_Cylinder cyl1 = asurface1.Cylinder();
08060     gp_Cylinder cyl2 = asurface2.Cylinder(); 
08061     gp_Ax1  axis1 = cyl1.Axis();
08062     gp_Ax1  axis2 = cyl2.Axis();
08063     if(!axis1.IsCoaxial(axis2, 0.001, TOL))
08064     {
08065       PRINT_ERROR( "Cylinders need to have the same axis of symmetry.\n");
08066       return CUBIT_FAILURE;
08067     }
08068     double radius = cyl1.Radius()/2.0 + cyl2.Radius()/2.0; 
08069     gp_Ax2 axis;
08070     axis.SetAxis(axis1);
08071     TopoDS_Solid S = BRepPrimAPI_MakeCylinder(axis, radius, height);
08072 
08073     Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S,
08074                                                                 CUBIT_TRUE);
08075 
08076     if (lump == NULL)
08077     {
08078       PRINT_ERROR("In OCCModifyEngine::get_conic_mid_surface\n"
08079                   "   Cannot create a cylinder for given radius.\n");
08080       return CUBIT_FAILURE;
08081     }
08082 
08083     tool = CAST_TO(lump, OCCLump)->get_body();
08084     double z = centroid.z();
08085     z -= height/2.0;
08086     centroid.z(z);
08087     OCCQueryEngine::instance()->translate(tool, centroid);  
08088   }
08089 
08090   else  //GeomAbs_Cone
08091   {
08092     gp_Cone cone1 = asurface1.Cone();
08093     gp_Cone cone2 = asurface2.Cone();
08094     double angle1 = cone1.SemiAngle();
08095     double angle2 = cone2.SemiAngle();
08096     if(fabs(angle1 - angle2) > 0.001)
08097     {
08098       PRINT_ERROR( "Cones do not have the same semi-angle.\n");
08099       return CUBIT_FAILURE;
08100     }
08101     gp_Ax1  axis1 = cone1.Axis();
08102     gp_Ax1  axis2 = cone2.Axis();
08103     if(!axis1.IsCoaxial(axis2, 0.001, TOL))
08104     {
08105       PRINT_ERROR( "Cones need to have the same axis of symmetry.\n");
08106       return CUBIT_FAILURE;
08107     } 
08108     if(axis1.IsOpposite(axis2, 0.001))
08109     {
08110       PRINT_ERROR( "Cones need to have the same orientation of axis.\n");
08111       return CUBIT_FAILURE;
08112     }
08113     double r1 = cone1.RefRadius()/2.0 + cone2.RefRadius()/2.0; 
08114     gp_Ax3 axis;
08115     axis.SetAxis(axis1);
08116     gp_Cone cone(axis, angle1, r1);
08117     TopoDS_Face face = BRepBuilderAPI_MakeFace(cone);
08118     Surface* surface = 
08119       OCCQueryEngine::instance()->populate_topology_bridge(face, CUBIT_TRUE);
08120     tool = CAST_TO(surface,OCCSurface)->my_body();  
08121   } 
08122   DLIList<BodySM*> from_bodies, midsurface_bodies;
08123   from_bodies.append(body_to_trim_to);
08124 
08125   CubitStatus stat = intersect(tool, from_bodies, midsurface_bodies,
08126                                CUBIT_TRUE);
08127   OCCQueryEngine::instance()->delete_solid_model_entities(tool);
08128   if (midsurface_bodies.size() == 1)
08129     result_body = midsurface_bodies.get();
08130   else {
08131     for (int i = 0; i < midsurface_bodies.size(); ++i)
08132       OCCQueryEngine::instance()->delete_solid_model_entities(midsurface_bodies.get_and_step());
08133     stat = CUBIT_FAILURE;
08134   }
08135 
08136   return stat;
08137 }
08138 
08139 //=============================================================================
08140 // Function   : get_toric_mid_surface
08141 // Member Type: PUBLIC
08142 // Description: Calculates a mid-surface between 2 toric surfaces.
08143 // Author     : Jane Hu
08144 // Date       : 01/09
08145 //=============================================================================
08146 CubitStatus OCCModifyEngine::get_toric_mid_surface( Surface* surface_ptr1,
08147                                      Surface* surface_ptr2,
08148                                      BodySM* body_to_trim_to,
08149                                      BodySM*& result_body ) const
08150 {
08151   OCCSurface* occ_surf1 = CAST_TO(surface_ptr1, OCCSurface);
08152   OCCSurface* occ_surf2 = CAST_TO(surface_ptr2, OCCSurface);
08153   if(occ_surf1->geometry_type() != TORUS_SURFACE_TYPE ||
08154      occ_surf2->geometry_type() != TORUS_SURFACE_TYPE)
08155   {
08156     PRINT_ERROR( "Both surfaces provided should be toric type.\n");
08157     return CUBIT_FAILURE;
08158   }
08159 
08160   BRepAdaptor_Surface asurface1(*occ_surf1->get_TopoDS_Face());
08161   BRepAdaptor_Surface asurface2(*occ_surf2->get_TopoDS_Face());
08162 
08163   gp_Torus torus1 = asurface1.Torus();
08164   gp_Torus torus2 = asurface2.Torus();
08165 
08166   gp_Pnt center1 = torus1.Location();
08167   gp_Pnt center2 = torus2.Location();
08168 
08169   if(!center1.IsEqual(center2, TOL))
08170   {
08171     PRINT_ERROR( "Torii need to have the same center.\n");
08172     return CUBIT_FAILURE;
08173   }
08174 
08175   double major_r1 = torus1.MajorRadius();
08176   double major_r2 = torus2.MajorRadius();
08177   if(fabs(major_r1 - major_r2) > TOL)
08178   {
08179     PRINT_ERROR( "Torii need to have the same major radius.\n");
08180     return CUBIT_FAILURE;
08181   }
08182 
08183   gp_Ax1 axis1 = torus1.Axis();
08184   gp_Ax1 axis2 = torus2.Axis();
08185   if(!axis1.IsCoaxial(axis2, 0.001, TOL))
08186   {
08187     PRINT_ERROR( "Torii need to have the same axis of symmetry.\n");
08188     return CUBIT_FAILURE;
08189   }
08190 
08191   double radius = torus1.MinorRadius()/2.0 + torus2.MinorRadius()/2.0;
08192   gp_Ax2 axis;
08193   axis.SetAxis(axis1);
08194   TopoDS_Solid S = BRepPrimAPI_MakeTorus(axis, major_r1, radius);
08195 
08196   Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S,
08197                                                                 CUBIT_TRUE);
08198 
08199   if (lump == NULL)
08200   {
08201     PRINT_ERROR("In OCCModifyEngine::get_toric_mid_surface\n"
08202                 "   Cannot create a torus for given radii.\n");
08203     return CUBIT_FAILURE;
08204   }
08205 
08206   BodySM* tool = CAST_TO(lump, OCCLump)->get_body();
08207 
08208   DLIList<BodySM*> from_bodies, midsurface_bodies;
08209   from_bodies.append(body_to_trim_to);
08210 
08211   CubitStatus stat = intersect(tool, from_bodies, midsurface_bodies,
08212                                CUBIT_TRUE);
08213   OCCQueryEngine::instance()->delete_solid_model_entities(tool);
08214   if (midsurface_bodies.size() == 1)
08215     result_body = midsurface_bodies.get();
08216   else {
08217     for (int i = 0; i < midsurface_bodies.size(); ++i)
08218       OCCQueryEngine::instance()->delete_solid_model_entities(midsurface_bodies.get_and_step());
08219     stat = CUBIT_FAILURE;
08220   }
08221 
08222   return stat; 
08223 }
08224 
08225 //=============================================================================
08226 // Function   : tweak_chamfer
08227 // Member Type: PUBLIC
08228 // Description: Chamfer curves on solid bodies.  The left and right offsets are
08229 //              with respect to the curve direction.  If the given right offset
08230 //              is negative, the left offset is used.  Users can preview to
08231 //              clarify the meaning of left and right.
08232 // Author     : Jane Hu
08233 // Date       : 03/2009
08234 //=============================================================================
08235 CubitStatus OCCModifyEngine::tweak_chamfer( DLIList<Curve*> & curve_list, 
08236                                             double left_offset,
08237                                             DLIList<BodySM*> & new_bodysm_list,
08238                                             double right_offset,
08239                                             CubitBoolean keep_old_body,
08240                                             CubitBoolean preview ) const
08241 {
08242   CubitStatus stat;
08243   int count = 0;
08244   if(right_offset <= 0.0)
08245     right_offset = left_offset;
08246 
08247   for(int i = 0; i < curve_list.size(); i++)
08248   {
08249     BodySM * new_bodysm_ptr = NULL;
08250     stat = tweak_fillet(curve_list.get_and_step(), left_offset, right_offset,
08251                       new_bodysm_ptr , keep_old_body, CUBIT_FALSE, CUBIT_FALSE);
08252     if(stat && new_bodysm_ptr)
08253     {
08254       new_bodysm_list.append_unique(new_bodysm_ptr);
08255       count = new_bodysm_list.size();
08256     }
08257     else
08258       break;
08259   }
08260 
08261   if(count == 0)
08262     return CUBIT_FAILURE;
08263 
08264   if(preview)
08265   {
08266     GfxPreview::clear();
08267     for(int i = 0; i < new_bodysm_list.size(); i++)
08268     {
08269       BodySM* new_bodysm = new_bodysm_list.get_and_step();
08270       TopoDS_Shape* modified_shape; 
08271       CAST_TO(new_bodysm, OCCBody)->get_TopoDS_Shape(modified_shape);
08272       TopExp_Explorer Ex;
08273       Ex.Init(*modified_shape, TopAbs_FACE);
08274       for( ; Ex.More(); Ex.Next() )
08275       {
08276         TopoDS_Face face = TopoDS::Face(Ex.Current());
08277         // Draw this face
08278         OCCDrawTool::instance()->draw_FACE( &face, CUBIT_BLUE_INDEX, CUBIT_TRUE );
08279       }
08280     }
08281     OCCQueryEngine::instance()->delete_solid_model_entities(new_bodysm_list);
08282     new_bodysm_list.clean_out();
08283   }
08284 
08285   return CUBIT_SUCCESS;
08286 }
08287 
08288 //=============================================================================
08289 // Function   : tweak_chamfer
08290 // Member Type: PUBLIC
08291 // Description: Chamfer vertices on solid or sheet bodies.  On a solid body 
08292 //              there can be up to 3 offsets; on a sheet body up to 2 offsets.
08293 //              The offsets are in the direction of the supplied edges.  If 
08294 //              multiple vertices are supplied, only one offset value is 
08295 //              allowed and the edges are not used.
08296 // Author     : Jane Hu
08297 // Date       : 03/09
08298 //=============================================================================
08299 CubitStatus
08300 OCCModifyEngine::tweak_chamfer( DLIList<TBPoint*> & point_list, 
08301                                 double offset1,
08302                                 DLIList<BodySM*> & new_bodysm_list,
08303                                 Curve * edge1,
08304                                 double offset2,
08305                                 Curve * edge2,
08306                                 double offset3,
08307                                 Curve * edge3,
08308                                 CubitBoolean keep_old_body,
08309                                 CubitBoolean preview ) const
08310 {
08311   // Sort out vertices between sheet and solid bodies
08312   DLIList<TBPoint*> solid_points, sheet_points;
08313   DLIList<OCCSurface*> s_list;
08314   DLIList<OCCBody*> bodies;
08315   if( sort_points_by_body_type( point_list, solid_points, sheet_points, 
08316                                 s_list, bodies ) == CUBIT_FAILURE )
08317     return CUBIT_FAILURE;
08318 
08319   if(solid_points.size() > 0 && solid_points.size() != bodies.size())
08320   {
08321     PRINT_ERROR( "cannot find bodies corresponding to the points.\n" );
08322     return CUBIT_FAILURE;
08323   }
08324 
08325   if(sheet_points.size() > 0 && sheet_points.size() != s_list.size())
08326   {
08327     PRINT_ERROR( "cannot find surfaces corresponding to the points.\n" );
08328     return CUBIT_FAILURE;
08329   }
08330 
08331   // Do simple forms
08332   if( edge1 == NULL || offset2 <= 0.0 )
08333   {
08334     if( tweak_chamfer_solid( solid_points, bodies, offset1, new_bodysm_list,
08335       keep_old_body, preview )== CUBIT_FAILURE )
08336       return CUBIT_FAILURE;
08337     return tweak_fillet_chamfer_sheet( sheet_points, s_list, offset1, 
08338            CUBIT_FALSE, new_bodysm_list, keep_old_body, preview );
08339   }
08340 
08341   if( solid_points.size() > 1 || sheet_points.size() > 1 )
08342   {
08343     PRINT_ERROR( "cannot chamfer multiple vertices with a variable radius.\n" );
08344     return CUBIT_FAILURE;
08345   }
08346 
08347   if( solid_points.size() )
08348   {
08349     TBPoint *point_ptr = solid_points.get();
08350 
08351     if( tweak_chamfer_solid( point_ptr, bodies.get(), offset1, edge1, 
08352         offset2, edge2, offset3, edge3,
08353         new_bodysm_list, keep_old_body, preview ) == CUBIT_FAILURE )
08354       return CUBIT_FAILURE;
08355 
08356     return CUBIT_SUCCESS;
08357   }
08358 
08359   if( sheet_points.size() )
08360   {
08361     TBPoint *point_ptr = sheet_points.get();
08362 
08363     if( tweak_chamfer_sheet( point_ptr, s_list.get(), offset1, edge1, offset2, 
08364         edge2, new_bodysm_list, keep_old_body, preview ) == CUBIT_FAILURE )
08365       return CUBIT_FAILURE;
08366 
08367     return CUBIT_SUCCESS;
08368   }
08369   return CUBIT_SUCCESS;
08370 }
08371 
08372 CubitStatus
08373 OCCModifyEngine::tweak_chamfer_solid( DLIList<TBPoint*> &point_list,
08374                                     DLIList<OCCBody*> &bodies,
08375                                     double radius,
08376                                     DLIList<BodySM*> &new_bodysm_list,
08377                                     CubitBoolean keep_old_body,
08378                                     CubitBoolean preview )const
08379 {
08380   //if point_list.size() > 1, after the first chamfer operation, the rest of 
08381   //the points in point_list maybe deleted and recreated, so can't use the 
08382   //points' pointers any more.
08383   DLIList<CubitVector> p_locs;
08384   if(point_list.size() > 1)
08385   {
08386     for (int i = 1; i < point_list.size(); i++)
08387      p_locs.append(point_list[i]->coordinates());
08388   }
08389   for(int i = 0; i < point_list.size(); i++)
08390   {
08391     DLIList<TopologyBridge*> parents;
08392     TBPoint* point = point_list.get_and_step();
08393     OCCBody* body = bodies.get_and_step();
08394     DLIList<OCCPoint*> new_p_list;
08395     if( i > 0)
08396     {
08397       body->get_all_points(new_p_list);
08398       if(!new_p_list.move_to((OCCPoint*)point)) 
08399       {
08400         CubitVector p_loc = p_locs[i-1];
08401         for(int j = 0; j < new_p_list.size(); j++)
08402         {
08403           CubitVector test_loc = new_p_list.step_and_get()->coordinates();
08404           if(test_loc == p_loc)
08405           {
08406             point = new_p_list.get(); 
08407             break;
08408           }
08409         }
08410       }
08411     }
08412     OCCPoint* occ_point = CAST_TO(point, OCCPoint);
08413     if(occ_point != NULL)
08414       occ_point->get_parents_virt(parents); //OCCCurves
08415     assert(parents.size() == 3);
08416     DLIList<Curve*> curves;
08417     for(int j = 0; j < 3; j++)
08418     {
08419       OCCCurve* occ_curve = CAST_TO(parents.get_and_step(), OCCCurve); 
08420       curves.append(occ_curve);
08421     }
08422     CubitStatus stat;
08423     stat = tweak_chamfer_solid(point, body,radius, curves.pop(), radius, 
08424                         curves.pop(), radius, curves.pop(), new_bodysm_list,
08425                         keep_old_body, CUBIT_FALSE );
08426     if(!stat)
08427       return CUBIT_FAILURE;
08428   }
08429   if(preview)
08430   {
08431     GfxPreview::clear();
08432     for(int i = 0; i < new_bodysm_list.size(); i++)
08433     {
08434       BodySM* new_bodysm = new_bodysm_list.get_and_step();
08435       TopoDS_Shape* modified_shape ;
08436       CAST_TO(new_bodysm, OCCBody)->get_TopoDS_Shape(modified_shape);
08437       TopExp_Explorer Ex;
08438       Ex.Init(*modified_shape, TopAbs_FACE);
08439       for( ; Ex.More(); Ex.Next() )
08440       {
08441         TopoDS_Face face = TopoDS::Face(Ex.Current());
08442         // Draw this face
08443         OCCDrawTool::instance()->draw_FACE( &face, CUBIT_BLUE_INDEX, CUBIT_TRUE );
08444       }
08445     }
08446     OCCQueryEngine::instance()->delete_solid_model_entities(new_bodysm_list);
08447     new_bodysm_list.clean_out();
08448   }
08449 
08450   return CUBIT_SUCCESS;
08451 
08452 }
08453 
08454 CubitStatus
08455 OCCModifyEngine::tweak_chamfer_solid( TBPoint* point_ptr,
08456                                     OCCBody* body,
08457                                     double r1,
08458                                     Curve *c1,
08459                                     double r2,
08460                                     Curve *c2,
08461                                     double r3,
08462                                     Curve *c3,
08463                                     DLIList<BodySM *> &new_bodysm_list,
08464                                     CubitBoolean keep_old_body,
08465                                     CubitBoolean preview )const
08466 {
08467   if(r1 <= 0.0 || r2 <= 0.0 || r3 <= 0.0)
08468   {
08469     PRINT_ERROR( "Chamfer radii must be greater than zero.\n" );
08470     return CUBIT_FAILURE;
08471   }
08472   
08473   DLIList<Curve*> curves;
08474   curves.append(c1);
08475   curves.append(c2);
08476   curves.append(c3);
08477   
08478   DLIList<double> radii;
08479   radii.append(r1);
08480   radii.append(r2);
08481   radii.append(r3);
08482 
08483   //check point on curves
08484   OCCPoint* occ_point = CAST_TO(point_ptr, OCCPoint);
08485   CubitVector position = occ_point->coordinates();
08486   DLIList<CubitVector> locations;
08487   for(int i = 0; i < 3; i++)
08488   {
08489     OCCCurve *occ_curve = NULL;
08490     occ_curve = CAST_TO(curves.get_and_step(), OCCCurve);
08491     double length = occ_curve->measure();
08492 
08493     DLIList<OCCPoint*> point_list;
08494     occ_curve->get_points(point_list);
08495     CubitBoolean in = point_list.is_in_list(occ_point); 
08496     if(!in)
08497     {
08498       PRINT_ERROR( "Point is not on curve.\n" );
08499       return CUBIT_FAILURE;
08500     }
08501     //find cutting points on curves
08502     double u, u1, u2;
08503     occ_curve->get_param_range(u1,u2);
08504     u = occ_curve->u_from_position(position); 
08505     if(fabs(u-u1) < TOL)
08506       u = occ_curve->u_from_arc_length(u1, radii[i]);
08507     else
08508       u = occ_curve->u_from_arc_length(u1, length-radii[i]);
08509     CubitVector c_p;
08510     occ_curve->position_from_u(u, c_p);
08511     locations.append(c_p);
08512   }
08513 
08514   //decide normal
08515   CubitVector v1, v2, normal;
08516   CubitVector point_1 = locations.pop();
08517   CubitVector point_2 = locations.pop();
08518   CubitVector point_3 = locations.pop();
08519   v1 = point_2 - point_1;
08520   v2 = point_1 - point_3;
08521   normal = ~(v1 * v2); 
08522   CubitVector center;
08523   double volume;
08524   body->mass_properties(center, volume); 
08525   CubitVector dir = ~(center - position);
08526   if(normal % dir > 0.0)//1, 3, 2 order
08527   {
08528     CubitVector v = point_2;
08529     point_2 = point_3;
08530     point_3 = v;
08531   }
08532 
08533   DLIList<BodySM*> bodies;
08534   BodySM* new_body;
08535   if(keep_old_body || preview)
08536     new_body = copy_body(body); 
08537   else
08538     new_body = body;
08539 
08540   bodies.append(new_body);
08541   const CubitVector p1 = point_1;
08542   const CubitVector p2 = point_2;
08543   const CubitVector p3 = point_3;
08544   CubitStatus status = const_cast<OCCModifyEngine*> (this)->
08545                                section(bodies, p1, p2, p3, 
08546                                new_bodysm_list, true,false, false);    
08547   if(!status)
08548     return CUBIT_FAILURE;
08549 
08550   if(!preview)
08551     return CUBIT_SUCCESS;
08552 
08553   GfxPreview::clear();
08554 
08555   for(int i = 0; i < new_bodysm_list.size(); i++)
08556   {
08557      BodySM* new_bodysm = new_bodysm_list.get_and_step();
08558      DLIList<OCCSurface*> surfs = CAST_TO(new_bodysm, OCCBody)->my_sheet_surfaces();
08559      for(int j = 0 ; j < surfs.size(); j++)
08560      {
08561        TopoDS_Face* modified_shape = surfs.get_and_step()->get_TopoDS_Face();
08562        // Draw this face
08563        OCCDrawTool::instance()->draw_FACE( modified_shape, CUBIT_BLUE_INDEX, CUBIT_TRUE );
08564      }
08565   }
08566   OCCQueryEngine::instance()->delete_solid_model_entities(new_bodysm_list);
08567   new_bodysm_list.clean_out();
08568 
08569   return CUBIT_SUCCESS;
08570 }
08571 
08572 CubitStatus
08573 OCCModifyEngine::sort_points_by_body_type( DLIList<TBPoint*> &point_list,
08574                                          DLIList<TBPoint*> &solid_points,
08575                                          DLIList<TBPoint*> &sheet_points,
08576                                          DLIList<OCCSurface*> &s_list,
08577                                          DLIList<OCCBody*> &bodies )const
08578 {
08579   for (int i = 0; i < point_list.size(); i++)
08580   {
08581     DLIList<TopologyBridge*> parents;
08582     OCCPoint* point = CAST_TO(point_list.get_and_step(), OCCPoint);
08583     int curve_size = 0;
08584     if(point != NULL)
08585     {
08586       point->get_parents_virt(parents); //OCCCurves
08587       if(parents.size() < 2)
08588       {
08589         PRINT_ERROR( "Vertex found not attached to any surfaces.\n" );
08590         return CUBIT_FAILURE;
08591       } 
08592       else if(parents.size() > 3)
08593       {
08594         PRINT_ERROR( "Vertex found attached to multiple bodies.\n" );
08595         return CUBIT_FAILURE;
08596       }
08597       curve_size = parents.size();
08598     }
08599     
08600     OCCCurve* occ_curve = CAST_TO(parents.get(), OCCCurve);
08601     parents.clean_out();
08602     occ_curve->get_parents_virt(parents); //OCCCoEdges
08603     if(parents.size() == 0)
08604     {
08605       PRINT_ERROR( "Vertex found not attached to any surfaces.\n" );
08606       return CUBIT_FAILURE;
08607     }
08608     OCCCoEdge* coedge = CAST_TO(parents.get(), OCCCoEdge);
08609     parents.clean_out();
08610     coedge->get_parents_virt(parents);  //OCCLoops
08611     assert(parents.size() > 0);
08612     OCCLoop* loop = CAST_TO(parents.get(), OCCLoop);
08613     parents.clean_out();
08614     loop->get_parents_virt(parents); //OCCSurface
08615     assert(parents.size() > 0);
08616     OCCSurface* s = CAST_TO(parents.get(), OCCSurface); 
08617     if(s->my_body() != NULL && curve_size == 2) //sheet body
08618     {
08619       s_list.append(s);
08620       sheet_points.append(point);
08621     }
08622     else if(s->my_body() != NULL && curve_size == 3) //shell body
08623     {
08624       PRINT_ERROR( "Vertex found attached to multiple surfaces but not on bodies.\n" );
08625       return CUBIT_FAILURE;
08626     }
08627     else
08628     {
08629       solid_points.append(point);
08630       DLIList<OCCBody*> solid_bodies;
08631       s->get_bodies(solid_bodies);
08632       assert(solid_bodies.size() == 1);
08633       bodies += solid_bodies;
08634     }
08635   }
08636   return CUBIT_SUCCESS;
08637 }
08638 //=============================================================================
08639 // Function   : tweak_fillet
08640 // Member Type: PUBLIC
08641 // Description: Create a round fillet (or blend) at the given curves on solid 
08642 //              bodies.
08643 // Author     : Jane Hu
08644 // Date       : 01/09
08645 //=============================================================================
08646 CubitStatus OCCModifyEngine::tweak_fillet( DLIList<Curve*> & curve_list, 
08647                                            double radius,
08648                                            DLIList<BodySM*> & new_bodysm_list,
08649                                            CubitBoolean keep_old_body,
08650                                            CubitBoolean preview )const 
08651 {
08652   CubitStatus stat;
08653   int count = 0;
08654   for(int i = 0; i < curve_list.size(); i++) 
08655   {
08656     BodySM * new_bodysm_ptr = NULL;
08657     stat = tweak_fillet(curve_list.get_and_step(), radius, radius, 
08658                         new_bodysm_ptr , keep_old_body, CUBIT_FALSE);
08659     if(stat && new_bodysm_ptr)
08660     {
08661       new_bodysm_list.append_unique(new_bodysm_ptr);
08662       count = new_bodysm_list.size();
08663     }
08664     else
08665       break;
08666   }
08667 
08668   if(count == 0) 
08669     return CUBIT_FAILURE;
08670  
08671   if(preview)
08672   {
08673     GfxPreview::clear();
08674     for(int i = 0; i < new_bodysm_list.size(); i++)
08675     {
08676       BodySM* new_bodysm = new_bodysm_list.get_and_step();
08677       TopoDS_Shape* modified_shape ; 
08678       CAST_TO(new_bodysm, OCCBody)->get_TopoDS_Shape(modified_shape);
08679       TopExp_Explorer Ex;
08680       Ex.Init(*modified_shape, TopAbs_FACE);
08681       for( ; Ex.More(); Ex.Next() )
08682       {
08683         TopoDS_Face face = TopoDS::Face(Ex.Current());
08684         // Draw this face
08685         OCCDrawTool::instance()->draw_FACE( &face, CUBIT_BLUE_INDEX, CUBIT_TRUE );
08686       }
08687     }
08688     OCCQueryEngine::instance()->delete_solid_model_entities(new_bodysm_list);  
08689     new_bodysm_list.clean_out();
08690   }
08691   
08692   return CUBIT_SUCCESS;
08693 }
08694 
08695 //=============================================================================
08696 // Function   : tweak_fillet
08697 // Member Type: PUBLIC
08698 // Description: Create a round fillet (or blend) at the given curves on a solid
08699 //              body.  The fillet/chamfer has a variable radius from the
08700 //              start to the end of the curve.
08701 // Author     : Jane Hu
08702 // Date       : 01/09
08703 //=============================================================================
08704 CubitStatus OCCModifyEngine::tweak_fillet( Curve * curve_ptr,
08705                                            double start_radius,
08706                                            double end_radius,
08707                                            BodySM *& new_bodysm_ptr,
08708                                            CubitBoolean keep_old_body,
08709                                            CubitBoolean preview )const
08710 {
08711   return tweak_fillet(curve_ptr, start_radius, end_radius, new_bodysm_ptr,
08712                       keep_old_body, preview, CUBIT_TRUE);
08713 }
08714 
08715 //=============================================================================
08716 // Function   : tweak_fillet
08717 // Member Type: private
08718 // Description: Create a round fillet (or blend) at the given curves on a solid 
08719 //              body.  The fillet/chamfer has a variable radius from the 
08720 //              start to the end of the curve.
08721 // Author     : Jane Hu 
08722 // Date       : 01/09
08723 //=============================================================================
08724 CubitStatus OCCModifyEngine::tweak_fillet( Curve * curve_ptr, 
08725                                            double start_radius,
08726                                            double end_radius,
08727                                            BodySM *& new_bodysm_ptr,
08728                                            CubitBoolean keep_old_body,
08729                                            CubitBoolean preview,
08730                                            CubitBoolean if_fillet ) const
08731 {
08732   //check if this id is valid 
08733   OCCQueryEngine* oqe = OCCQueryEngine::instance();
08734   DLIList <OCCBody* > *bodies = oqe->BodyList;  
08735   DLIList<OCCCurve*> curves;
08736   for(int j = 0; j <  bodies->size(); j++)
08737   {
08738     OCCBody* body = bodies->get_and_step();
08739     body->get_all_curves(curves);
08740   }
08741 
08742   bool curve_alive = false;
08743   for(int j = 0; j <  curves.size(); j++)
08744   {
08745     if(curve_ptr == curves.get_and_step())
08746     {
08747       curve_alive = true; 
08748       break;
08749     }
08750   }
08751 
08752   if(!curve_alive)
08753   {
08754     PRINT_ERROR("This curve is not valid in the current model.\n");
08755     return CUBIT_FAILURE;
08756   }
08757 
08758   OCCCurve *occ_curve = CAST_TO(curve_ptr, OCCCurve);
08759   TopoDS_Edge* topo_edge = occ_curve->get_TopoDS_Edge();
08760 
08761   TopTools_IndexedDataMapOfShapeListOfShape M;
08762   DLIList<TopoDS_Shape*> shape_list;
08763   TopoDS_Face* s = NULL;
08764   for(int j = 0; j <  bodies->size(); j++)
08765   {
08766     OCCBody* body = bodies->get_and_step();
08767     TopExp_Explorer Ex;
08768     TopoDS_Shape* pshape ; 
08769     body->get_TopoDS_Shape(pshape);
08770     
08771     if (pshape && !pshape->IsNull())
08772     {
08773       M.Clear();
08774       TopExp::MapShapesAndAncestors(*pshape, TopAbs_EDGE, TopAbs_COMPOUND, M);
08775       if(!M.Contains(*topo_edge))
08776          continue;
08777 
08778       shape_list.append_unique(pshape);
08779     }   
08780 
08781     if(!if_fillet) //for chamfer, need to know the face for the curve.
08782     {
08783       DLIList<TopologyBridge*> parents;
08784       occ_curve->get_parents_virt(parents); //OCCCoEdges
08785       assert(parents.size() > 1);
08786       OCCCoEdge* coedge = CAST_TO(parents.get(), OCCCoEdge);
08787       parents.clean_out();
08788       coedge->get_parents_virt(parents);  //OCCLoops
08789       assert(parents.size() > 0);
08790       OCCLoop* loop = CAST_TO(parents.get(), OCCLoop);
08791       parents.clean_out(); 
08792       loop->get_parents_virt(parents); //OCCSurface
08793       assert(parents.size() > 0);
08794       s = CAST_TO(parents.get(), OCCSurface)->get_TopoDS_Face();
08795     }
08796   }
08797   if(shape_list.size() != 1)
08798   {
08799     PRINT_ERROR("Fillets must be created on solids.\n");
08800     return CUBIT_FAILURE;
08801   }
08802 
08803   TopoDS_Shape newShape;
08804   TopoDS_Shape* shape = shape_list.get();
08805   if(keep_old_body)
08806   {
08807     BRepBuilderAPI_Copy api_copy(*shape);
08808     newShape = api_copy.ModifiedShape(*shape);
08809   }
08810   else
08811     newShape = *shape;
08812 
08813   BRepBuilderAPI_MakeShape* fillet;
08814   if(if_fillet)
08815   {
08816     fillet = new BRepFilletAPI_MakeFillet(newShape);
08817     dynamic_cast<BRepFilletAPI_MakeFillet*>(fillet)->Add(start_radius, end_radius, *topo_edge);
08818   }
08819   else
08820   {
08821     fillet = new BRepFilletAPI_MakeChamfer(newShape);
08822     dynamic_cast<BRepFilletAPI_MakeChamfer*>(fillet)->Add(start_radius, end_radius, *topo_edge, *s);
08823   }
08824   fillet->Build();
08825 
08826   if(!fillet->IsDone())
08827   {
08828     PRINT_ERROR("Can't create fillet on given curve.\n");
08829     return CUBIT_FAILURE;
08830   } 
08831   TopoDS_Shape modified_shape = fillet->Shape();
08832 
08833   if( !preview )
08834   {
08835     TopExp_Explorer Ex;
08836     Ex.Init(newShape, TopAbs_SOLID);
08837     TopoDS_Solid old_solid = TopoDS::Solid(Ex.Current());
08838     OCCLump::update_OCC_entity(old_solid , modified_shape, fillet);     
08839     DLIList<TopologyBridge*> tbs = OCCQueryEngine::instance()->populate_topology_bridge(modified_shape);
08840     new_bodysm_ptr = CAST_TO(tbs.