Author: janehu Date: 2008-12-23 14:11:34 -0600 (Tue, 23 Dec 2008) New Revision: 2498 Added: cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2493 cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2494 Modified: cgm/trunk/geom/OCC/OCCModifyEngine.cpp Log: Modified to consider that the curves given in create_arc_three function can have multiple solutions or none solution. In multiple solution case, the first reasonable solution will be choosing. Modified: cgm/trunk/geom/OCC/OCCModifyEngine.cpp =================================================================== --- cgm/trunk/geom/OCC/OCCModifyEngine.cpp 2008-12-23 19:55:52 UTC (rev 2497) +++ cgm/trunk/geom/OCC/OCCModifyEngine.cpp 2008-12-23 20:11:34 UTC (rev 2498) @@ -4968,30 +4968,15 @@ vt3 = *intscts.get(); double u, u11, u12, u21, u22, u31, u32; - u12 = occ_crv1->u_from_position(vt1); - u11 = occ_crv1->u_from_position(vt3); - if(u12 < u11) - { - u = u12; - u12 = u11; - u11 = u; - } - u22 = occ_crv2->u_from_position(vt1); - u21 = occ_crv2->u_from_position(vt2); - if(u22 < u21) - { - u = u22; - u22 = u21; - u21 = u; - } - u32 = occ_crv3->u_from_position(vt2); - u31 = occ_crv3->u_from_position(vt3); - if(u32 < u31) - { - u = u32; - u32 = u31; - u31 = u; - } + occ_crv1->get_param_range(u11, u12); + occ_crv2->get_param_range(u21, u22); + occ_crv3->get_param_range(u31, u32); + + CubitVector pt1, pt2, pt3; + occ_crv1->position_from_u(u11, pt1); + occ_crv2->position_from_u(u21, pt2); + occ_crv3->position_from_u(u31, pt3); + CubitVector tangent1, tangent2, tangent3; occ_crv1->get_tangent(vt1, tangent1); occ_crv2->get_tangent(vt2, tangent2); @@ -5074,8 +5059,13 @@ OCCQueryEngine::instance()->get_intersections(curve3, vt1, p12, intscts,none,none); int_pt = *intscts.pop(); u = occ_crv3->u_from_position (int_pt); - assert(u >= u31-tol && u <= u32+tol); - int_pt1 = int_pt; + if(u >= u31-tol && u <= u32+tol) + int_pt1 = int_pt; + else + { + PRINT_ERROR("Can't find the intesection point to create circle.\n"); + return (Curve*) NULL; + } } OCCQueryEngine::instance()->get_intersections(curve1, vt2, p21, intscts,none,none); @@ -5088,8 +5078,13 @@ OCCQueryEngine::instance()->get_intersections(curve1, vt2, p22, intscts,none,none); int_pt = *intscts.pop(); u = occ_crv1->u_from_position (int_pt); - assert(u >= u11-tol && u <= u12+tol); - int_pt2 = int_pt; + if(u >= u11-tol && u <= u12+tol) + int_pt2 = int_pt; + else + { + PRINT_ERROR("Can't find the intesection point to create circle.\n"); + return (Curve*) NULL; + } } OCCQueryEngine::instance()->get_intersections(curve2, vt3, p31, intscts,none,none); @@ -5102,8 +5097,13 @@ OCCQueryEngine::instance()->get_intersections(curve2, vt3, p32, intscts,none,none); int_pt = *intscts.pop(); u = occ_crv2->u_from_position (int_pt); - assert(u >= u21-tol && u <= u22+tol); - int_pt3 = int_pt; + if(u >= u21-tol && u <= u22+tol) + int_pt3 = int_pt; + else + { + PRINT_ERROR("Can't find the intesection point to create circle.\n"); + return (Curve*) NULL; + } } //4. use the 3 intersection points to find the arc or circle. OCCPoint occ_p1(int_pt1); Copied: cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2493 (from rev 2493, cgm/trunk/geom/OCC/OCCModifyEngine.cpp) =================================================================== --- cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2493 (rev 0) +++ cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2493 2008-12-23 20:11:34 UTC (rev 2498) @@ -0,0 +1,5632 @@ +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +// Filename : OCCModifyEngine.cpp +// +// Purpose : ModifyEngine for OCC geometry +// +// Special Notes : Modeled after GeometryModifyEngine and AcisModifyEngine. +// +// Author : Jane Hu +// +// Creation Date : 1/08 +// +//------------------------------------------------------------------------- +#include "gp_Pnt.hxx" +#include "gp_Ax2.hxx" +#include "gp_Dir.hxx" +#include "gp_Hypr.hxx" +#include "gp_Parab.hxx" +#include "gp_Elips.hxx" +#include "gp_Pln.hxx" +#include "gp_Cylinder.hxx" +#include "gp_Cone.hxx" +#include "gp_Sphere.hxx" +#include "gp_Torus.hxx" +#include "BRepBuilderAPI_MakeShell.hxx" +#include "BRepBuilderAPI_MakeSolid.hxx" +#include "BRepOffsetAPI_MakeDraft.hxx" +#include "BRepBuilderAPI_TransitionMode.hxx" +#include "BRepBuilderAPI_MakeWire.hxx" +#include "BRepPrimAPI_MakeHalfSpace.hxx" +#include "BRepBndLib.hxx" +#include "TopoDS_Shape.hxx" +#include "TopAbs_Orientation.hxx" +#include "TColgp_Array1OfPnt.hxx" +#include "GC_MakeArcOfCircle.hxx" +#include "GC_MakeCircle.hxx" +#include "GC_MakeArcOfHyperbola.hxx" +#include "GC_MakeArcOfParabola.hxx" +#include "GC_MakeArcOfEllipse.hxx" +#include "GC_MakeSegment.hxx" +#include "GC_MakeTrimmedCone.hxx" +#include "GC_MakeTrimmedCylinder.hxx" +#include "gce_MakeElips.hxx" +#include "Geom_BezierCurve.hxx" +#include "BndLib_AddSurface.hxx" +#include "Handle_Geom_Plane.hxx" +#include "BRepExtrema_DistShapeShape.hxx" +#include "Extrema_ExtPC.hxx" +#include "BRepPrimAPI_MakePrism.hxx" +#include "BRepSweep_Revol.hxx" +#include "BRepPrimAPI_MakeCone.hxx" +#include "BRepOffsetAPI_ThruSections.hxx" +#include "BRepLib_FuseEdges.hxx" +#include "BRepOffsetAPI_MakePipe.hxx" +#include "BRepPrimAPI_MakeTorus.hxx" +#include "BRepPrimAPI_MakeCylinder.hxx" +#include "BRepBuilderAPI_Transform.hxx" +#include "BRepAdaptor_Curve.hxx" +#include "GC_MakeEllipse.hxx" +#include "BRepBuilderAPI_MakeEdge.hxx" +#include "BRepAdaptor_Surface.hxx" +#include "BRepBuilderAPI_MakeFace.hxx" +#include "BRepOffsetAPI_MakeThickSolid.hxx" +#include "BRepBuilderAPI_Sewing.hxx" +#include "BRepBuilderAPI_Copy.hxx" +#include "LocOpe_SplitShape.hxx" +#include "BRep_Tool.hxx" +#include "BRep_Builder.hxx" +#include "GProp_GProps.hxx" +#include "BRepGProp.hxx" +#include "TopoDS.hxx" +#include "TopologyBridge.hpp" +#include "ProgressTool.hpp" +#include "BRepAlgoAPI_Fuse.hxx" +#include "BRepAlgoAPI_Cut.hxx" +#include "BRepAlgoAPI_Section.hxx" +#include "BRepAlgoAPI_Common.hxx" +#include "BRepPrimAPI_MakeSphere.hxx" +#include "BRepPrimAPI_MakeBox.hxx" +#include "BRepPrimAPI_MakeWedge.hxx" +#include "BRepTools_WireExplorer.hxx" +#include "Handle_Geom_TrimmedCurve.hxx" +#include "Handle_Geom_RectangularTrimmedSurface.hxx" +#include "BndLib_Add3dCurve.hxx" +#include "TopOpeBRep_EdgesIntersector.hxx" +#include "TopExp_Explorer.hxx" +#include "TopExp.hxx" +#include "OCCModifyEngine.hpp" +#include "OCCQueryEngine.hpp" +#include "OCCCoFace.hpp" +#include "CubitMessage.hpp" +#include "CubitDefines.h" +#include "TopTools_DataMapOfShapeInteger.hxx" +#include "BRepFeat_SplitShape.hxx" +#include "TopOpeBRep_ShapeIntersector.hxx" +#include "TopTools_ListIteratorOfListOfShape.hxx" +#include "CubitUtil.hpp" +#include "CubitPoint.hpp" +#include "CubitPointData.hpp" +#include "CubitFacet.hpp" +#include "CubitQuadFacet.hpp" +#include "CubitFacetData.hpp" +#include "CubitFacetEdge.hpp" +#include "CubitFacetEdgeData.hpp" +#include "GeometryQueryTool.hpp" +#include "GeometryModifyTool.hpp" +#include "ChollaSurface.hpp" +#include "ChollaCurve.hpp" +#include "ChollaPoint.hpp" +#include "OCCPoint.hpp" +#include "OCCCurve.hpp" +#include "CurveFacetEvalTool.hpp" +#include "FacetEvalTool.hpp" +#include "OCCCoEdge.hpp" +#include "OCCLoop.hpp" +#include "OCCSurface.hpp" +#include "OCCShell.hpp" +#include "OCCLump.hpp" +#include "OCCBody.hpp" +#include "ChollaEngine.hpp" +#include "TDGeomFacet.hpp" +#include "CubitFileIOWrapper.hpp" +#include "TDFacetBoundaryPoint.hpp" +#include "Cholla.h" +#include "Body.hpp" +#include "GfxDebug.hpp" +#include "RefFace.hpp" +#include "FacetDataUtil.hpp" +#include "FBDataUtil.hpp" +#include "FBIntersect.hpp" +#include "IntegerHash.hpp" +#include "CpuTimer.hpp" +#include "AppUtil.hpp" +#include "SphereEvaluator.hpp" +#include "CylinderEvaluator.hpp" +#include <vector> +OCCModifyEngine* OCCModifyEngine::instance_ = 0; +#define DEBUG +//=============================================================================== +// Function : OCCModifyEngine +// Member Type: PUBLIC +// Description: constructor +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +OCCModifyEngine::OCCModifyEngine() +{ +// assert( !instance_ ); + + // add this modify engine to geometrymodifytool + GeometryModifyTool::instance()->add_gme(this); +} + + +//=============================================================================== +// Function : ~OCCModifyEngine +// Member Type: PUBLIC +// Description: destructor +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +OCCModifyEngine::~OCCModifyEngine() +{ + instance_ = 0; +} + +//=============================================================================== +// Function : make_Point +// Member Type: PUBLIC +// Description: make a geometric entity point +// Author : Jane Hu +// Date : 10/07 +//=============================================================================== +Point* OCCModifyEngine::make_Point( CubitVector const& point) const +{ + gp_Pnt pt = gp_Pnt( point.x(), point.y(), point.z()); + TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt); + + // Create a new PointACIS object + return OCCQueryEngine::instance()->populate_topology_bridge( theVertex ); +} + +//=============================================================================== +// Function : make_Curve +// This function creates a curve given an existing curve, copy. +// Member Type: PUBLIC +// Description: make a curve +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve(Curve * curve_ptr) const +{ + OCCCurve* occ_curve = CAST_TO(curve_ptr, OCCCurve); + if (!occ_curve) + { + PRINT_ERROR("Cannot create an OCC curve from the given curve.\n" + "Possible incompatible geometry engines.\n"); + return (Curve *)NULL; + } + + TopoDS_Edge *theEdge = occ_curve->get_TopoDS_Edge(); + + BRepBuilderAPI_Copy api_copy(*theEdge); + + TopoDS_Shape newShape = api_copy.ModifiedShape(*theEdge); + + TopoDS_Edge newEdge = TopoDS::Edge(newShape); + + return OCCQueryEngine::instance()->populate_topology_bridge(newEdge); +} + +//=============================================================================== +// Function : make_Curve +// Member Type: PUBLIC +// Description: make a curve by projecting a straight line defined by +// point1_ptr, and point2_ptr onto face_ptr, third_point +// is used for curves that could be periodic to dertermine +// the correct direction. +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve( Point const* point1_ptr, + Point const* point2_ptr, + Surface* face_ptr, + const CubitVector * third_point) const +{ + assert (point1_ptr != NULL && point2_ptr != NULL); + GeometryType type = STRAIGHT_CURVE_TYPE; + CubitBoolean closed = CUBIT_FALSE; + DLIList<CubitVector*> mid_points; + Curve* curve = NULL; + if (point1_ptr != point2_ptr) + curve = make_Curve(type, point1_ptr, point2_ptr, mid_points); + else //could be a closed shape + { + if(third_point != NULL && face_ptr != NULL) + { + closed = CUBIT_TRUE; + Point * Pnt = make_Point(*third_point); + curve = make_Curve(type, point1_ptr, Pnt, mid_points); + } + else + { + PRINT_ERROR("Cannot create an OCC curve from the given duplicated points.\n"); + return (Curve *)NULL; + } + } + + Curve* new_curve = NULL; + if(face_ptr == NULL) + return curve; + + DLIList<Point*> points; + new_curve = + CAST_TO(curve, OCCCurve)->project_curve(face_ptr, points, closed, third_point); + + delete curve; + return new_curve; +} + +//=============================================================================== +// Function : make_Curve +// Member Type: PUBLIC +// Description: make a spline curve by using the points on surface. +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve( GeometryType curve_type, + Point const* point1_ptr, + Point const* point2_ptr, + DLIList<CubitVector*>& vector_list, + Surface* face_ptr) const +{ + assert(point1_ptr != NULL && point2_ptr != NULL); + + if (curve_type != SPLINE_CURVE_TYPE + && curve_type != STRAIGHT_CURVE_TYPE) + { + PRINT_ERROR("Cannot create an OCC curve from the given curve_type.\n" + "Candidates are SPLINE_CURVE_TYPE and STRAIGHT_CURVE_TYPE.\n"); + return (Curve *)NULL; + } + + if (curve_type == STRAIGHT_CURVE_TYPE) + return make_Curve(curve_type, point1_ptr, point2_ptr, NULL, CUBIT_FORWARD); + + OCCPoint* occ_point1 = CAST_TO(const_cast<Point*>(point1_ptr), OCCPoint); + OCCPoint* occ_point2 = CAST_TO(const_cast<Point*>(point2_ptr), OCCPoint); + + if (occ_point1 == NULL || occ_point2 == NULL) + { + PRINT_ERROR("Cannot create an OCC curve from the given points.\n" + "Possible incompatible geometry engines.\n"); + return (Curve *)NULL; + } + + //project all points on the surface if possible + OCCSurface* occ_face = NULL; + if (face_ptr != NULL) + occ_face = CAST_TO(face_ptr, OCCSurface); + + gp_Pnt pt; + int size = 2+vector_list.size(); + TColgp_Array1OfPnt points(1, size); + CubitVector* vector = NULL; + CubitVector closest_location; + for(int i = 1; i <= size; i++) + { + if (i == 1) + { + TopoDS_Vertex *point = occ_point1->get_TopoDS_Vertex(); + pt = BRep_Tool::Pnt(*point); + vector = new CubitVector(point1_ptr->coordinates()); + } + else if (i == size) + { + TopoDS_Vertex *point = occ_point2->get_TopoDS_Vertex(); + pt = BRep_Tool::Pnt(*point); + vector = new CubitVector(point2_ptr->coordinates()); + } + else + { + vector = vector_list.get_and_step(); + pt.SetCoord(vector->x(), vector->y(), vector->z()); + } + + if (occ_face != NULL) + { + occ_face->closest_point(*vector, &closest_location); + pt.SetCoord(closest_location.x(), closest_location.y(), closest_location.z()) ; + } + + points.SetValue(i, pt); + } + + //make curve according to the curve type. + if(curve_type == SPLINE_CURVE_TYPE) + { + Geom_BezierCurve BezierCurve(points); + Geom_BezierCurve* curve = new Geom_BezierCurve(BezierCurve); + Handle(Geom_BoundedCurve) curve_ptr(curve); + TopoDS_Vertex * vt1 = occ_point1->get_TopoDS_Vertex(); + TopoDS_Vertex * vt2 = occ_point2->get_TopoDS_Vertex(); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt2); + return OCCQueryEngine::instance()->populate_topology_bridge(new_edge); + } + + return (Curve*) NULL; +} + +//=============================================================================== +// Function : make_Curve +// Member Type: PUBLIC +// Description: make a curve +// For STRAIGHT_CURVE_TYPE: +// intermediate_point_ptr is not used +// +// For PARABOLA_CURVE_TYPE +// intermediate_point_ptr is the tip of the parabola +// +// For HYPERBOLA_CURVE_TYPE +// intermediate_point_ptr is the center of its two foci +// +// For ELLIPSE_CURVE_TYPE +// intermediate_point_ptr is the center of the ellipse +// the two points are vertices, one gives the major radius, +// the other point gives the minor radius. +// sense is used to determine which part of the ellipse is required +// +// For ARC_CURVE_TYPE +// arc passes three points +// +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve( GeometryType curve_type, + Point const* point1_ptr, + Point const* point2_ptr, + CubitVector const* intermediate_point_ptr, + CubitSense sense) const +{ + assert (point1_ptr != NULL && point2_ptr != NULL); + DLIList<CubitVector*> mid_points; + if (intermediate_point_ptr) + { + CubitVector mid_point = *intermediate_point_ptr; + mid_points.append(&mid_point); + } + + CubitVector v1(point1_ptr->coordinates()); + CubitVector v2(point2_ptr->coordinates()); + + gp_Pnt pt1(v1.x(),v1.y(), v1.z()); + gp_Pnt pt2(v2.x(),v2.y(), v2.z()); + + CubitVector v3; + gp_Pnt pt3; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + + Handle(Geom_TrimmedCurve) curve_ptr; + if(intermediate_point_ptr != NULL) + { + v3 = *intermediate_point_ptr; + pt3.SetCoord(v3.x(),v3.y(), v3.z()); + } + + if (curve_type == STRAIGHT_CURVE_TYPE) + curve_ptr = GC_MakeSegment(pt1,pt2); + + else if (curve_type == ARC_CURVE_TYPE) + { + assert(intermediate_point_ptr != NULL); + curve_ptr = GC_MakeArcOfCircle(pt1, pt3, pt2); + } + + else if (curve_type == ELLIPSE_CURVE_TYPE) + { + assert(intermediate_point_ptr != NULL); + + gp_Pnt center(v3.x(), v3.y(), v3.z()); + + gp_Elips ellipse; + gce_MakeElips ellipse1(pt1 , pt2 , center); + if(ellipse1.IsDone()) + ellipse = ellipse1.Value(); + else if(!ellipse1.IsDone() && ellipse1.Status() == gce_InvertRadius) + { + gce_MakeElips ellipse2(pt2, pt1, center); + if(ellipse2.IsDone()) + ellipse = ellipse2.Value(); + else + { + PRINT_ERROR("Can't create an ellipse from give 3 points.\n"); + return (Curve *)NULL; + } + } + else + { + PRINT_ERROR("Can't create an ellipse from give 3 points.\n"); + return (Curve *)NULL; + } + CubitBoolean use_sense = (sense == CUBIT_FORWARD ? CUBIT_TRUE : CUBIT_FALSE); + curve_ptr = GC_MakeArcOfEllipse(ellipse, pt1, pt2, use_sense); + } + + else if(curve_type == PARABOLA_CURVE_TYPE || + curve_type == HYPERBOLA_CURVE_TYPE) + { + assert(intermediate_point_ptr != NULL); + + //find the directrix and focus of the parabola + //or the axis, major radius and minor radius of the hyperbola + CubitVector width_vec = v2 - v1; + if(width_vec.length_squared() < tol * tol) + { + PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n" + "2 end points are the same.\n"); + return (Curve *)NULL; + } + + CubitVector midpoint_vec = (v1 + v2)/2.0; + CubitVector height_vec = midpoint_vec - v3; + gp_Pnt center(v3.x(), v3.y(), v3.z()); + + if (height_vec.length_squared() < tol * tol) + { + PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n" + "3 points are in the same line.\n"); + return (Curve *)NULL; + } + CubitVector x = height_vec; + x.normalize(); + gp_Dir x_dir(x.x(), x.y(), x.z()); + + CubitVector N = x * (v2 - v1); + if (N.length_squared() < tol * tol) + { + PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n" + "3 points are in the same line.\n"); + return (Curve *)NULL; + } + N.normalize(); + gp_Dir N_dir(N.x(), N.y(), N.z()); + + gp_Ax2 axis(center, N_dir, x_dir); + + if(curve_type == HYPERBOLA_CURVE_TYPE) + { + // (focus2) (v3) . (v2) + // . . . (midpoint = focus1) + // . (v1) + CubitVector focus2 = 2 * v3 - midpoint_vec; + + //according to the definition of hyperbola, + //2 * a = length(v2 - focus2)-length(v2 - focus1) + + double major = (v2 - focus2).length()/2.0 - (v2 - midpoint_vec).length()/2.0; + + // if a = 1/2 length major axis, b = 1/2 length minor axis and + // c = distance center to focus, then a*a + b*b = c*c + + double c_squared = (midpoint_vec - v3).length_squared(); + double minor = sqrt(c_squared - major*major ); + gp_Hypr hypt(axis, major, minor); + curve_ptr = + GC_MakeArcOfHyperbola(hypt, pt1, pt2, CUBIT_TRUE); + } + + else + { + // Find the focus of this parabola. + // Since for a parabola with its peak at the origin, y = (1/(4*a))*x^2, + // and since we have restricted this parabola to be symmetric (per the + // FastQ method, see the FastQ file getwt.f), we can use the following + // relationship to + // determine "a", the distance the focus lies from the peak on the line + // formed by the peak and the midpoint of the start and end points` + double a = width_vec.length_squared()/(16. * height_vec.length()); + gp_Parab parab(axis, a); + curve_ptr = + GC_MakeArcOfParabola(parab, pt1, pt2, CUBIT_TRUE); + } + } + + else + { + PRINT_ERROR("In OCCModifyEngine::make_Curve\n" + " Invalid curve type.\n"); + return (Curve *)NULL; + } + + OCCPoint* occ_pt1 = CAST_TO(const_cast<Point*>(point1_ptr),OCCPoint); + OCCPoint* occ_pt2 = CAST_TO(const_cast<Point*>(point2_ptr),OCCPoint); + TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex(); + TopoDS_Vertex * vt2 = occ_pt2->get_TopoDS_Vertex(); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt2); + return OCCQueryEngine::instance()->populate_topology_bridge(new_edge); +} + +//=============================================================================== +// Function : make_Surface +// This function creates a surface given an existing surface, copy. +// Member Type: PUBLIC +// Description: make a surface, OCC allows to create a stand along surface, +// however the CGM has a design of making all surfaces in a (sheet) +// body. This will add complexity on all free surface related +// calculation and modification, and adding potential bugs too. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +Surface* OCCModifyEngine::make_Surface( Surface * surface_ptr, + CubitBoolean extended_from) const +{ + OCCSurface* occ_surface = CAST_TO(surface_ptr, OCCSurface); + if (!occ_surface) + { + PRINT_ERROR("Cannot create an OCC surface from the given surface.\n" + "Possible incompatible geometry engines.\n"); + return (Surface *)NULL; + } + + //Start of the codes + double UMax, VMax, UMin, VMin; + occ_surface->get_param_range_U(UMin, UMax); + occ_surface->get_param_range_V(VMin, VMax); + + TopoDS_Face *theFace = occ_surface->get_TopoDS_Face(); + if( !theFace) + { + PRINT_ERROR("Cannot create an OCC surface from the given surface.\n" + "Possible incompatible geometry engines.\n"); + return (Surface *)NULL; + } + + TopoDS_Face newFace; + BRepAdaptor_Surface asurface(*theFace); + + CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box(); + double const height = 2*(bounding_box.diagonal()).length(); + CubitBox box = occ_surface->bounding_box(); + double ratio = height/(box.diagonal().length()); + + double middleU = (UMin + UMax)/2.0; + double middleV = (VMin + VMax)/2.0; + double U1 = middleU - (UMax-UMin)/2.0 * ratio; + double U2 = middleU + (UMax-UMin)/2.0 * ratio; + double V1 = middleV - (VMax - VMin)/2.0 * ratio; + double V2 = middleV + (VMax - VMin)/2.0 * ratio; + + if (extended_from == CUBIT_TRUE) + { + // We need to get the type of surface. + GeometryType type = occ_surface->geometry_type(); + if (type == PLANE_SURFACE_TYPE) + { + gp_Pln plane = asurface.Plane(); + newFace = BRepBuilderAPI_MakeFace(plane, U1, U2, V1, V2); + } + else if(type == CONE_SURFACE_TYPE) + { + //make an infinite cone. + //Given this lets create another face that is extended from it. + if(asurface.GetType() == GeomAbs_Cone) + { + gp_Cone cone = asurface.Cone(); + gp_Pnt Apex = cone.Apex(); + double semi_angle = cone.SemiAngle(); + gp_Pnt p2; + double radius2; + gp_XYZ xyz; + if (semi_angle > 0) + xyz = Apex.XYZ() + cone.Position().Direction().XYZ()*height; + + else + xyz = Apex.XYZ() - cone.Position().Direction().XYZ()*height; + + p2.SetXYZ(xyz); + radius2 = height * tan(fabs(semi_angle)); + Handle(Geom_RectangularTrimmedSurface) trimmed_cone; + trimmed_cone = GC_MakeTrimmedCone(Apex, p2, 0, radius2); + newFace = BRepBuilderAPI_MakeFace(trimmed_cone); + } + else + { + gp_Cylinder cylinder = asurface.Cylinder(); + //gp_Pnt pnt = asurface.Value(UMin,V1); + double radius = cylinder.Radius(); + gp_Ax1 axis = cylinder.Axis(); + Handle(Geom_RectangularTrimmedSurface) trimmed_cyl; + trimmed_cyl = GC_MakeTrimmedCylinder(axis, radius, height); + newFace = BRepBuilderAPI_MakeFace(trimmed_cyl); + } + } + else if(type == SPHERE_SURFACE_TYPE) + { + //make a whole sphere. + gp_Sphere sphere = asurface.Sphere(); + newFace = BRepBuilderAPI_MakeFace(sphere); + } + else if(type == TORUS_SURFACE_TYPE) + { + //make a whole torus + gp_Torus torus = asurface.Torus(); + newFace = BRepBuilderAPI_MakeFace(torus); + } + else if(type == SPLINE_SURFACE_TYPE ) + { + //extend the surfaces using the equation if possible. + Handle(Geom_BezierSurface) bezier = asurface.Bezier(); + newFace = BRepBuilderAPI_MakeFace(bezier, U1, U2, V1, V2); + } + } + + else + { + BRepBuilderAPI_Copy api_copy(*theFace); + TopoDS_Shape newShape = api_copy.ModifiedShape(*theFace); + newFace = TopoDS::Face(newShape); + } + + Surface *surface = OCCQueryEngine::instance()->populate_topology_bridge( + newFace, CUBIT_TRUE); + + return surface; +} + +//=============================================================================== +// Function : make_Surface +// Member Type: PUBLIC +// Description: make a surface of type surface_type, given the list of curves. +// check edges option is done in GeometryModifyTool level, so +// disregard this option. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +Surface* OCCModifyEngine::make_Surface( GeometryType surface_type, + DLIList<Curve*>& curve_list, + Surface * old_surface_ptr, + bool check_edges) const +{ + //Create TopoDS_Edge list to make a surface. + DLIList<DLIList<TopoDS_Edge*>*> topo_edges_loops; + curve_list.reset() ; + + //check no intersections of the TopoDS_Edge's. + //need to check that no intersection in the middle of the curves, not at + //vertices or out of boundary. + + int count = 0; //intersection point should be the same as curve_list size. + for ( int i = 0 ; i < curve_list.size()-1 ; i++ ) + { + for(int j = i+1; j < curve_list.size(); j ++) + { + DLIList<CubitVector*> intscts; + CubitBoolean bounded = CUBIT_TRUE;//dummy arg. + CubitBoolean closest = CUBIT_TRUE;//dummy arg. + CubitStatus yes_int = + OCCQueryEngine::instance()->get_intersections(curve_list[i], + curve_list[j], intscts, bounded, closest); + if(yes_int) + { + //check intscts point should be vertex or outside boundary. + if (intscts.size() > 2 ) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface with intersecting curves.\n"); + return (Surface *)NULL; + } + else + { + for(int k = 0; k < intscts.size(); k++) + { + CubitVector *v = intscts.get_and_step(); + CubitPointContainment is_on = CAST_TO(curve_list[i],OCCCurve)-> + point_containment(*v); + if (is_on == CUBIT_PNT_BOUNDARY) + { + is_on = CAST_TO(curve_list[j],OCCCurve)-> + point_containment(*v); + if (is_on == CUBIT_PNT_BOUNDARY) + count++; + } + else if(is_on == CUBIT_PNT_INSIDE) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface with intersecting curves.\n"); + return (Surface *)NULL; + } + } + } + } + } + } + + if (count > curve_list.size()) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface with intersecting curves.\n"); + return (Surface *)NULL; + } + + CubitStatus stat = sort_curves(curve_list, topo_edges_loops); + if( stat == CUBIT_FAILURE ) //case of one disconnected curve + return (Surface*) NULL; + + // Use the topo_edges to make a topo_face + TopoDS_Face* topo_face; + topo_face = make_TopoDS_Face(surface_type,topo_edges_loops, old_surface_ptr); + + for (int i = 0; i < topo_edges_loops.size(); i++) + { + DLIList<TopoDS_Edge*>* topo_edges = topo_edges_loops.get_and_step(); + for(int j = 0; j < topo_edges->size(); j++) + topo_edges->pop(); + delete topo_edges; + } + + if(!topo_face) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface object.\n"); + return (Surface *)NULL; + } + + // make the topology bridges for the face + Surface *surface = OCCQueryEngine::instance()->populate_topology_bridge( + *topo_face, CUBIT_TRUE); + topo_face->Nullify(); + delete topo_face; + return surface ; +} + +//=============================================================================== +// Function : sort_curves +// Member Type: PROTECTED +// Description: sort the curves so they are in order and make closed loop +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::sort_curves(DLIList<Curve*> curve_list, + DLIList<DLIList<TopoDS_Edge*>*>& topo_edges_loops)const +{ + topo_edges_loops.clean_out(); + CubitStatus stat = CUBIT_SUCCESS; + std::vector< DLIList<TopoDS_Edge*>* > topo_edges(curve_list.size()); + int size_in = curve_list.size(); + for(int i = 0; i < size_in; i++) + topo_edges[i] = new DLIList<TopoDS_Edge*>; + + curve_list.reset() ; + Curve const* curve_ptr = NULL ; + OCCCurve* occ_curve = NULL; + TopoDS_Edge* topo_edge = NULL; + + OCCPoint* start = NULL; + OCCPoint* end = NULL; + DLIList<OCCPoint*> point_list; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + CubitBoolean new_end; + int size = curve_list.size(); + + int count = 0; + for ( int i = 0 ; i < size ; i++ ) + { + if (i == 0) + new_end = CUBIT_TRUE; + for(int j = 0; j < curve_list.size(); j ++) + { + curve_ptr = curve_list.get() ; + occ_curve = CAST_TO(const_cast<Curve*>(curve_ptr), OCCCurve); + + if(occ_curve == NULL) + { + PRINT_ERROR("In OCCModifyEngine::sort_curves\n" + " Got a NULL pointer to OCCCurve\n") ; + return CUBIT_FAILURE; + } + + point_list.clean_out(); + occ_curve->get_points(point_list); + //assert(point_list.size()==2); + + if (i == 0) + { + start = point_list.get(); + end = point_list.pop(); + break; + } + + if(end->is_equal(*(point_list.get()), tol) || + end->is_equal(*(point_list.step_and_get()),tol)) + { + end = point_list.step_and_get(); + new_end = CUBIT_TRUE; + break; + } + + else if(start->is_equal(*(point_list.get()), tol) || + start->is_equal(*(point_list.step_and_get()),tol)) + { + start = end; + end = point_list.step_and_get(); + new_end = CUBIT_TRUE; + break; + } + curve_list.step(); + } + + if (new_end)//found next curve + { + topo_edge = occ_curve->get_TopoDS_Edge(); + topo_edges[count]->append(topo_edge); + curve_list.remove(); + if(start->is_equal( *end, tol)) //formed a closed loop + { + i = -1; + size = curve_list.size() ; + topo_edges_loops.append(topo_edges[count]); + count++; + } + else + new_end = CUBIT_FALSE; + } + else + { + stat = CUBIT_FAILURE; + i = -1; + size = curve_list.size(); + topo_edges_loops.append(topo_edges[count]); + count++; + } + } + + if( new_end == CUBIT_FALSE ) //case of one disconnected curve + { + topo_edges_loops.append(topo_edges[count]); + stat = CUBIT_FAILURE; + } + + for(int i = 0; i < size_in; i++) + { + if(topo_edges[i]->size() == 0) + delete topo_edges[i]; + } + return stat; +} +//=============================================================================== +// Function : make_TopoDS_Face +// Member Type: PROTECTED +// Description: make a opoDS_Face of type surface_type, given the list of +// TopoDS_Edge. the TopoDS_Edge's should be in order in loops. +// check edges option is done in GeometryModifyTool level, so +// disregard this option. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +TopoDS_Face* OCCModifyEngine::make_TopoDS_Face(GeometryType surface_type, + DLIList<DLIList<TopoDS_Edge*>*> topo_edges_list, + Surface * old_surface_ptr)const +{ + TopoDS_Face* topo_face = NULL; + // Make sure a supported type of surface is being requested. + if ( surface_type != PLANE_SURFACE_TYPE && + surface_type != BEST_FIT_SURFACE_TYPE) + { + PRINT_WARNING("In OCCGeometryEngine::make_TopoDS_Face\n" + " At this time, cannot make a TopoDS_Face that isn't" + " planar or best fit.\n"); + return topo_face; + } + + // Set the TopoDS_Face pointer, if requested. + TopoDS_Face *fit_Face = NULL; + Handle_Geom_Surface S; + if ( old_surface_ptr != NULL ) + { + OCCSurface *surf = CAST_TO(old_surface_ptr, OCCSurface ); + fit_Face = surf->get_TopoDS_Face(); + S = BRep_Tool::Surface(*fit_Face); + } + + // Make a wire from the topo_edges. + // Coincident TopoDS_Vertex will be deleted by OCC. + if(topo_edges_list.size() == 0) + return topo_face; + + DLIList<TopoDS_Wire*> wires; + GProp_GProps myProps; + double max_area = 0.0; + TopoDS_Wire* out_Wire = NULL; + TopoDS_Wire test_Wire; + DLIList<TopoDS_Edge*>* topo_edges; + //check and make sure the outer loop is in the first + for(int i = 0; i < topo_edges_list.size() ; i++) + { + topo_edges = topo_edges_list.get_and_step(); + BRepBuilderAPI_MakeWire aWire(*(topo_edges->get())); + for(int j = 1; j < topo_edges->size(); j++) + aWire.Add(*(topo_edges->step_and_get())); + + test_Wire = aWire.Wire(); + wires.append(&test_Wire); + + if (topo_edges_list.size() == 1) + break; + + BRepBuilderAPI_MakeFace made_face(test_Wire); + + if (!made_face.IsDone()) + { + PRINT_ERROR("In OCCModifyEngine::make_TopoDS_Face\n" + " Cannot find the best fit surface for given curves.\n"); + return topo_face; + } + TopoDS_Face test_face = made_face.Face(); + BRepGProp::SurfaceProperties(test_face, myProps); + double area = myProps.Mass(); + out_Wire = max_area > area ? out_Wire : &test_Wire; + max_area = max_area > area ? max_area : area; + } + + if (out_Wire) + { + wires.remove(out_Wire); + wires.insert_first(out_Wire); + } + + //create the TopoDS_Face + CubitBoolean error = CUBIT_FALSE; + + for(int i = 0; i < topo_edges_list.size() ; i++) + { + TopoDS_Wire *the_wire = wires.get_and_step(); + if (i == 0) + { + if( old_surface_ptr != NULL ) + { + BRepBuilderAPI_MakeFace made_face(S, *the_wire); + if (!made_face.IsDone()) + { + error = CUBIT_TRUE; + break; + } + topo_face = new TopoDS_Face(made_face.Face()); + } + else + { + CubitBoolean is_planar = (surface_type == PLANE_SURFACE_TYPE ? + CUBIT_TRUE : CUBIT_FALSE); + BRepBuilderAPI_MakeFace made_face(*the_wire, is_planar); + if (!made_face.IsDone()) + { + error = CUBIT_TRUE; + break; + } + + topo_face = new TopoDS_Face(made_face.Face()); + } + } + else + { + BRepBuilderAPI_MakeFace made_face(*topo_face, *the_wire); + if (!made_face.IsDone()) + { + error = CUBIT_TRUE; + break; + } + delete topo_face; + topo_face = new TopoDS_Face(made_face.Face()); + } + } + + if(error) + { + PRINT_ERROR("In OCCModifyEngine::make_TopoDS_Face\n" + " Cannot find the best fit surface for given curves.\n"); + return (TopoDS_Face*) NULL; + } + + return topo_face; +} +//=============================================================================== +// Function : make_Lump +// Member Type: PUBLIC +// Description: make a lump of one shell +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +Lump* OCCModifyEngine::make_Lump( DLIList<Surface*>& surface_list ) const +{ + if (surface_list.size() < 2) + return (Lump*) NULL; + + //all surfaces should be stand along surface bodies or shell bodies' surface + DLIList<BodySM*> body_list; + for(int i = 0; i < surface_list.size(); i++) + { + OCCSurface* occ_surface = CAST_TO(surface_list.get_and_step(), OCCSurface); + if (occ_surface == NULL) + { + PRINT_ERROR("Cannot create an OCC lump from the given surfaces.\n" + "Possible incompatible geometry engines.\n"); + return (Lump *)NULL; + } + OCCBody* occ_body = occ_surface->my_body(); + if(occ_body && occ_body->my_sheet_surface() == NULL) + { + PRINT_ERROR("Cannot create an OCC lump from the given surfaces.\n" + "The surfaces are not free.\n"); + return (Lump *)NULL; + } + else if(!occ_body) + { + OCCShell* shell = occ_surface->my_shell(); + if(!shell) + { + PRINT_ERROR("This is a bug, please report it. \n"); + return (Lump*)NULL; + } + occ_body = shell->my_body(); + } + body_list.append_unique(occ_body); + } + + TopoDS_Shape aShape; + CubitStatus stat = stitch_surfs(body_list, aShape); + if(!stat) + { + PRINT_ERROR("The surfaces are not all connected, can't make a lump. \n"); + return (Lump*)NULL; + } + + TopExp_Explorer Ex, Ex2; + TopoDS_Shell aShell ; + for (Ex.Init(aShape, TopAbs_SHELL, TopAbs_SOLID); Ex.More()&& stat; Ex.Next()) + aShell = TopoDS::Shell(Ex.Current()); + + //check to make sure the aShell is closed. + int num_edges = 0; + int pairs = 0; + //sometimes there's duplicate TopoDS_Edges in the shell. + DLIList<TopoDS_Edge*> edge_list; + for (Ex.Init(aShell, TopAbs_EDGE); Ex.More()&& stat; Ex.Next()) + { + TopoDS_Edge edge1 = TopoDS::Edge(Ex.Current()); + TopoDS_Edge* new_edge = new TopoDS_Edge(edge1); + edge_list.append(new_edge); + } + + int size = edge_list.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Edge edge1 = *edge_list[i]; + int same = 0; + for (int j = i+1; j < edge_list.size(); j++) + { + TopoDS_Edge edge2 = *edge_list[j]; + if(edge1.IsEqual(edge2)) + { + same ++; + edge_list.remove(&edge1); + i--; + size--; + break; + } + } + if(same > 0) + continue; + + else + num_edges++; + + for (int j = 0; j < size; j++) + { + TopoDS_Edge edge2 = *edge_list[j]; + if (!edge1.IsEqual(edge2)&& edge1.IsSame(edge2)) + { + pairs++; + break; + } + } + } + + for (int k = 0; k < edge_list.size(); k++) + { + TopoDS_Edge* edge = edge_list.get_and_step(); + edge->Nullify(); + delete edge; + } + + if (num_edges == pairs ) + aShell.Closed(CUBIT_TRUE); + + else + PRINT_ERROR("Surfaces must make a water-tight shape to make a lump.\n"); + + if(aShell.Closed()) + { + BRepBuilderAPI_MakeSolid aMakeSolid(aShell); + if (!aMakeSolid.IsDone()) + { + PRINT_ERROR("Cannot create an OCC Lump from the given surfaces.\n" + "OCC internal error.\n"); + return (Lump *)NULL; + } + + TopoDS_Solid aSolid = aMakeSolid.Solid(); + + return + OCCQueryEngine::instance()->populate_topology_bridge(aSolid, CUBIT_TRUE); + } + + return (Lump*) NULL; +} + +//=============================================================================== +// Function : make_BodySM +// Member Type: PUBLIC +// Description: make a BodySM from a surface +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +BodySM* OCCModifyEngine::make_BodySM( Surface *surface ) const +{ + OCCSurface* occ_surface = CAST_TO(surface, OCCSurface); + if(!occ_surface) + { + PRINT_ERROR("Cannot create an OCC body from the given surface.\n" + "Possible incompatible geometry engines.\n"); + return (BodySM *)NULL; + } + + OCCBody* occ_body = occ_surface->my_body(); + if(occ_body) + return occ_body; + + TopoDS_Face* face = occ_surface->get_TopoDS_Face(); + surface = OCCQueryEngine::instance()->populate_topology_bridge(*face, CUBIT_TRUE); + + return CAST_TO(surface, OCCSurface)->my_body(); +} + + + +//=============================================================================== +// Function : make_BodySM +// Member Type: PUBLIC +// Description: make a BodySM given a list of Lumps. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +BodySM* OCCModifyEngine::make_BodySM( DLIList<Lump*>& lump_list ) const +{ + if (lump_list.size() == 0) + return (BodySM*) NULL; + + //Create a compsolid shape, copy all BodySM's solids to create new compbody + DLIList<BodySM*> bodysm_list; + TopoDS_CompSolid CS; + BRep_Builder B; + B.MakeCompSolid(CS); + + //Add every shape to the CompSolid + for(int i = 0; i < lump_list.size(); i++) + { + Lump* lump = lump_list.get_and_step(); + OCCLump* occ_lump = CAST_TO(lump, OCCLump); + if(!occ_lump) + { + PRINT_ERROR("Cannot create an OCC BodySM from the given lumps.\n" + "Possible incompatible geometry engines.\n"); + return (BodySM *)NULL; + } + TopoDS_Solid* solid = occ_lump->get_TopoDS_Solid(); + BRepBuilderAPI_Copy api_copy(*solid); + TopoDS_Shape newShape = api_copy.ModifiedShape(*solid); + B.Add(CS, newShape); + } + + BodySM* bodysm = OCCQueryEngine::instance()->populate_topology_bridge(CS); + + return bodysm; + +} + + +//=============================================================================== +// Function : sphere +// Member Type: PUBLIC +// Description: build an OCC sphere +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::sphere(double radius) const +{ + if (radius <= 0) + return (BodySM*) NULL; + + TopoDS_Solid S = BRepPrimAPI_MakeSphere(radius); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + if (lump == NULL) + return (BodySM*)NULL; + + return CAST_TO(lump, OCCLump)->get_body(); +} + + +//=============================================================================== +// Function : brick +// Member Type: PUBLIC +// Description: build an OCC brick +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::brick( double wid, double dep, double hi ) const +{ + if (wid <= 0 || dep <=0 || hi <= 0) + return (BodySM*)NULL; + + TopoDS_Solid S = BRepPrimAPI_MakeBox(wid, dep, hi); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + + if (lump == NULL) + return (BodySM*)NULL; + + BodySM* body = CAST_TO(lump, OCCLump)->get_body(); + if(body) + CAST_TO(body,OCCBody)->move(-wid/2.0, -dep/2.0, -hi/2.0); + return body; +} + + +//=============================================================================== +// Function : brick +// Member Type: PUBLIC +// Description: create an OCC brick given center axes and extension +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::brick( const CubitVector& center, + const CubitVector axes[3], + const CubitVector &extension) const +{ + CubitVector left_corner = center - 0.5 * extension; + gp_Pnt left_point(left_corner.x(), left_corner.y(), left_corner.z()); + gp_Dir main_dir(axes[2].x(), axes[2].y(), axes[2].z()); + gp_Dir x_dir(axes[0].x(), axes[0].y(), axes[0].z()); + gp_Ax2 Axis(left_point, main_dir, x_dir); + TopoDS_Solid S = BRepPrimAPI_MakeBox( Axis, extension.x(), extension.y(), + extension.z()); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + if (lump == NULL) + return (BodySM*)NULL; + + return CAST_TO(lump, OCCLump)->get_body(); +} + +//=============================================================================== +// Function : prism +// Member Type: PUBLIC +// Description: create an OCC prism +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::prism( double height, int sides, double major, + double minor) const +{ + //currently OCC only support 4 sided prism + if (sides != 4) + { + PRINT_ERROR("Option not supported for OCC based geometry.\n"); + return (BodySM*) NULL; + } + + return brick(2 * major, 2 * minor, height); +} + +//=============================================================================== +// Function : pyramid +// Member Type: PUBLIC +// Description: create an OCC pyramid +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::pyramid( double height, int sides, double major, + double minor, double top) const +{ + //currently OCC only support 4 sided pyramid + if (sides != 4) + { + PRINT_ERROR("Option not supported for OCC based geometry.\n"); + return (BodySM*) NULL; + } + + TopoDS_Solid S = BRepPrimAPI_MakeWedge( 2 * major, 2* minor, height, + 2 * top); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + if (lump == NULL) + return (BodySM*)NULL; + + BodySM* body = CAST_TO(lump, OCCLump)->get_body(); + if(body) + CAST_TO(body, OCCBody)->move(-major, -minor, -height/2.0); + return body; + +} + +//=============================================================================== +// Function : cylinder +// Member Type: PUBLIC +// Description: create an OCC cylinder, its base shape can be ellipse with +// r1, r2 while r3 = 0; or it can be a cone with r1, +// r3 while r2 = 0. +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::cylinder( double hi, double r1, double r2, double r3 ) const +{ + TopoDS_Solid S; + if(r2 != r1)//elliptical based cylinder + { + gp_Pnt center(0.0, 0.0, 0.0); + gp_Dir main_dir(0.0, 0.0, 1.0); + gp_Dir x_dir(1.0, 0.0, 0.0); + gp_Ax2 Axis(center, main_dir, x_dir); + Handle(Geom_Curve) curve_ptr = GC_MakeEllipse(Axis, r1, r2); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr); + BRepBuilderAPI_MakeWire aWire(new_edge); + + TopoDS_Wire test_Wire = aWire.Wire(); + + BRepOffsetAPI_ThruSections builder(CUBIT_TRUE, CUBIT_TRUE); + builder.AddWire(test_Wire); + if (r3 == 0) + { + gp_Pnt pt = gp_Pnt( 0.0, 0.0, hi); + TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt); + builder.AddVertex(theVertex); + } + else + { + gp_Pnt center2(0.0, 0.0,hi); + gp_Ax2 Axis2(center2, main_dir, x_dir); + Handle(Geom_Curve) curve_ptr = GC_MakeEllipse(Axis2, r3, r3*r2/r1); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr); + BRepBuilderAPI_MakeWire aWire(new_edge); + TopoDS_Wire test_Wire = aWire.Wire(); + builder.AddWire(test_Wire); + } + builder.Build() ; + S = TopoDS::Solid(builder.Shape()); + } + + else // cone + { + if(r1 == r3) //cylinder + S = BRepPrimAPI_MakeCylinder(r1, hi); + else + S = BRepPrimAPI_MakeCone(r1, r3, hi); + } + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + + if (lump == NULL) + { + PRINT_ERROR("In OCCModifyEngine::cylinder\n" + " Cannot create a cylinder for given radii.\n"); + return (BodySM*)NULL; + } + + BodySM* body = CAST_TO(lump, OCCLump)->get_body(); + if(body) + CAST_TO(body, OCCBody)->move(0, 0, -hi/2.0); + return body; +} + +//=============================================================================== +// Function : torus +// Member Type: PUBLIC +// Description: create an OCC torus +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::torus( double r1, double r2 ) const +{ + if (r1 <= 0 || r2 <= 0) + return (BodySM*) NULL; + + TopoDS_Solid S = BRepPrimAPI_MakeTorus(r1, r2); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + + if (lump == NULL) + { + PRINT_ERROR("In OCCModifyEngine::torus\n" + " Cannot create a torus for given radii.\n"); + return (BodySM*)NULL; + } + + return CAST_TO(lump, OCCLump)->get_body(); +} + +//=============================================================================== +// Function : planar_sheet +// Member Type: PUBLIC +// Description: create an OCC planar_sheet with four vectors. +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::planar_sheet ( const CubitVector& p1, + const CubitVector& p2, + const CubitVector& p3, + const CubitVector& p4) const +{ + Point* point1 = make_Point(p1); + Point* point2 = make_Point(p2); + Point* point3 = make_Point(p3); + Point* point4 = make_Point(p4); + Curve * curve1 = make_Curve( point1, point2); + if (curve1 == NULL) + return (BodySM*) NULL; + Curve * curve2 = make_Curve( point2, point3); + if (curve2 == NULL) + return (BodySM*) NULL; + Curve * curve3 = make_Curve( point3, point4); + if (curve3 == NULL) + return (BodySM*) NULL; + Curve * curve4 = make_Curve( point4, point1); + if (curve4 == NULL) + return (BodySM*) NULL; + DLIList<Curve*> curves; + curves.append(curve1); + curves.append(curve2); + curves.append(curve3); + curves.append(curve4); + Surface* surface = make_Surface(PLANE_SURFACE_TYPE, curves); + if (surface == NULL) + return (BodySM*) NULL; + return CAST_TO(surface,OCCSurface)->my_body(); +} + +//=============================================================================== +// Function : copy_body +// Member Type: PUBLIC +// Description: copy an OCC-based body +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::copy_body ( BodySM* bodyPtr ) const +{ + OCCBody* occ_body = CAST_TO(bodyPtr, OCCBody); + if (!occ_body) + { + PRINT_ERROR("Cannot create an OCC bodySM from the given bodySM.\n" + "Possible incompatible geometry engines.\n"); + return (BodySM *)NULL; + } + + TopoDS_CompSolid *theCS = occ_body->get_TopoDS_Shape(); + + if (theCS == NULL) //sheet body + { + OCCShell* occ_shell = occ_body->shell(); + if (occ_shell != NULL) + { + TopoDS_Shell* shell = occ_shell->get_TopoDS_Shell(); + BRepBuilderAPI_Copy api_copy(*shell); + TopoDS_Shape newShape = api_copy.ModifiedShape(*shell); + TopoDS_Shell newShell = TopoDS::Shell(newShape); + return OCCQueryEngine::instance()->populate_topology_bridge(newShell, CUBIT_TRUE)->my_body(); + } + + Surface* surface = make_Surface(occ_body->my_sheet_surface()); + if (surface == NULL) + { + PRINT_ERROR("Cannot create an OCC sheet bodySM from the given bodySM.\n"); + return (BodySM *)NULL; + } + + return CAST_TO(surface,OCCSurface)->my_body(); + } + + if(OCCQueryEngine::instance()->OCCMap->IsBound(*theCS)) + { + BRepBuilderAPI_Copy api_copy(*theCS); + + TopoDS_Shape newShape = api_copy.ModifiedShape(*theCS); + + TopoDS_CompSolid newCS = TopoDS::CompSolid(newShape); + + return OCCQueryEngine::instance()->populate_topology_bridge(newCS); + } + + //single lump body + Lump *lump = occ_body->lumps().get(); + TopoDS_Solid solid = *(CAST_TO(lump, OCCLump)->get_TopoDS_Solid()); + BRepBuilderAPI_Copy api_copy(solid); + TopoDS_Shape newShape = api_copy.ModifiedShape(solid); + TopoDS_Solid newSolid = TopoDS::Solid(newShape); + lump = OCCQueryEngine::instance()->populate_topology_bridge(newSolid, + CUBIT_TRUE); + + return CAST_TO(lump, OCCLump)->get_body(); +} + +//=============================================================================== +// Function : stitch_surfs +// Member Type: PUBLIC +// Description: stitch all surfs and try to make a shell body. +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::stitch_surfs( + DLIList<BodySM*>& surf_bodies, + BodySM*& new_body) const +{ + new_body = NULL; + if (surf_bodies.size()==0) + return CUBIT_SUCCESS; + + if (surf_bodies.size()==1) + { + new_body = surf_bodies.get(); + return CUBIT_SUCCESS; + } + + TopoDS_Shape fuse; + CubitStatus stat = stitch_surfs(surf_bodies, fuse); + + DLIList<TopologyBridge*> tbs = OCCQueryEngine::instance()-> + populate_topology_bridge(fuse); + + if (stat) + { + OCCBody* body = CAST_TO(tbs.get(), OCCBody); + + if (body) + new_body = body ; + } + + else + { + surf_bodies.clean_out(); + for(int i= 0; i<tbs.size(); i++) + surf_bodies.append(CAST_TO(tbs.get_and_step(), OCCBody)); + } + + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : stitch_surfs +// Member Type: PUBLIC +// Description: stitch all surfs and try to make a TopoDS_Shell . +// called by stitch into surface body +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::stitch_surfs( + DLIList<BodySM*>& surf_bodies, + TopoDS_Shape& fuse) const +{ + if (surf_bodies.size() < 2) + return CUBIT_SUCCESS; + + DLIList<TopoDS_Shape*> faces_to_stitch; + for (int i = 0; i < surf_bodies.size(); i++) + { + BodySM * tool_body = surf_bodies.get_and_step(); + OCCBody* occ_body = CAST_TO(tool_body, OCCBody); + OCCSurface* surface = occ_body->my_sheet_surface(); + OCCShell* shell = occ_body->shell(); + if (surface == NULL && shell == NULL) + { + PRINT_ERROR("Can't stitch non-sheet bodySM's. \n"); + return CUBIT_FAILURE; + } + + delete occ_body; + if (surface) + { + delete surface->my_shell(); + delete surface->my_lump(); + surface->set_shell(NULL); + surface->set_lump(NULL); + surface->set_body(NULL); + + TopoDS_Face* topods_face = surface->get_TopoDS_Face(); + if (topods_face != NULL) + faces_to_stitch.append(topods_face); + } + else + { + delete shell->my_lump(); + shell->set_body(NULL); + shell->set_lump(NULL); + + TopoDS_Shell* topods_shell = shell->get_TopoDS_Shell(); + if(topods_shell) + faces_to_stitch.append(topods_shell); + } + } + + faces_to_stitch.reset(); + surf_bodies.reset(); + TopoDS_Shape* first_face = faces_to_stitch.pop(); + + TopoDS_Shape* second_face = NULL; + for( int i = faces_to_stitch.size()-1; i >= 0; i --) + { + second_face = faces_to_stitch[i]; + BRepAlgoAPI_Fuse fuser(*second_face, *first_face); + + TopoDS_Shape new_shape ; + for(int j = 0; j < 2; j++) + { + TopTools_IndexedMapOfShape M; + if(j == 0) + TopExp::MapShapes(*second_face, TopAbs_FACE, M); + else + TopExp::MapShapes(*first_face, TopAbs_FACE, M); + for(int ii=1; ii<=M.Extent(); ii++) + { + TopoDS_Face face = TopoDS::Face(M(ii)); + TopTools_ListOfShape shapes; + shapes.Assign(fuser.Modified(face)); + if (shapes.Extent() == 1) + { + new_shape = shapes.First(); + OCCSurface::update_OCC_entity(face, TopoDS::Face(new_shape), &fuser); + } + else if(fuser.IsDeleted(face) || shapes.Extent() > 1) + { + TopoDS_Face null_face; + OCCSurface::update_OCC_entity(face, null_face, &fuser); + } + } + } + + fuse = fuser.Shape(); + first_face = &fuse; + } + + TopExp_Explorer Ex; + int count_shell = 0; + for (Ex.Init(fuse, TopAbs_SHELL, TopAbs_SOLID); Ex.More(); Ex.Next()) + count_shell++; + + if ( count_shell != 1) + { + PRINT_ERROR("Can't stitch all surfaces into one BodySM's. \n"); + return CUBIT_FAILURE; + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : subtract +// Member Type: PUBLIC +// Description: subtract boolean operation on OCC-based bodies +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::subtract(DLIList<BodySM*> &tool_body_list, + DLIList<BodySM*> &from_bodies, + DLIList<BodySM*> &new_bodies, + bool imprint, + bool keep_old) const +{ + // copy the bodies in case keep_old is true + DLIList<TopoDS_Shape*> tool_bodies_copy; + + //for subtract function, tool-body has to be solid, + //otherwise it's just imprint + DLIList<CubitBox*>* tool_boxes = new DLIList<CubitBox*>(); + DLIList<CubitBoolean> is_tool_volume; + //keep the tool_body untouched + CubitStatus stat = + get_shape_list(tool_body_list, tool_bodies_copy, is_tool_volume, CUBIT_TRUE, tool_boxes); + + if(!stat) + return stat; + + //check that tool_bodies are all solid, shell and surface body can't be used + //for subtracting purpose. + if(is_tool_volume.is_in_list(CUBIT_FALSE)) + { + PRINT_WARNING("Surfaces or Shells can't be used to cut a body.\n"); + while (tool_boxes->size()) + delete tool_boxes->pop(); + delete tool_boxes; + while (tool_bodies_copy.size()) + delete tool_bodies_copy.pop(); + return CUBIT_FAILURE; + } + + stat = do_subtract(from_bodies, tool_bodies_copy, is_tool_volume, + tool_boxes, new_bodies, keep_old, imprint) ; + + //ok, we're done wih all cuts, delete unnecessaries. + while (tool_boxes->size()) + delete tool_boxes->pop(); + delete tool_boxes; + while (tool_bodies_copy.size()) + delete tool_bodies_copy.pop(); + if(!keep_old) //delete tool_bodies + OCCQueryEngine::instance()->delete_solid_model_entities(tool_body_list); + return stat; +} + +CubitStatus OCCModifyEngine::do_subtract(DLIList<BodySM*> &from_bodies, + DLIList<TopoDS_Shape*> &tool_bodies_copy, + DLIList<CubitBoolean> &is_tool_volume, + DLIList<CubitBox*>* tool_boxes, + DLIList<BodySM*> &new_bodies, + bool keep_old, + bool imprint) const +{ + DLIList<TopoDS_Shape*> from_bodies_copy; + DLIList<CubitBoolean> is_volume; + //get the from_bodies underling shapes + CubitStatus stat = get_shape_list(from_bodies, from_bodies_copy, is_volume, keep_old); + if(!stat) + { + for (int i = 0; i < tool_bodies_copy.size(); i++) + { + TopoDS_Shape* shape = tool_bodies_copy.get_and_step(); + delete shape; + } + tool_bodies_copy.clean_out(); + return CUBIT_FAILURE; + } + + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + int fraction_remaining = 100; + + // subtract the tool body from each body in the list + + CubitMessage* cmi = CubitMessage::instance(); + TopoDS_Shape* from_shape = from_bodies_copy.get(); + DLIList<TopologyBridge*> tbs; + for (int i = 0; i < from_bodies_copy.size(); i++) + { + BodySM* from_body = from_bodies.get(); + CubitBox box1 = CAST_TO(from_body, OCCBody)->get_bounding_box(); + int count = 0; //count for not preforming cut + for(int j = 0; j < tool_bodies_copy.size(); j ++) + { + if (cmi->Interrupt()) + { + PRINT_ERROR("Subtraction interrupted. Aborting...\n"); + while (tool_boxes->size()) + delete tool_boxes->pop(); + delete tool_boxes; + while (tool_bodies_copy.size()) + delete tool_bodies_copy.pop(); + while (from_bodies_copy.size()) + delete from_bodies_copy.pop(); + return CUBIT_FAILURE; + } + CubitBox tool_box = *tool_boxes->get_and_step(); + if(!tool_box.overlap(tol,box1)) + { + count++; + continue; + } + TopoDS_Shape* tool_shape = tool_bodies_copy.get_and_step(); + + //bodies overlap, proceed with the subtract + BRepAlgoAPI_Cut cutter(*from_shape, *tool_shape); + TopoDS_Shape cut_shape = cutter.Shape(); + + //compare to see if the from_shape has gotten cut. + CubitBoolean has_changed; + check_operation(cut_shape, from_shape, is_volume[i], has_changed, &cutter, keep_old); + + CubitStatus stat; + if(!has_changed && !from_shape->IsNull()) + { + stat = CUBIT_FAILURE; + //Add imprint code here + if(imprint) + stat = imprint_toposhapes(from_shape, tool_shape); + if(!stat) + { + PRINT_ERROR("Can't do imprint operation on the body. \n"); + count++; + } + continue; + } + } + + //ok, we're done with all cuts, construct new Body' + if (count < tool_bodies_copy.size() ) + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*from_shape); + else + { + PRINT_INFO("The %d body did not change because cutting tools are not interscting with it.\n", i+1); + from_bodies.change_to(NULL); + } + from_bodies.step(); + from_shape = from_bodies_copy.step_and_get(); + + // done with this j iteration; write out count, if necessary + if (from_bodies.size() * tool_bodies_copy.size() > 1) + { + int frac_done = (100 * (i+1)) / (from_bodies.size()); + if ((100 - frac_done) < fraction_remaining) + { + fraction_remaining = 100 - frac_done; + PRINT_INFO("%d%% remaining.\n ", fraction_remaining+1); + } + } + } + + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + new_bodies.append(bodysm); + } + + //ok, we're done wih all cuts, delete unnecessaries. + if(keep_old) + { + int size = from_bodies_copy.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Shape* shape = from_bodies_copy.pop(); + shape->Nullify(); + delete shape; + } + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : imprint_toposhapes +// Member Type: PROTECTED +// Description: imprint boolean operation on OCC-based bodies. +// from_shape must be TopoDS_Face or above, tool_shape can be +// TopoDS_Edge or above. +// on_faces works only when tool_shape is an Edge, indicates that +// those edges only imprint on the on_faces. +// Author : Jane HU +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint_toposhapes(TopoDS_Shape*& from_shape, + TopoDS_Shape* tool_shape, + DLIList<TopoDS_Face*>*on_faces)const +{ + int count = 0; //number of imprinting + + //indicate if there's more faces to be imprinted + CubitBoolean more_face = CUBIT_TRUE; + DLIList<TopoDS_Face*> list_for_delete; + + //list of face on from_shape that has been imprinted + DLIList<TopoDS_Face*> from_faces; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + while( more_face) + { + TopoDS_Face from_face,tool_face; + TopoDS_Edge* common_edge = NULL; + DLIList<TopoDS_Shape*> tool_faces_edges; + TopTools_ListOfShape list_of_edges; + BRepFeat_SplitShape splitor(*from_shape); + CubitBoolean qualified = CUBIT_TRUE; + if (tool_shape->TShape()->ShapeType() == TopAbs_EDGE) + { + if(count == 1) + break; + + DLIList<TopoDS_Face*> faces; + //need to delete TopoDS_Face* in faces + common_edge = find_imprinting_edge(*from_shape, TopoDS::Edge(*tool_shape),faces); + if (common_edge) + { + if (on_faces) + qualified = CUBIT_FALSE; + for(int j = 0; j < faces.size(); j++) + { + from_face = *faces.get(); + for (int i = 0; on_faces && i < on_faces->size(); i++) + { + if (from_face.IsSame(*(on_faces->get_and_step()))) + { + qualified = CUBIT_TRUE; + break; + } + } + faces.get()->Nullify(); + delete faces.get(); + faces.step(); + } + if (qualified && (from_faces.size() == 0 || (from_faces.size() && !from_face.IsSame(*from_faces.get()))) ) + list_of_edges.Append(*common_edge); + else + from_face.Nullify(); + common_edge->Nullify(); + delete common_edge; + } + } + else + { + TopOpeBRep_ShapeIntersector intersector; + intersector.InitIntersection(*from_shape, *tool_shape); + + //find the intersecting edges and faces. + int max_edge = 0; + for(; intersector.MoreIntersection(); intersector.NextIntersection()) + { + TopoDS_Shape face1; + face1 = intersector.ChangeFacesIntersector().Face(1); + CubitBoolean has_imprinted = CUBIT_FALSE; + for (int j = 0; j < from_faces.size(); j++) + { + TopoDS_Face* topo_face = from_faces.get_and_step(); + if(face1.IsSame(*topo_face)) + { + has_imprinted = CUBIT_TRUE; + break; + } + } + + if (has_imprinted) + continue; + + TopoDS_Shape edge_face; + + edge_face = intersector.ChangeFacesIntersector().Face(2); + BRepAlgoAPI_Section section(face1, edge_face); + + //intersection edges between face1 and edge_face + TopTools_ListOfShape temp_list_of_edges; + temp_list_of_edges.Assign(section.SectionEdges()); + int num_edges = temp_list_of_edges.Extent(); + + CubitBoolean is_same = face1.IsSame(from_face); + CubitBoolean is_same_tool = CUBIT_FALSE; + for (int j = 0; j < tool_faces_edges.size(); j++) + { + TopoDS_Shape* topo_face_edge = tool_faces_edges.get_and_step(); + if(edge_face.IsSame(*topo_face_edge)) + { + is_same_tool = CUBIT_TRUE; + break; + } + } + if (max_edge < num_edges ) + { + list_of_edges.Assign(temp_list_of_edges); + max_edge = num_edges ; + from_face = TopoDS::Face(face1); + TopoDS_Shape* topo_shape = new TopoDS_Shape(edge_face); + DLIList<TopoDS_Shape*> shape_list; + for(int iii = 0; iii < tool_faces_edges.size(); iii++) + { + int size = shape_list.size(); + shape_list.append_unique(tool_faces_edges.get_and_step()); + if (size < shape_list.size()) + { + shape_list.last(); + shape_list.get()->Nullify(); + delete shape_list.get(); + } + } + tool_faces_edges.clean_out(); + for(int i = 0 ; i < num_edges; i++) + //later has to use it num_edges times + tool_faces_edges.append(topo_shape); + } + else if(num_edges == max_edge && is_same && !is_same_tool) + //multi tool faces cut the same face + { + TopTools_ListIteratorOfListOfShape Itor, temp_Itor; + temp_Itor.Initialize(temp_list_of_edges); + for(; temp_Itor.More(); temp_Itor.Next()) + { + TopoDS_Edge temp_edge = TopoDS::Edge(temp_Itor.Value()); + Itor.Initialize(list_of_edges); + CubitBoolean same_edge = CUBIT_FALSE; + + GProp_GProps myProps1; + BRepGProp::LinearProperties(temp_edge, myProps1); + gp_Pnt center1 = myProps1.CentreOfMass(); + for(; Itor.More(); Itor.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(Itor.Value()); + GProp_GProps myProps2; + BRepGProp::LinearProperties(edge, myProps2); + gp_Pnt center2 = myProps2.CentreOfMass(); + if(center1.IsEqual(center2, tol)) + { + same_edge = CUBIT_TRUE; + break; + } + } + if(!same_edge) + { + list_of_edges.Append(temp_edge); + TopoDS_Shape* topo_shape = new TopoDS_Shape(edge_face); + tool_faces_edges.append(topo_shape); + } + } + } + } + } + if (from_face.IsNull()) + { + more_face = CUBIT_FALSE; + DLIList<TopoDS_Shape*> shape_list; + for(int iii = 0; iii < tool_faces_edges.size(); iii++) + { + int size = shape_list.size(); + shape_list.append_unique(tool_faces_edges.get_and_step()); + if (size < shape_list.size()) + { + shape_list.last(); + shape_list.get()->Nullify(); + delete shape_list.get(); + } + } + tool_faces_edges.clean_out(); + + for (int iii=0; iii < from_faces.size(); iii++) + { + TopoDS_Face* topo_face = from_faces.get_and_step(); + topo_face->Nullify(); + delete topo_face; + } + + for (int iii=0; iii < list_for_delete.size(); iii++) + { + TopoDS_Face* topo_face = list_for_delete.get_and_step(); + topo_face->Nullify(); + delete topo_face; + } + continue; + } + + TopTools_ListIteratorOfListOfShape Itor; + + //list_of_edges is the intersection edges on tool_faces_edges + Itor.Initialize(list_of_edges); + int total_edges = list_of_edges.Extent(); + DLIList<Curve*> curve_list; + CubitBoolean topo_changed = CUBIT_FALSE; + tool_faces_edges.reset(); + + //check to see if the intersection edge is: + //1. on from_face: if not, skip it + //2. overlap with from_edges : if not, add the edge for splitting face + //3. if overlap, is it the same edge:if not add it for splitting edge + // if yes, skip it too + + Surface* face = NULL; + if (OCCQueryEngine::instance()->OCCMap->IsBound(from_face)) + { + int i = OCCQueryEngine::instance()->OCCMap->Find(from_face); + face = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(i))->second; + } + else + face = OCCQueryEngine::instance()->populate_topology_bridge(from_face); + OCCSurface* occ_face = CAST_TO(face, OCCSurface); + + DLIList<Curve*> common_curves; + for(; Itor.More(); Itor.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(Itor.Value()); + //copy the edge for imprinting. + BRepBuilderAPI_Copy api_copy(edge); + TopoDS_Shape newShape = api_copy.ModifiedShape(edge); + edge = TopoDS::Edge(newShape); + Curve* curve = NULL; + curve = OCCQueryEngine::instance()->populate_topology_bridge(edge); + if(curve) + common_curves.append(curve); + } + + DLIList<DLIList<TopoDS_Edge*>*> temp_edge_lists; + list_of_edges.Clear(); + if (common_curves.size() >= 1) + { + sort_curves(common_curves, temp_edge_lists); + DLIList<TopoDS_Edge*>* edge_list; + int size = temp_edge_lists.size(); + for(int i = 0; i < size; i++) + { + edge_list = temp_edge_lists.pop(); + //make sure the copied edges are sharing vertices. + BRepBuilderAPI_MakeWire myWire; + edge_list->reset(); + for(int i = 0; i < edge_list->size(); i++) + { + TopoDS_Edge e = *(edge_list->get_and_step()); + myWire.Add(e); + } + TopoDS_Wire wire = myWire.Wire(); + BRepTools_WireExplorer Ex(wire); + for(; Ex.More(); Ex.Next()) + list_of_edges.Append(Ex.Current()); + } + } + for(Itor.Initialize(list_of_edges); Itor.More(); Itor.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(Itor.Value()); + //check to see if the intersection edge is on from_face + TopExp_Explorer Ex; + CubitBoolean added = CUBIT_FALSE; + CubitBoolean skipped = CUBIT_FALSE; + GProp_GProps myProps1; + BRepGProp::LinearProperties(edge, myProps1); + double d1 = myProps1.Mass(); + gp_Pnt pt = myProps1.CentreOfMass(); + CubitVector p(pt.X(), pt.Y(), pt.Z()); + + CubitVector point_on_surf; + occ_face->closest_point_trimmed(p, point_on_surf); + if(p.distance_between(point_on_surf) > tol) //edge not on from_face + { + skipped = CUBIT_TRUE; + total_edges--; + } + + else + { + for (Ex.Init(from_face, TopAbs_EDGE); Ex.More(); Ex.Next()) + { + //check if the edge is on from_face edges, add such edge on existing + //edge to split it. + TopoDS_Edge from_edge = TopoDS::Edge(Ex.Current()); + + GProp_GProps myProps2; + BRepGProp::LinearProperties(from_edge, myProps2); + double d2 = myProps2.Mass(); + Curve* curve = NULL; + if (OCCQueryEngine::instance()->OCCMap->IsBound(from_edge)) + { + int i = OCCQueryEngine::instance()->OCCMap->Find(from_edge); + curve = (OCCCurve*)(OCCQueryEngine::instance()->OccToCGM->find(i))->second; + } + else + curve = OCCQueryEngine::instance()->populate_topology_bridge(from_edge); + OCCCurve* occ_curve = CAST_TO(curve, OCCCurve); + CubitPointContainment pc = occ_curve->point_containment(p); + + if(pc == CUBIT_PNT_ON) //overlap + { + //check if they are the same edge, so don't need to be split + //the overlapped edges are considered the same if they have the + //same length + if((d2 - d1) > tol) + { + added = CUBIT_TRUE; + splitor.Add(edge, from_edge); + } + else + skipped = CUBIT_TRUE; + total_edges--; + break; + } + } + } + if(added) + { + topo_changed = CUBIT_TRUE; + continue; + } + if (!skipped) + { + //check if edge's inside from_face by checking bounding boxes + BRepAdaptor_Curve acurve(edge); + BRepAdaptor_Surface asurface( from_face); + Bnd_Box aBox_edge, aBox_face; + BndLib_Add3dCurve::Add(acurve, Precision::Approximation(), aBox_edge); + BndLib_AddSurface::Add(asurface, Precision::Approximation(), aBox_face); + double min[3], max[3]; + aBox_edge.Get( min[0], min[1], min[2], max[0], max[1], max[2]); + CubitBox aBox_e(min, max); + aBox_face.Get( min[0], min[1], min[2], max[0], max[1], max[2]); + CubitBox aBox_f(min, max); + if (aBox_e <= aBox_f) + { + Curve* curve = OCCQueryEngine::instance()->populate_topology_bridge(edge); + curve_list.append(curve); + } + } + } + + DLIList<DLIList<TopoDS_Edge*>*> edge_lists; + if (total_edges >= 1) + { + CubitStatus stat = sort_curves(curve_list, edge_lists); + DLIList<TopoDS_Edge*>* edge_list; + int size = edge_lists.size(); + for (int iii = 0; iii < size; iii++) + { + edge_list = edge_lists.pop(); + + //check if the edges make a split of the surface, error out if it's + //just a scar on the surface + int count_intersection = 0; + if (stat == CUBIT_FAILURE) //Open wire + { + count_intersection = check_intersection(edge_list, from_face); + + if (count_intersection < 2) + PRINT_WARNING("Cant make a scar on existing face without splitting it. \n"); + } + if (stat || count_intersection == 2) + { + BRepBuilderAPI_MakeWire myWire; + edge_list->reset(); + for(int i = 0; i < edge_list->size(); i++) + { + TopoDS_Edge e = *(edge_list->get_and_step()); + myWire.Add(e); + } + splitor.Add(myWire.Wire(),from_face); + topo_changed = CUBIT_TRUE; + break; + } + for(int iii = 0; iii < edge_list->size(); iii++) + edge_list->pop(); + delete edge_list; + } + } + if(topo_changed) + { + splitor.Build(); + topo_changed = CUBIT_FALSE; + if(splitor.IsDone()) + { + //take care of on_faces list first:after operation, the on_faces + // will have at least one face changed, update the pointer. + if (on_faces) + { + for(int k = 0; k < on_faces->size(); k++) + { + TopoDS_Face* compare_face = on_faces->get_and_step(); + if(from_face.IsSame(*compare_face)) + { + on_faces->remove(compare_face); + TopTools_ListOfShape shapes; + shapes.Assign(splitor.Modified(from_face)); + while(shapes.Extent() > 0) + { + TopoDS_Face* face = + new TopoDS_Face(TopoDS::Face(shapes.First())); + shapes.RemoveFirst(); + on_faces->append(face); + list_for_delete.append(face); + } + } + } + } + + TopoDS_Shape new_from_shape = splitor.Shape(); + if(from_shape->TShape()->ShapeType() == TopAbs_COMPSOLID) + { + TopoDS_CompSolid old_csolid = TopoDS::CompSolid(*from_shape); + OCCBody::update_OCC_entity(old_csolid, new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + + else if(from_shape->TShape()->ShapeType() == TopAbs_SOLID) + { + TopoDS_Solid old_solid = TopoDS::Solid(*from_shape); + OCCLump::update_OCC_entity(old_solid, new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + else if(from_shape->TShape()->ShapeType() == TopAbs_SHELL) + { + TopoDS_Shell old_shell = TopoDS::Shell(*from_shape); + OCCShell::update_OCC_entity(old_shell,new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + else if(from_shape->TShape()->ShapeType() == TopAbs_FACE) + { + TopoDS_Face old_face = TopoDS::Face(*from_shape); + OCCSurface::update_OCC_entity(old_face,new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + + TopTools_ListOfShape shapes; + for(int i = 0; i < from_faces.size(); i++) + { + TopoDS_Face* topo_face = from_faces.get(); + shapes.Assign(splitor.Modified(*topo_face)); + topo_face = new TopoDS_Face(TopoDS::Face(shapes.First())); + from_faces.get()->Nullify(); + delete from_faces.get(); + from_faces.change_to(topo_face); + from_faces.step(); + } + count++; + } + } + else + { + TopoDS_Face* topo_face = new TopoDS_Face(from_face); + from_faces.append(topo_face); + } + } + + + TopExp_Explorer Ex; + int num_face = 0; + for (Ex.Init(*from_shape, TopAbs_FACE); Ex.More(); Ex.Next()) + { + TopoDS_Face face = TopoDS::Face(Ex.Current()); + num_face++; + } + +#ifdef DEBUG + PRINT_INFO("Total %d cuts performed, with from_shape having %d faces.\n", count, num_face); +#endif + + if (count > 0) + return CUBIT_SUCCESS; + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : find_imprinting_edge +// Member Type: PROTECTED +// Description: imprint boolean operation on OCC-based bodies. +// from_shape must be TopoDS_Face or above, tool_shape must be +// TopoDS_Edge. +// Author : Jane HU +// Date : 05/08 +//=============================================================================== +TopoDS_Edge* OCCModifyEngine::find_imprinting_edge(TopoDS_Shape& from_shape, + TopoDS_Edge& tool_shape, + DLIList<TopoDS_Face*>& from_faces)const +{ + TopoDS_Edge* edge = NULL; + //list of face on from_shape that has been imprinted + from_faces.clean_out(); + TopExp_Explorer Ex; + for (Ex.Init(from_shape, TopAbs_FACE); Ex.More(); Ex.Next()) + { + TopoDS_Face face = TopoDS::Face(Ex.Current()); + BRepAlgoAPI_Common intersector(face, tool_shape); + TopTools_ListOfShape shapes; + shapes.Assign(intersector.Modified(tool_shape)); + if (shapes.IsEmpty()) + continue; + if ( shapes.Extent() > 1) + { + PRINT_ERROR("Edge has multiple intersection with the shape, make it simpler. \n"); + continue; + } + if (shapes.First().TShape()->ShapeType() != TopAbs_EDGE) + continue; + if(edge == NULL) + { + TopoDS_Edge common_edge = TopoDS::Edge(shapes.First()); + BRepBuilderAPI_Copy api_copy(common_edge); + TopoDS_Shape newShape = api_copy.ModifiedShape(common_edge); + edge = new TopoDS_Edge(TopoDS::Edge(newShape)); + } + from_faces.append(new TopoDS_Face(face)); + } + return edge; +} + +int OCCModifyEngine::check_intersection(DLIList<TopoDS_Edge*>* edge_list, + TopoDS_Face from_face)const +{ + int count_intersection = 0; + //Consider if edge_list has only one edge, and it intersects the from_face + //at two different places. + CubitBoolean double_check = CUBIT_FALSE; + if (edge_list->size() == 1) + double_check = CUBIT_TRUE; + + gp_Pnt intsec_pnt[2]; + for(int j = 0; j < edge_list->size(); j++) + { + TopoDS_Edge* edge = edge_list->get_and_step(); + BRepAdaptor_Curve acurve(*edge); + double lower_bound = acurve.FirstParameter(); + double upper_bound = acurve.LastParameter(); + TopExp_Explorer Ex; + gp_Pnt newP[2]; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + for (Ex.Init(from_face, TopAbs_EDGE); Ex.More(); Ex.Next()) + { + TopoDS_Edge from_edge = TopoDS::Edge(Ex.Current()); + BRepAdaptor_Curve acurve2(from_edge); + double lower_bound2 = acurve2.FirstParameter(); + double upper_bound2 = acurve2.LastParameter(); + BRepExtrema_DistShapeShape distShapeShape(*edge, from_edge); + CubitBoolean qualified[2] = {CUBIT_FALSE, CUBIT_FALSE}; + if (distShapeShape.IsDone() && distShapeShape.Value() < tol) + { + newP[0] = distShapeShape.PointOnShape1(1); + if (double_check && distShapeShape.NbSolution() == 2) + newP[1] = distShapeShape.PointOnShape1(2); + double newVal[2]; + for(int j =0; j < distShapeShape.NbSolution(); j++) + { + Extrema_ExtPC ext(newP[j], acurve, Precision::Approximation()); + if (ext.IsDone() && (ext.NbExt() > 0)) { + for ( int i = 1 ; i <= ext.NbExt() ; i++ ) { + if ( ext.IsMin(i) ) { + newVal[j] = ext.Point(i).Parameter(); + if ((newVal[j]-lower_bound) >= -tol && + (upper_bound - newVal[j]) >= -tol) + { + qualified[j] = CUBIT_TRUE; + break; + } + } + } + } + } + for(int j = 0; j < distShapeShape.NbSolution(); j++) + { + if (qualified[j]) + { + qualified[j] = CUBIT_FALSE; + Extrema_ExtPC ext(newP[j], acurve2, Precision::Approximation()); + double newVal; + if (ext.IsDone() && (ext.NbExt() > 0)) { + for ( int i = 1 ; i <= ext.NbExt() ; i++ ) { + if ( ext.IsMin(i) ) { + newVal = ext.Point(i).Parameter(); + if ((newVal-lower_bound2) >= -tol && + (upper_bound2 - newVal) >= -tol) + { + qualified[j] = CUBIT_TRUE; + break; + } + } + } + } + } + } + for(int k = 0; k < distShapeShape.NbSolution(); k++) + { + if (qualified[k]) + count_intersection++; + intsec_pnt[count_intersection-1] = newP[k]; + if (count_intersection == 2) + { + //make sure the two intersect point are not the same one + if (intsec_pnt[0].IsEqual(intsec_pnt[1], tol)) + count_intersection--; + } + } + } + if (count_intersection == 2) + break; + } //for loop + } + return count_intersection; +} +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: imprint boolean operation on OCC-based bodies +// Author : Jane Hu +// Date : 04/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint(BodySM* BodyPtr1, BodySM* BodyPtr2, + BodySM*& newBody1, BodySM*& newBody2, + bool keep_old) const +{ + newBody1 = NULL; + newBody2 = NULL; + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_volume; + + DLIList<BodySM*> bodysm_list; + bodysm_list.append(BodyPtr1); + bodysm_list.append(BodyPtr2); + + CubitStatus stat = get_shape_list(bodysm_list,shape_list,is_volume,keep_old); + + if(!stat) + return stat; + + TopoDS_Shape* shape1 = shape_list.get(); + TopoDS_Shape* shape2 = shape_list.step_and_get(); + DLIList<TopologyBridge*> tbs; + stat = imprint_toposhapes(shape1, shape2); + if(stat) + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape1); + newBody1 = CAST_TO(tbs.get(),BodySM); + } + + else if(!stat && keep_old) + { + delete shape1; + PRINT_INFO("There's no imprint on the first body.\n"); + newBody1 = BodyPtr1; + } + + tbs.clean_out(); + stat = imprint_toposhapes(shape2, shape1); + if(stat) + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape2); + newBody2 = CAST_TO(tbs.get(),BodySM); + } + + else if(!stat && keep_old) + { + delete shape2; + PRINT_INFO("There's no imprint on the second body.\n"); + newBody2 = BodyPtr2; + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : get_the_shape_list +// Member Type: PRIVATE +// Description: get the TopoDS_Shape list for imprinting use. +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus OCCModifyEngine::get_shape_list(DLIList<BodySM*>& BodySM_list, + DLIList<TopoDS_Shape*>& shape_list, + DLIList<CubitBoolean>& is_volume, + bool keep_old, + DLIList<CubitBox*>* b_boxes) const +{ + OCCBody* occ_body = NULL; + shape_list.clean_out(); + is_volume.clean_out(); + CubitStatus stat = CUBIT_SUCCESS; + for(int i = 0; i <BodySM_list.size(); i++) + { + occ_body = CAST_TO(BodySM_list.get_and_step(), OCCBody); + if (!occ_body) + continue; + + OCCSurface* surface = occ_body->my_sheet_surface(); + OCCShell* shell = occ_body->shell(); + is_volume.append( CUBIT_TRUE); + + if(b_boxes) + { + CubitBox *tool_box = new CubitBox(occ_body->get_bounding_box()); + b_boxes->append(tool_box); + } + + if(surface) + { + TopoDS_Face* topo_face = surface->get_TopoDS_Face(); + if(!topo_face) + { + stat = CUBIT_FAILURE; + break; + } + if(keep_old) + { + BRepBuilderAPI_Copy api_copy(*topo_face); + TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_face); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + shape_list.append(Shape1); + } + else + shape_list.append(topo_face); + is_volume.change_to( CUBIT_FALSE); + } + else if(shell) + { + TopoDS_Shell* topo_shell = shell->get_TopoDS_Shell(); + if(!topo_shell) + { + stat = CUBIT_FAILURE; + break; + } + if(keep_old) + { + BRepBuilderAPI_Copy api_copy(*topo_shell); + TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_shell); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + shape_list.append(Shape1); + } + else + shape_list.append(topo_shell); + is_volume.change_to( CUBIT_FALSE); + } + + else + { + DLIList<Lump*> lumps = occ_body->lumps(); + if (lumps.size() > 1) + { + PRINT_ERROR("Can't do boolean operation on CompSolid types. \n"); + stat = CUBIT_FAILURE; + break; + } + + TopoDS_Solid* solid = CAST_TO(lumps.get(), OCCLump)->get_TopoDS_Solid(); + if(!solid) + { + stat = CUBIT_FAILURE; + break; + } + if(keep_old) + { + BRepBuilderAPI_Copy api_copy(*solid); + TopoDS_Shape newShape = api_copy.ModifiedShape(*solid); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + shape_list.append(Shape1); + } + else + shape_list.append(solid); + } + } + if(!stat) + { + for (int i = 0; keep_old && i < shape_list.size(); i++) + { + TopoDS_Shape* shape = shape_list.get_and_step(); + delete shape; + } + shape_list.clean_out(); + return CUBIT_FAILURE; + } + return CUBIT_SUCCESS; +} +//=============================================================================== +// Function : imprint multiple bodies at once +// Member Type: PUBLIC +// Description: imprint boolean operation on OCC-based bodies +// Author : Jane HU +// Date : 04/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint(DLIList<BodySM*> &from_body_list , + DLIList<BodySM*> &new_from_body_list, + bool keep_old, + DLIList<TopologyBridge*>* new_tbs, + DLIList<TopologyBridge*>* att_tbs) const +{ + CubitStatus success = CUBIT_SUCCESS; + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_vo; + CubitStatus stat = get_shape_list(from_body_list, shape_list, is_vo,keep_old); + + if(!stat) + return stat; + + int size = shape_list.size(); + // total number of imprints to be done + int total_imprints = (size * (size -1))/2; + + if( size > 2 ) + { + char message[128]; + sprintf(message, "Imprinting %d OCC Bodies", from_body_list.size() ); + AppUtil::instance()->progress_tool()->start(0, total_imprints, message); + } + + for(int i = 0; i < size; i++) + { + TopoDS_Shape* shape1 = shape_list[i]; + CubitBoolean modified = CUBIT_FALSE; + for(int j = i+1; j < size+i; j ++) + { + if (CubitMessage::instance()->Interrupt()) + { + success = CUBIT_FAILURE; + break; + } + + TopoDS_Shape* shape2 = shape_list[j%size]; + DLIList<TopologyBridge*> tbs; + CubitStatus stat = imprint_toposhapes(shape1, shape2); + if(stat) + modified = CUBIT_TRUE; + } + if(modified) + { + DLIList<TopologyBridge*> tbs; + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape1); + new_from_body_list.append(CAST_TO(tbs.get(),BodySM)); + } + shape_list.reset(); + if( size > 2 ) + AppUtil::instance()->progress_tool()->step(); + } + + if( size > 2 ) + AppUtil::instance()->progress_tool()->end(); + + if( CubitMessage::instance()->Interrupt() ) + PRINT_INFO("Imprint aborted.\n"); + + return success; +} + +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: imprint curves onto body_list +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<BodySM*> &body_list, + DLIList<Curve*> &ref_edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old, + bool show_messages) const +{ + CubitStatus success = CUBIT_SUCCESS; + DLIList<TopoDS_Shape*> shape_list, tool_shapes; + DLIList<CubitBoolean> is_vo; + CubitStatus stat = get_shape_list(body_list, shape_list, is_vo, keep_old); + if (!stat) + return stat; + + int size = ref_edge_list.size(); + // total number of imprints to be done + + if( size > 2 && show_messages) + { + char message[128]; + sprintf(message, "Imprinting %d OCC Bodies", body_list.size() ); + AppUtil::instance()->progress_tool()->start(0, size, message); + } + for (int i = 0; i < ref_edge_list.size(); i++) + { + OCCCurve* curve = CAST_TO(ref_edge_list.get_and_step(), OCCCurve) ; + if (!curve) + continue; + + TopoDS_Edge* edge = curve->get_TopoDS_Edge(); + if (edge->IsNull()) + continue; + + if (CubitMessage::instance()->Interrupt()) + { + success = CUBIT_FAILURE; + break; + } + + for(int j = 0; j < shape_list.size(); j ++) + { + TopoDS_Shape* shape = shape_list.get(); + + stat = imprint_toposhapes(shape, (TopoDS_Shape*)edge); + if (stat) + shape_list.change_to(shape); + shape_list.step(); + body_list.step(); + } + + if( size > 2 ) + AppUtil::instance()->progress_tool()->step(); + } + + for(int j = 0; j < shape_list.size(); j ++) + { + DLIList<TopologyBridge*> tbs; + TopoDS_Shape* shape = shape_list.get_and_step(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape); + new_body_list.append(CAST_TO(tbs.get(),BodySM)); + } + + if( size > 2 ) + AppUtil::instance()->progress_tool()->end(); + + if( CubitMessage::instance()->Interrupt() ) + PRINT_INFO("Imprint aborted.\n"); + return success; +} + +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: to be consistante with Acis imprint. +// The surfaces must be part of a body, but the curves +// just have to be valid OCC edge. +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old ) const +{ + DLIList<TopoDS_Face*> face_list; + DLIList<TopoDS_Shape*> shape_list; + + face_edge_imprint(ref_face_list, edge_list, face_list, shape_list, keep_old); + + for(int j = 0; j < shape_list.size(); j ++) + { + DLIList<TopologyBridge*> tbs; + TopoDS_Shape* shape = shape_list.get_and_step(); + if (shape->TShape()->ShapeType() == TopAbs_COMPSOLID) + { + if(!OCCQueryEngine::instance()->OCCMap->IsBound(*shape)) + { + TopExp_Explorer Ex; + for (Ex.Init(*shape, TopAbs_SOLID);Ex.More(); Ex.Next()) + { + TopoDS_Shape subshape = Ex.Current(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(subshape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } + } + else + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } + + if (keep_old) + { + for(int i = 0; i < face_list.size(); i++) + { + TopoDS_Face* face = face_list.get(); + face->Nullify(); + delete face; + } + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : face_edge_imprint +// Member Type: PRIVATE +// Description: to be consistante with Acis imprint. +// The surfaces must be part of a body, but the curves +// just have to be valid OCC edge. +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus +OCCModifyEngine::face_edge_imprint( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &edge_list, + DLIList<TopoDS_Face*>& face_list, + DLIList<TopoDS_Shape*>& shape_list, + bool keep_old ) const +{ + for(int i = 0; i <ref_face_list.size(); i++) + { + OCCSurface* surface = CAST_TO(ref_face_list.get_and_step(), OCCSurface); + if(!surface) + continue; + + TopoDS_Face* topo_face = surface->get_TopoDS_Face(); + face_list.append(topo_face); + + if(surface->my_shell() && !surface->my_body())//shell body + shape_list.append(surface->my_shell()->get_TopoDS_Shell()); + else if(surface->my_body()) //a sheet body + shape_list.append(topo_face); + else + { + //int size = shape_list.size(); + OCCQueryEngine* oqe = OCCQueryEngine::instance(); + DLIList <OCCBody* > *bodies = oqe->BodyList; + TopTools_IndexedDataMapOfShapeListOfShape M; + OCCBody * body = NULL; + for(int j = 0; j < bodies->size(); j++) + { + body = bodies->get_and_step(); + TopExp_Explorer Ex; + TopoDS_Face the_face; + TopoDS_Shape ashape = *(body->get_TopoDS_Shape()); + M.Clear(); + TopExp::MapShapesAndAncestors(ashape, TopAbs_FACE, TopAbs_COMPSOLID, M); + if(!M.Contains(*topo_face)) + continue; + shape_list.append_unique(body->get_TopoDS_Shape()); + } + } + } + + if(keep_old) + { + for(int i = 0; i < shape_list.size(); i++) + { + TopoDS_Shape* shape = shape_list.get(); + BRepBuilderAPI_Copy api_copy(*shape); + TopoDS_Shape newShape = api_copy.ModifiedShape(*shape); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + for(int j = 0; j < face_list.size(); j++) + { + TopoDS_Face* face = face_list.get(); + TopExp_Explorer Ex; + for (Ex.Init(*shape, TopAbs_FACE); Ex.More(); Ex.Next()) + { + if(face->IsSame(Ex.Current())) + { + face = new TopoDS_Face(TopoDS::Face(api_copy.ModifiedShape(*face))); + face_list.change_to(face); + } + } + face_list.step(); + } + shape_list.change_to(Shape1); + shape_list.step(); + } + } + + for (int i = 0; i < edge_list.size(); i++) + { + OCCCurve* curve = CAST_TO(edge_list.get_and_step(), OCCCurve) ; + if (!curve) + continue; + + TopoDS_Edge* edge = curve->get_TopoDS_Edge(); + if (edge->IsNull()) + continue; + + for(int j = 0; j < shape_list.size(); j ++) + { + TopoDS_Shape* shape = shape_list.get_and_step(); + imprint_toposhapes(shape, (TopoDS_Shape*)edge, &face_list); + } + } + return CUBIT_SUCCESS; +} +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: To be consistent with AcisModifyEngine, althought it's hard +// to have a GUI interface for users to input. All surface must +// on the same body. +// Author : Jane HU +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<Surface*>& surface_list, + DLIList<DLIList<Curve*>*>& curve_lists_list, + BodySM*& new_body, + bool keep_old ) const +{ + DLIList<TopoDS_Face*> face_list; + DLIList<TopoDS_Shape*> shape_list; + DLIList<TopoDS_Shape*> shape_list_all; + + assert (surface_list.size() == curve_lists_list.size()); + + for(int j = 0; j < surface_list.size(); j++) + { + Surface* surface = surface_list.get_and_step(); + DLIList<Surface*> ref_face_list; + ref_face_list.append(surface); + DLIList<Curve*> *edge_list = curve_lists_list.get_and_step(); + face_edge_imprint(ref_face_list, *edge_list, face_list, shape_list, keep_old); + + for(int i = 0; i < shape_list.size(); i++) + { + TopoDS_Shape* shape = shape_list.get_and_step(); + shape_list_all.append_unique(shape); + } + shape_list.clean_out(); + + if (keep_old) + { + for(int i = 0; i < face_list.size(); i++) + { + TopoDS_Face* face = face_list.get(); + face->Nullify(); + delete face; + } + } + + face_list.clean_out(); + } + + DLIList<BodySM*> new_body_list; + shape_to_bodySM(shape_list, new_body_list); + + if (new_body_list.size() == 1) + { + new_body = new_body_list.get(); + return CUBIT_SUCCESS; + } + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : shape_to_bodySM +// Member Type: PRIVATE +// Description: After imprint, update shape list to bodySM_list +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +void OCCModifyEngine::shape_to_bodySM( DLIList<TopoDS_Shape*> shape_list, + DLIList<BodySM*>& new_body_list)const +{ + for(int j = 0; j < shape_list.size(); j ++) + { + DLIList<TopologyBridge*> tbs; + TopoDS_Shape* shape = shape_list.get_and_step(); + if (shape->TShape()->ShapeType() == TopAbs_COMPSOLID) + { + if(!OCCQueryEngine::instance()->OCCMap->IsBound(*shape)) + { + TopExp_Explorer Ex; + for (Ex.Init(*shape, TopAbs_SOLID);Ex.More(); Ex.Next()) + { + TopoDS_Shape subshape = Ex.Current(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(subshape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } + } + else + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } +} + +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: Imprints locations to bodies (for splitting curves, there's +// no known ways to put hard points on surfaces in OCC, so I just +// add free_vertex on OCCSurface definition, mesh should look on +// this structure). +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<BodySM*> &body_list, + DLIList<CubitVector*> &vector_list, + DLIList<BodySM*>& new_body_list, + bool keep_old, + DLIList<TopologyBridge*>*, + DLIList<TopologyBridge*>* ) const +{ + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_vo; + CubitStatus stat = get_shape_list(body_list, shape_list, is_vo, keep_old); + if(!stat) + return stat; + + for (int i = 0; i < body_list.size(); i++) + { + OCCBody* body = CAST_TO(body_list.get_and_step(), OCCBody); + TopoDS_Shape* from_shape = shape_list.get_and_step(); + if (!body) + continue; + DLIList<OCCSurface*> surfaces; + DLIList<OCCCurve*> curves; + + body->get_all_surfaces(surfaces); + body->get_all_curves(curves); + + CubitBoolean on_vertex = CUBIT_FALSE; + CubitBoolean on_curve = CUBIT_FALSE; + for (int j = 0; j < vector_list.size(); j ++) + { + CubitVector* v = vector_list[j]; + if(v == NULL) + continue; + for (int k = 0; k < curves.size(); k ++) + { + OCCCurve* curve = curves.get_and_step(); + CubitPointContainment pc = curve->point_containment(*v); + if(pc == CUBIT_PNT_BOUNDARY) + { + on_vertex = CUBIT_TRUE; + break; + } + + else if( pc == CUBIT_PNT_INSIDE) + { + LocOpe_SplitShape splitor(*from_shape); + on_curve = CUBIT_TRUE; + TopoDS_Edge edge = *curve->get_TopoDS_Edge(); + gp_Pnt pt = gp_Pnt(v->x(), v->y(), v->z()); + TopoDS_Vertex vertex = BRepBuilderAPI_MakeVertex(pt); + double param = curve->u_from_position(*v); + splitor.Add(vertex, param, edge); + + //update the curve_list + TopTools_ListOfShape edge_shapes; + edge_shapes.Assign(splitor.DescendantShapes(edge)); + while(edge_shapes.Extent()) + { + TopoDS_Shape edge_shape = edge_shapes.First(); + TopoDS_Edge occ_edge = TopoDS::Edge(edge_shape); + OCCCurve* test_curve; + test_curve = CAST_TO(OCCQueryEngine::instance()->populate_topology_bridge(occ_edge), OCCCurve); + if(test_curve) + curves.append(test_curve); + edge_shapes.RemoveFirst(); + } + curves.remove(curve); + + TopTools_ListOfShape shapes; + shapes.Assign(splitor.DescendantShapes(*from_shape)); + if(from_shape->TShape()->ShapeType() ==TopAbs_COMPSOLID) + OCCBody::update_OCC_entity(*from_shape, shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + else if(shapes.First().TShape()->ShapeType() == TopAbs_SOLID) + OCCLump::update_OCC_entity(TopoDS::Solid(*from_shape), + shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + + else if(shapes.First().TShape()->ShapeType() == TopAbs_SHELL) + OCCShell::update_OCC_entity(TopoDS::Shell(*from_shape), + shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + + else if(shapes.First().TShape()->ShapeType() == TopAbs_FACE) + OCCSurface::update_OCC_entity(TopoDS::Face(*from_shape), + shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(shapes.First()); + break; + } + } + if(on_vertex || on_curve) + continue; + + //check possible on surface + for(int n = 0; n < surfaces.size(); n ++) + { + OCCSurface* surface = surfaces.get_and_step(); + if(!surface->is_position_on(*v)) + continue; + + CubitPointContainment ps = surface->point_containment(*v); + if(ps == CUBIT_PNT_INSIDE) + { + Point* p = make_Point(*v); + if(p) + surface->add_hardpoint(CAST_TO(p, OCCPoint)); + break; + } + } + } + } + + shape_to_bodySM(shape_list, new_body_list); + + return stat; +} + +//=============================================================================== +// Function : imprint_projected_edges +// Member Type: PUBLIC +// Description: Projects a list of Curves on to a list of Surfaces +// and imprint the faces with the new Curves +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus +OCCModifyEngine::imprint_projected_edges( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &ref_edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old_body, + bool keep_free_edges) const +{ + DLIList<Curve*> projected_curves; + CubitStatus + stat = project_edges(ref_face_list, ref_edge_list, projected_curves); + if(!stat) + return stat; + + // imprint Surface with curves + stat = imprint(ref_face_list, projected_curves, new_body_list, keep_old_body ); + + if(keep_free_edges) + return stat; + + PRINT_INFO( "Removing projected curves \n"); + for(int i=0; i< projected_curves.size();i++) + { + // Now delete this Curve and its underlying solid model entities + + Curve* curve = projected_curves.get_and_step(); + stat = OCCQueryEngine::instance()->delete_solid_model_entities( curve ); + if (stat == CUBIT_FAILURE) + { + PRINT_ERROR("In OCCQueryEngine::delete_geometry\n" + " Could not delete OCCCurve.\n" + " The Model database is likely corrupted " + "due to\n this unsuccessful deletion.\n" ); + } + } + return stat; +} +//=============================================================================== +// Function : project_edges +// Member Type: PUBLIC +// Description: Projects a list of Curves on to a list of Surfaces +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::project_edges( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &ref_edge_list, + DLIList<Curve*> &projected_curves, + bool print_error ) const + +{ + CubitVector* v = NULL; + Curve* projected_curve = NULL; + DLIList<Point*> points; + //project curves onto surfaces. + for(int i = 0; i < ref_edge_list.size(); i++) + { + OCCCurve* curve = CAST_TO(ref_edge_list.get_and_step(), OCCCurve); + if(!curve) + continue; + + for (int j = 0; j < ref_face_list.size(); j++) + { + OCCSurface* surface = CAST_TO(ref_face_list.get_and_step(), OCCSurface); + if(!surface) + continue; + if(surface->is_closed_in_U() || surface->is_closed_in_V()) + { + if(print_error) + PRINT_ERROR("This function can't project curves on closed surfaces.\n"); + return CUBIT_FAILURE; + } + + projected_curve = NULL; + projected_curve = curve->project_curve(surface, points, CUBIT_FALSE, v); + if(projected_curve) + projected_curves.append_unique(projected_curve); + } + } + while(points.size() > 0) + delete points.pop(); + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : imprint_projected_edges +// Member Type: PUBLIC +// Description: Projects a list of curves on to a list of surfaces +// and imprint the bodies with the new curves +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus +OCCModifyEngine::imprint_projected_edges(DLIList<Surface*> &ref_face_list, + DLIList<BodySM*> &body_list, + DLIList<Curve*> &ref_edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old, + bool keep_free_edges) const +{ + DLIList<Curve*> projected_curves; + CubitStatus + stat = project_edges(ref_face_list, ref_edge_list, projected_curves); + if(!stat) + return stat; + return CUBIT_FAILURE; + + // imprint bodies with curves + stat = imprint(body_list,projected_curves, new_body_list, keep_old); + + if (keep_free_edges) + return stat; + + PRINT_INFO( "Removing projected curves \n"); + for(int i=0; i< projected_curves.size();i++) + { + // Now delete this Curve + Curve* curve = projected_curves.get_and_step(); + stat = OCCQueryEngine::instance()-> + delete_solid_model_entities( curve ); + if (stat == CUBIT_FAILURE) + { + PRINT_ERROR("In OCCModifyEngine::delete_geometry\n" + " Could not delete Curve.\n" + " The Model database is likely corrupted " + "due to\n this unsuccessful deletion.\n" ); + } + } + return stat; +} + +//=============================================================================== +// Function : intersect +// Member Type: PUBLIC +// Description: intersect boolean operation of body with list of bodies. +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::intersect(BodySM* tool_body_ptr, + DLIList<BodySM*> &from_bodies, + DLIList<BodySM*> &new_bodies, + bool keep_old) const +{ + DLIList<BodySM*> tool_bodies; + DLIList<TopoDS_Shape*> tool_shapes; + DLIList<CubitBoolean> is_tool_volume, is_volume; + + tool_bodies.append(tool_body_ptr); + //get tool_body's underlying shape, copy it, so boolean wouldn't touch it. + CubitStatus stat = + get_shape_list(tool_bodies, tool_shapes, is_tool_volume, CUBIT_TRUE); + if(!stat) + return stat; + + DLIList<TopoDS_Shape*> shape_list; + stat = get_shape_list(from_bodies, shape_list, is_volume, keep_old); + if(!stat) + { + for (int i = 0; i < tool_shapes.size(); i++) + { + TopoDS_Shape* shape = tool_shapes.get_and_step(); + delete shape; + } + tool_shapes.clean_out(); + return CUBIT_FAILURE; + } + + TopoDS_Shape* tool_shape = tool_shapes.get(); + CubitBoolean has_changed; + DLIList<TopologyBridge*> tbs; + for (int i = 0; i < shape_list.size(); i++) + { + TopoDS_Shape* from_shape = shape_list.get_and_step(); + //BodySM* from_body = from_bodies.get_and_step(); + BRepAlgoAPI_Common intersector(*from_shape, *tool_shape); + TopoDS_Shape common_shape = intersector.Shape(); + check_operation(common_shape, from_shape, is_volume[i], has_changed, + &intersector, keep_old); + + if(from_shape->IsNull()) + { + PRINT_INFO("The %d body did not have common part with the tool_body.\n", i+1); + continue; + } + else + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*from_shape); + } + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + new_bodies.append(bodysm); + } + + //ok, we're done wih all cuts, delete unnecessaries. + if(!keep_old) + OCCQueryEngine::instance()->delete_solid_model_entities(tool_body_ptr); + + for(int i = 0; i < tool_shapes.size(); i++) + { + TopoDS_Shape* shape = tool_shapes.get_and_step(); + shape->Nullify(); + delete shape; + } + + if(keep_old) + { + int size = shape_list.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Shape* shape = shape_list.pop(); + shape->Nullify(); + delete shape; + } + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : check_operation +// Member Type: PRIVATE +// Description: check and update the from_shape according to type of the body. +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +void OCCModifyEngine::check_operation(TopoDS_Shape& cut_shape, + TopoDS_Shape*& from_shape, //output + CubitBoolean is_volume, + CubitBoolean& has_changed, //output + BRepAlgoAPI_BooleanOperation* op, + CubitBoolean keep_old) const +{ + //compare to see if the from_shape has gotten cut. + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + if(is_volume) + { + GProp_GProps myProps; + BRepGProp::VolumeProperties(*from_shape, myProps); + double orig_mass = myProps.Mass(); + BRepGProp::VolumeProperties(cut_shape, myProps); + double after_mass = myProps.Mass(); + if(fabs(-after_mass + orig_mass) <= tol) + { + has_changed= CUBIT_FALSE; //common is itself + return; + } + + //got cut. Update the entities + if(after_mass < tol) //no common section + cut_shape.Nullify(); + has_changed = CUBIT_TRUE; + TopExp_Explorer Ex; + Ex.Init(*from_shape, TopAbs_SOLID); + TopoDS_Solid old_solid = TopoDS::Solid(Ex.Current()); + OCCLump::update_OCC_entity(old_solid , cut_shape, op); + } + else + { + GProp_GProps myProps; + BRepGProp::SurfaceProperties(*from_shape, myProps); + double orig_mass = myProps.Mass(); + BRepGProp::SurfaceProperties(cut_shape, myProps); + double after_mass = myProps.Mass(); + if(fabs(-after_mass + orig_mass) <= tol) + { + has_changed= CUBIT_FALSE; //common is itself, or not cut + return; + } + //got cut. Update the entities + if(after_mass < tol)//no common section + cut_shape.Nullify(); + has_changed = CUBIT_TRUE; + if(from_shape->TShape()->ShapeType() == TopAbs_SHELL) + { + TopoDS_Shell old_shell = TopoDS::Shell(*from_shape); + OCCShell::update_OCC_entity(old_shell,cut_shape, op); + } + else + { + TopoDS_Face old_face = TopoDS::Face(*from_shape); + OCCSurface::update_OCC_entity(old_face,cut_shape, op); + } + } + if(keep_old) + delete from_shape; + from_shape = new TopoDS_Shape(cut_shape); +} + +//=============================================================================== +// Function : chop +// Member Type: PUBLIC +// Description: chop boolean operation between OCC-based bodies +// bodies has a size() = 2, a blank body and a tool body. +// chops the blank with the tool, returing the body formed +// by subtracting the tool from the blank, and the body formed +// by intersecting the tool with the blank, simultaneously. +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::chop(DLIList<BodySM*>& bodies, + DLIList<BodySM*> &intersectBodies, + DLIList<BodySM*> &outsideBodies, + BodySM*& leftoversBody, + bool keep_old , + bool nonreg) const +{ + //according to Acis chop function, leftoverBody = 0; + leftoversBody = 0; + + //there's no effect of nonreg. keep_old mean if to keep the tool_body + if(bodies.size() != 2) + { + PRINT_WARNING("Chop operation works only on two bodies. Nothing modified\n"); + return CUBIT_FAILURE; + } + + //outsideBodies keeps the surface, curve ids if keep_old is false. + BodySM* blank_body = bodies.get(); + + //copy blank_body for intersect operation, because it will get changed. + DLIList<BodySM*> tool_bodies, from_bodies; + from_bodies.append(blank_body); + BodySM* tool_body = bodies.step_and_get(); + tool_bodies.append(tool_body); + + CubitStatus stat = intersect(tool_body, from_bodies, + intersectBodies, CUBIT_TRUE); + + if(!stat) + return CUBIT_FAILURE; + + stat = subtract(tool_bodies, from_bodies, outsideBodies, + CUBIT_FALSE, keep_old); + + return stat; +} + +//=============================================================================== +// Function : unite +// Member Type: PUBLIC +// Description: unite boolean operation between OCC-based bodies +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::unite(DLIList<BodySM*> &bodies, + DLIList<BodySM*> &newBodies, + bool keep_old) const +{ + if(bodies.size() < 2) + { + newBodies = bodies; + return CUBIT_SUCCESS; + } + //all bodies must have only one lump in order for boolean operation to work. + DLIList<Lump*> lumps; + for (int i = 0; i < bodies.size(); i++) + { + lumps = CAST_TO(bodies.get_and_step(), OCCBody)->lumps(); + if (lumps.size() > 1) + { + PRINT_WARNING("All bodies must have only one lump for boolean operations to work.\n"); + return CUBIT_FAILURE; + } + } + + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_volume; + CubitStatus stat = + get_shape_list(bodies, shape_list, is_volume, keep_old); + + if(!stat) + return stat; + + //find a non-sheet body to be the first shape + TopoDS_Shape* first_shape; + CubitBoolean first_is_volume; + if((first_is_volume = is_volume.move_to(CUBIT_TRUE))) + { + int index = is_volume.get_index(); + first_shape = shape_list[index]; + shape_list.remove(first_shape); + is_volume.step(index); + is_volume.remove(); + bodies.step(index); + bodies.remove(); + } + + else + { + first_shape = shape_list.pop(); + bodies.pop(); + } + + int size = shape_list.size(); + for(int i = 0; i < size; i++) + { + TopoDS_Shape* second_shape = shape_list.get_and_step(); + + BRepAlgoAPI_Fuse fuser(*first_shape, *second_shape); + TopoDS_Shape new_shape = fuser.Shape(); + + CubitBoolean has_changed; + check_operation(new_shape, first_shape, first_is_volume, has_changed, &fuser, keep_old); + + check_operation(new_shape,second_shape, is_volume[i], has_changed, &fuser, keep_old); + } + + //ok, we're done with all unites, construct new Body' + DLIList<TopologyBridge*> tbs; + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*first_shape); + + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + newBodies.append(bodysm); + } + + //ok, we're done with all unites, delete unnecessaries. + if(keep_old) + { + shape_list.append(first_shape); + int size = shape_list.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Shape* shape = shape_list.pop(); + shape->Nullify(); + delete shape; + } + } + + return CUBIT_SUCCESS; +} + +CubitStatus OCCModifyEngine::thicken( DLIList<BodySM*>& bodies, + DLIList<BodySM*>& new_bodies, + double depth, + CubitBoolean both) const +{ + PRINT_ERROR("Option not supported for OCC based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : hollow +// Member Type: PUBLIC +// Description: Hollow existing solid body by remove one or several surfaces +// Can only take one body at a time. +// depth > 0, thick body going outside bodies +// depth < 0, thick body going inside bodies +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::hollow( DLIList<BodySM*>& bodies, + DLIList<Surface*>& surfs_to_remove, + DLIList<BodySM*>& new_bodies, + double depth) const +{ + if(bodies.size() != 1 || surfs_to_remove.size() < 1) + { + PRINT_ERROR("Making thick solid in OCC will take one body and at least one surface at a time.\n"); + return CUBIT_FAILURE; + } + + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_volume; + CubitStatus stat = get_shape_list(bodies, shape_list, is_volume, CUBIT_FALSE); + + if(!stat) + return stat; + + if(!is_volume.get())//sheet body + { + PRINT_ERROR("Making thick solid in OCC needs an initial solid body to hollow with.\n"); + return CUBIT_FAILURE; + } + + //make sure the body to be hollowed has only one lump + OCCBody* occ_body = CAST_TO(bodies.get(), OCCBody); + DLIList<Lump*> lumps; + lumps = occ_body->lumps(); + if(lumps.size()!=1) + { + PRINT_ERROR("bodies with more than one lump can't be hollowed to make a thick body.\n"); + return CUBIT_FAILURE; + } + + //make sure surfs_to_remove are all in bodies + DLIList<OCCSurface*> surfaces; + TopTools_ListOfShape face_shapes; + occ_body->get_all_surfaces(surfaces); + for(int i = 0; i < surfs_to_remove.size(); i++) + { + OCCSurface* occ_surf = CAST_TO(surfs_to_remove.get(), OCCSurface); + if(!occ_surf) + continue; + if(!surfaces.is_in_list(occ_surf)) + continue; + TopoDS_Face * face = occ_surf->get_TopoDS_Face(); + face_shapes.Append(*face); + } + + if(face_shapes.IsEmpty()) + { + PRINT_ERROR("The surfaces provided should be from the body to be hollowed.\n"); + return CUBIT_FAILURE; + } + + double tol = 1.e-3; //hard coded for now, can be changed by application + TopoDS_Shape* solid = shape_list.get(); + BRepOffsetAPI_MakeThickSolid hollower(*solid, face_shapes, depth, tol, + BRepOffset_Skin, Standard_False, + Standard_False, GeomAbs_Intersection); + TopoDS_Shape new_shape = hollower.Shape(); + TopoDS_Solid old_solid = TopoDS::Solid(*solid); + OCCLump::update_OCC_entity(old_solid , new_shape, &hollower); + + //ok, we're done with all hollowing, construct new Body' + DLIList<TopologyBridge*> tbs; + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + new_bodies.append(bodysm); + } + + return CUBIT_SUCCESS; +} + + +//=============================================================================== +// Function : flip_normals +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine :: flip_normals( DLIList<Surface*>& face_list ) const +{ + DLIList<Surface*> surface_list; + while (face_list.size()) + { + OCCSurface* occ_surface = CAST_TO(face_list.pop(), OCCSurface); + OCCShell* occ_shell = occ_surface->my_shell(); + DLIList<OCCSurface*> surfaces; + surfaces.append(occ_surface); + if(occ_shell) //find all surfaces in face_list that belong to this shell + { + int size = face_list.size(); + for ( int i = 0; i < size; i++) + { + occ_surface = CAST_TO(face_list.get(), OCCSurface); + if(occ_shell == occ_surface->my_shell()) + surfaces.append(CAST_TO(face_list.remove(),OCCSurface)); + else + face_list.step(); + } + + if (!occ_shell->is_sheet()) + { + DLIList<OCCCoFace*> cofaces; + cofaces = occ_shell->cofaces(); + for(int i = 0; i < cofaces.size(); i++) + { + OCCCoFace* coface =cofaces.get_and_step(); + occ_surface = coface->surface(); + if(surfaces.is_in_list(occ_surface)) + { + TopoDS_Face* topoface = occ_surface->get_TopoDS_Face(); + TopAbs_Orientation ori = topoface->Orientation(); + topoface->Orientation(ori == TopAbs_FORWARD ? TopAbs_REVERSED : + TopAbs_FORWARD); + occ_surface->set_TopoDS_Face(*topoface); + coface->set_sense(coface->sense() == CUBIT_FORWARD ? + CUBIT_REVERSED : CUBIT_FORWARD); + surface_list.append(occ_surface); + } + } + } + else //sheet body + { + TopoDS_Face* topoface = occ_surface->get_TopoDS_Face(); + TopAbs_Orientation ori = topoface->Orientation(); + topoface->Orientation(ori == TopAbs_FORWARD ? TopAbs_REVERSED : + TopAbs_FORWARD); + occ_surface->set_TopoDS_Face(*topoface); + surface_list.append(occ_surface); + } + PRINT_INFO( "Modified volume\n" ); + } + else + PRINT_WARNING( "Volume was not modified\n" ); + } + face_list = surface_list; + return CUBIT_SUCCESS; +} + + +//=============================================================================== +// Function : sweep_translational +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 09/08 +//=============================================================================== +CubitStatus OCCModifyEngine:: sweep_translational( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + const CubitVector& sweep_vector, + double draft_angle, //in Radius + int draft_type, //RightCorner=1 or RoundCorner =2 + bool switchside,//not used, shell and surfaces are one sided, not like Acis + bool rigid, //not used here, in Acis, it means whether the end surface is + // parallel to the starting surface, or perpendicular to the path + Surface* stop_surf, + BodySM* to_body) const +{ + //in OCC, there's no sweep surface with draft option, this can be done by + //creating draft shell then make solid to achieve. + //while if draft_angle is 0, and stop_surf = 0, to_body = 0 + // directly use sweep functions. + TopoDS_Shape *stop_shape = NULL; + if(stop_surf) + { + OCCSurface* occ_surface = CAST_TO(stop_surf, OCCSurface); + stop_shape = occ_surface->get_TopoDS_Face(); + } + else if(to_body) + { + OCCBody* occ_body = CAST_TO(to_body, OCCBody); + if(occ_body->is_sheet_body()) + stop_shape = occ_body->my_sheet_surface()->get_TopoDS_Face(); + else if(occ_body->shell()) + stop_shape = occ_body->shell()->get_TopoDS_Shell(); + else + stop_shape = occ_body->get_TopoDS_Shape(); + } + + gp_Dir adir(sweep_vector.x(), sweep_vector.y(), sweep_vector.z()); + gp_Vec aVec(sweep_vector.x(), sweep_vector.y(), sweep_vector.z()); + + for (int i = ref_ent_list.size(); i > 0; i--) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + //Make copy of the surface for later to build solid. + OCCSurface* surface = CAST_TO(ref_ent, OCCSurface); + TopoDS_Shape toposhape ; + if(surface != NULL) + { + CubitStatus stat = get_sweepable_toposhape(surface, &sweep_vector, toposhape); + if(!stat) + continue; + } + OCCCurve* curve = CAST_TO(ref_ent, OCCCurve); + if(curve != NULL) + { + CubitStatus stat = get_sweepable_toposhape(curve, toposhape); + if(!stat) + continue; + } + + DLIList<TopologyBridge*> tbs; + //create the draft or the sweep + if(stop_shape == NULL && draft_angle == 0.) + { + BRepSweep_Prism swept(toposhape, aVec); + TopoDS_Shape new_shape = swept.Shape(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if (bodysm) + result_body_list.append(bodysm); + continue; + } + + BRepOffsetAPI_MakeDraft draft(toposhape, adir, draft_angle); + BRepBuilderAPI_TransitionMode Cornertype; + if(draft_type == 1) + Cornertype = BRepBuilderAPI_RightCorner; + else if(draft_type == 2) + Cornertype = BRepBuilderAPI_RoundCorner; + + draft.SetOptions(Cornertype); + if(stop_shape) + draft.Perform(*stop_shape); + else + draft.Perform(sweep_vector.length()); + TopoDS_Shape new_shape = draft.Shape(); + + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if(bodysm && surface != NULL) //only gets swept side and original surfaces + { + //get surfaces from the shell body and create a top surface to + //make a swept solid. + OCCShell* occ_shell = CAST_TO(bodysm, OCCBody)->shell(); + if(!occ_shell) + { + PRINT_WARNING("Sweep surface failed inside OCC engine.\n"); + return CUBIT_FAILURE; + } + DLIList<OCCCoFace*> cofaces = occ_shell->cofaces(); + DLIList<Surface*> surface_list; + for(int i = 0; i < cofaces.size(); i++) + surface_list.append(cofaces.get_and_step()->surface()); + + //create the top surface from edges. + DLIList<OCCCoEdge*> coedges; + for(int i = 0; i < surface_list.size(); i++) + CAST_TO(surface_list.get_and_step(), OCCSurface)->get_coedges(coedges); + for(int i = 0; i < coedges.size(); i++) + { + OCCCoEdge* coedge = coedges[i]; + if(coedge == NULL) + continue; + for(int j = i+1; j < coedges.size(); j++) + { + OCCCoEdge* temp_coedge = coedges[j]; + if(temp_coedge == NULL) + continue; + if(coedge->curve() == temp_coedge->curve() && + coedge->sense() != temp_coedge->sense()) + { + coedges.move_to(coedge); + coedges.change_to((OCCCoEdge*)NULL); + coedges.move_to(temp_coedge); + coedges.change_to((OCCCoEdge*)NULL); + } + } + } + coedges.remove_all_with_value(NULL); + assert(coedges.size() > 0); + DLIList<Curve*> curves; + for(int i = 0; i < coedges.size(); i++) + curves.append(coedges.get_and_step()->curve()); + + Surface* surf = make_Surface(PLANE_SURFACE_TYPE, curves); + if(!surf) + surf = make_Surface(BEST_FIT_SURFACE_TYPE, curves); + if(!surf) + { + PRINT_ERROR("Can't calculate for the top surface.\n"); + continue; + } + surface_list.append(surf); + DLIList<BodySM*> bodies; + create_solid_bodies_from_surfs(surface_list, bodies); + + if(bodies.size() == 1) + bodysm = bodies.get(); + else + { + PRINT_WARNING("Sweep surface failed in creating solid.\n"); + return CUBIT_FAILURE; + } + } + if (bodysm) + result_body_list.append(bodysm); + } + return CUBIT_SUCCESS; +} + +CubitStatus OCCModifyEngine::get_sweepable_toposhape(OCCCurve*& curve, + TopoDS_Shape& toposhape)const +{ + DLIList<OCCLoop*> loops; + loops = curve->loops(); + if( loops.size()) //not a free curve + { + //copy the curve + Curve* c_curve = make_Curve(curve); + if(c_curve) + curve = CAST_TO(c_curve, OCCCurve); + else + { + PRINT_ERROR("Can't copy the curve for sweep.\n"); + return CUBIT_FAILURE; + } + } + TopoDS_Edge *edge = curve->get_TopoDS_Edge( ); + toposhape = BRepBuilderAPI_MakeWire(*edge); + return CUBIT_SUCCESS; +} + +CubitStatus OCCModifyEngine::get_sweepable_toposhape(OCCSurface*& surface, + const CubitVector* sweep_v_p, + TopoDS_Shape& toposhape)const +{ + GeometryEntity* ref_ent = NULL; + //Make copy of the surface if it's not a sheet surface. + Surface* c_surface = NULL; + if(surface != NULL) + { + //check if the surface is sheet body, if not, copy it. + if(surface->my_body() == NULL) //not a sheet body + { + c_surface = make_Surface(surface); + if (c_surface == NULL) + { + PRINT_ERROR("Cannot copy surface in sweep_translational.\n"); + return CUBIT_FAILURE; + } + surface = CAST_TO(c_surface, OCCSurface); + } + + if(sweep_v_p) + { + CubitVector center = surface->center_point(); + CubitVector normal; + surface->closest_point(center,NULL,&normal); + CubitVector sweep_vector = *sweep_v_p; + if(normal % sweep_vector > 0) + { + DLIList<Surface*> surfaces; + surfaces.append(surface); + flip_normals(surfaces); + surface = CAST_TO(surfaces.get(), OCCSurface); + ref_ent = (GeometryEntity *)surface; + } + + else if(normal % sweep_vector == 0) + { + PRINT_ERROR("Sweeping direction should not be on the surface.\n"); + return CUBIT_FAILURE; + } + } + else + ref_ent = (GeometryEntity *)surface; + + if(surface->my_body() != NULL) //sheet body + { + delete surface->my_body(); + delete surface->my_shell(); + delete surface->my_lump(); + surface->set_shell(NULL); + surface->set_lump(NULL); + surface->set_body(NULL); + } + + TopoDS_Shape* toposhape_prt = + OCCQueryEngine::instance()->get_TopoDS_Shape_of_entity(ref_ent); + + if(!toposhape_prt) + { + PRINT_WARNING("GeometryEntity without TopoDS_Shape found.\n"); + return CUBIT_FAILURE; + } + toposhape = *toposhape_prt; + } + return CUBIT_SUCCESS; +} +//=============================================================================== +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 10/08 +//=============================================================================== +CubitStatus OCCModifyEngine:: sweep_perpendicular( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + double distance, + double draft_angle, + int draft_type, + bool switchside, //has no effect + bool rigid, //has no effect + Surface* stop_surf, + BodySM* to_body) const +{ + //find the vector perpendicular to the ref_ent normal, and sweep_translate + //the 'distance' along this vector + DLIList<GeometryEntity*> edge_list; + CubitVector vec; + for(int i = 0; i < ref_ent_list.size(); i++) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + Surface *face = CAST_TO(ref_ent, Surface); + Curve* edge = CAST_TO(ref_ent, Curve); + DLIList<GeometryEntity*> face_list; + if(face != NULL) + { + OCCSurface* occ_face = CAST_TO(face, OCCSurface); + CubitVector center = occ_face->center_point(); + CubitVector closest_p, unit_normal; + CubitStatus stat = + occ_face->closest_point(center, &closest_p, &unit_normal); + if(stat) + { + vec = distance * unit_normal; + face_list.append(ref_ent); + stat = sweep_translational(face_list, result_body_list, vec, + draft_angle, draft_type, switchside, + rigid, stop_surf, to_body); + } + } + else if (edge != NULL) + { + edge_list.append(ref_ent); + } + } + if(edge_list.size()) + PRINT_ERROR("Curves cannot be swept perpendicularly, please use the vector sweep.\n"); + + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : sweep_rotational +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 10/08 +//=============================================================================== +CubitStatus OCCModifyEngine:: sweep_rotational( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + const CubitVector& point, + const CubitVector& direction, + double angle, //in radians + int steps, //not used + double draft_angle, //not used + int draft_type, //not used + bool switchside, //not used + bool make_solid, + bool rigid, //not used + Surface* stop_surf, //not used + BodySM* to_body ) const //not used +{ + gp_Dir adir(direction.x(), direction.y(), direction.z()); + gp_Pnt pt = gp_Pnt( point.x(), point.y(), point.z()); + gp_Ax1 axis = gp_Ax1(pt, adir); + + gp_Lin line = gp_Lin(axis); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(line); + OCCCurve* acurve = new OCCCurve(&edge); + assert(acurve); + + CubitVector start; + CubitVector end; + + for (int i = ref_ent_list.size(); i > 0; i--) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + //Make copy of the surface or curve for later to build solid. + OCCSurface* surface = CAST_TO(ref_ent, OCCSurface); + OCCCurve* curve = CAST_TO(ref_ent, OCCCurve); + TopoDS_Shape toposhape ; + if(surface != NULL) + { + CubitStatus stat = get_sweepable_toposhape(surface, (CubitVector*)NULL, toposhape); + if(!stat) + continue; + //only non-intersecting of surface and axis can be swept. + DLIList<CubitVector*> intersect_pts; + OCCQueryEngine::instance()->get_intersections(acurve, surface, + intersect_pts, CUBIT_TRUE); + if(intersect_pts.size() > 0) + { + PRINT_ERROR("Only surfaces with no intersection point with the axis can be revolve-swept.\n"); + continue; + } + } + else if(curve != NULL) + { + CubitStatus stat = get_sweepable_toposhape(curve, toposhape); + if(!stat) + continue; + //closed curve can't intersect with the axis, while open curve can only + //intersect the axis at the end points. + //only curve not intersecting with axis in curve's middle locations + //can be revolved + DLIList<CubitVector*> intersect_pts; + OCCQueryEngine::instance()->get_intersections(curve, acurve, + intersect_pts, CUBIT_TRUE, CUBIT_TRUE); + if(!toposhape.Closed()) + { + //get start and end points + DLIList<OCCPoint*> point_list; + curve->get_points(point_list); + assert(2 == point_list.size()); + GeometryType type = curve->geometry_type(); + start = point_list.get_and_step()->coordinates(); + end = point_list.get()->coordinates(); + CubitBoolean start_int = CUBIT_FALSE; + CubitBoolean end_int = CUBIT_FALSE; + if(intersect_pts.size() > 0) + { + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + CubitBoolean non_int = CUBIT_FALSE; + for(int i = 0; i < intersect_pts.size(); i++) + { + CubitVector prt = *(intersect_pts.get_and_step()); + if(prt.distance_between(start) > tol && + prt.distance_between(end) > tol) + { + non_int = CUBIT_TRUE; + PRINT_ERROR("Only curves with no intersection point with the axis can be revolve-swept.\n"); + break; + } + else if(prt.distance_between(start) <= tol) + start_int = CUBIT_TRUE; + else if(prt.distance_between(end) <= tol) + end_int = CUBIT_TRUE; + } + if(non_int) + continue; + if(start_int && end_int && type == STRAIGHT_CURVE_TYPE) + { + PRINT_ERROR("Sweep along curve itself is not allowed.\n"); + continue; + } + } + } + else + { + if(intersect_pts.size() > 0) + { + PRINT_ERROR("Only curves with no intersection point with the axis can be revolve-swept.\n"); + continue; + } + } + } + else + { + PRINT_ERROR("Only surface or curve can be revolve-swept.\n"); + continue; + } + TopoDS_Shape new_shape; + DLIList<TopologyBridge*> tbs; + if(make_solid && curve != NULL ) + //giving an open wire and want a solid + { + if(!toposhape.Closed()) + { + //project the start and end points onto the axis + CubitBoolean start_closed = CUBIT_FALSE; + CubitBoolean end_closed = CUBIT_FALSE; + if(acurve->point_containment(start) != CUBIT_PNT_OFF) + start_closed = CUBIT_TRUE; + if(acurve->point_containment(end) != CUBIT_PNT_OFF) + end_closed = CUBIT_TRUE; + CubitVector start_proj, end_proj; + TopoDS_Edge edge1, edge2; + BRepBuilderAPI_MakeWire m_wire; + if(!start_closed) + { + acurve->closest_point(start, start_proj); + gp_Pnt pt1 = gp_Pnt( start.x(), start.y(), start.z()); + gp_Pnt pt2 = gp_Pnt( start_proj.x(), start_proj.y(), start_proj.z()); + edge1 = BRepBuilderAPI_MakeEdge(pt1, pt2); + m_wire.Add(edge1); + m_wire.Add(TopoDS::Wire(toposhape)); + } + else + { + m_wire.Add(TopoDS::Wire(toposhape)); + start_proj = start; + } + + if(!end_closed) + { + acurve->closest_point(end,end_proj); + gp_Pnt pt1 = gp_Pnt( end.x(), end.y(), end.z()); + gp_Pnt pt2 = gp_Pnt( end_proj.x(), end_proj.y(), end_proj.z()); + edge2 = BRepBuilderAPI_MakeEdge(pt1, pt2); + m_wire.Add(edge2); + } + + else + end_proj = end; + + gp_Pnt pt1 = gp_Pnt( end_proj.x(), end_proj.y(), end_proj.z()); + gp_Pnt pt2 = gp_Pnt( start_proj.x(), start_proj.y(), start_proj.z()); + TopoDS_Edge edge3 = BRepBuilderAPI_MakeEdge(pt2, pt1); + m_wire.Add(edge3); + + TopoDS_Wire wire = m_wire.Wire(); + toposhape = BRepBuilderAPI_MakeFace(wire); + } + else //closed + { + TopoDS_Wire wire = TopoDS::Wire(toposhape); + toposhape = BRepBuilderAPI_MakeFace(wire); + } + } + BRepSweep_Revol revol(toposhape, axis, angle); + new_shape = revol.Shape(); + + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if (bodysm) + result_body_list.append(bodysm); + continue; + } + OCCQueryEngine::instance()->delete_solid_model_entities(acurve); + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : sweep_along_curve +// Member Type: PUBLIC +// Description: The ref_edge_list must provide a list of curves which are +// connected, and making G1 continuous wire. +// Author : Jane Hu +// Date : 10/08 +//=============================================================================== +CubitStatus OCCModifyEngine::sweep_along_curve( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + DLIList<Curve*>& ref_edge_list, + double draft_angle, //only used for straight curve case + int draft_type, //only used for straight curve case + bool rigid, //not used + Surface* stop_surf, //not used + BodySM* to_body) const //not used +{ + //make wire out of ref_edge_list + BRepBuilderAPI_MakeWire awire; + TopTools_ListOfShape L; + OCCCurve* occ_curve = NULL; + GeometryType type; + int num_curve = 0; + for(int i = 0; i < ref_edge_list.size(); i++) + { + Curve* curve = ref_edge_list.get_and_step(); + occ_curve = CAST_TO(curve, OCCCurve); + if(!occ_curve) + continue; + TopoDS_Edge* topoedge = occ_curve->get_TopoDS_Edge( ); + BRepBuilderAPI_Copy api_copy(*topoedge); + TopoDS_Shape newShape = api_copy.ModifiedShape(*topoedge); + L.Append(newShape); + type = occ_curve->geometry_type(); + num_curve++; + } + if(L.IsEmpty()) + { + PRINT_ERROR("There's no valid sweeping path.\n"); + return CUBIT_FAILURE; + } + + if(num_curve == 1 && type == STRAIGHT_CURVE_TYPE && draft_angle != 0.0) + { + DLIList<OCCPoint*> point_list; + occ_curve->get_points(point_list); + CubitVector v1 = point_list.get_and_step()->coordinates(); + CubitVector v2 = point_list.get()->coordinates(); + CubitVector sweep_vector = v2-v1; + return sweep_translational(ref_ent_list,result_body_list,sweep_vector, + draft_angle, draft_type, CUBIT_FALSE, + rigid, stop_surf, to_body); + } + awire.Add(L); + TopoDS_Wire wire; + wire = awire.Wire(); + + BRepTools_WireExplorer it(wire); + int num_edges = 0; + for(; it.More(); it.Next()) + num_edges++; + + BRepLib_FuseEdges fuser(wire); + fuser.SetConcatBSpl(); + fuser.Perform(); + TopoDS_Shape spline = fuser.Shape(); + wire = TopoDS::Wire(spline); + + DLIList<TopologyBridge*> tbs; + for (int i = ref_ent_list.size(); i > 0; i--) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + //Make copy of the surface or curve for later to build solid. + OCCSurface* surface = CAST_TO(ref_ent, OCCSurface); + OCCCurve* curve = CAST_TO(ref_ent, OCCCurve); + TopoDS_Shape toposhape ; + if(surface != NULL) + { + CubitStatus stat = get_sweepable_toposhape(surface, (CubitVector*)NULL, toposhape); + if(!stat) + continue; + } + else if(curve != NULL) + { + CubitStatus stat = get_sweepable_toposhape(curve, toposhape); + if(!stat) + continue; + } + + //sweep along the wire + BRepOffsetAPI_MakePipe maker(wire, toposhape); + if(!maker.IsDone()) + { + PRINT_ERROR("Can't sweep along the provided curve(s).\n"); + continue; + } + TopoDS_Shape newShape = maker.Shape(); + + tbs += OCCQueryEngine::instance()->populate_topology_bridge(newShape); + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if (bodysm) + result_body_list.append(bodysm); + continue; + } + return CUBIT_SUCCESS; +} + +//HEADER- Webcut-related functions + +//=============================================================================== +// Function : webcut +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut(DLIList<BodySM*>& webcut_body_list, + const CubitVector &v1, + const CubitVector &v2, + const CubitVector &v3, + DLIList<BodySM*>& results_list, + bool imprint ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut(DLIList<BodySM*>& /*webcut_body_list*/, + BodySM const* /*tool_body*/, + DLIList<BodySM*>& /*results_list*/, + bool /*imprint*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_across_translate +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_across_translate( DLIList<BodySM*>& /*body_list*/, + Surface* /*plane_surf1*/, + Surface* /*plane_surf2*/, + DLIList<BodySM*>& /*results_list*/, + bool /*imprint*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_sheet +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_sheet(DLIList<BodySM*> & /*webcut_body_list*/, + BodySM * /*sheet_body*/, + DLIList<BodySM*> & /*new_bodies*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_extended_surf +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_extended_surf(DLIList<BodySM*> & /*webcut_body_list*/, + Surface * /*extend_from*/, + DLIList<BodySM*> & /*new_bodies*/, + int & /*num_cut*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_cylinder +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_cylinder(DLIList<BodySM*> &webcut_body_list, + double radius, + const CubitVector &axis, + const CubitVector ¢er, + DLIList<BodySM*>& results_list, + bool imprint ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_brick +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_brick( + DLIList<BodySM*>& /*webcut_body_list*/, + const CubitVector &/*center*/, + const CubitVector* /*axes[3]*/, + const CubitVector &/*extension*/, + DLIList<BodySM*> &/*results_list*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_planar_sheet +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_planar_sheet( + DLIList<BodySM*>& /*webcut_body_list*/, + const CubitVector &/*center*/, + const CubitVector* /*axes[2]*/, + double /*width*/, + double /*height*/, + DLIList<BodySM*> &/*results_list*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_curve_loop +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_curve_loop( + DLIList<BodySM*> &/*webcut_body_list*/, + DLIList<Curve*> &/*ref_edge_list*/, + DLIList<BodySM*>& /*results_list*/, + bool /*imprint*/) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : section +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 11/08 +//=============================================================================== +CubitStatus OCCModifyEngine::section( DLIList<BodySM*> §ion_body_list, + const CubitVector &point_1, + const CubitVector &point_2, + const CubitVector &point_3, + DLIList<BodySM*>& new_body_list, + bool keep_normal_side, + bool keep_old, + bool keep_both_sides) +{ + if (keep_both_sides == CUBIT_TRUE ) + { + PRINT_ERROR("keeping both sides of section is not implemented.\n"); + return CUBIT_FAILURE; + } + + //Calculate normal of the section plan + CubitVector v1, v2, normal; + v1 = point_2 - point_1; + v2 = point_3 - point_1; + normal = ~(v1 * v2); + if(normal.length() != 1) + { + PRINT_ERROR("The three points are co-linear, and can't be used as a cutting plane.\n"); + return CUBIT_FAILURE; + } + + if(keep_normal_side) + normal *= -1; + + gp_Pnt pt = gp_Pnt( point_1.x(), point_1.y(), point_1.z()); + gp_Dir normal_dir(normal.x(), normal.y(), normal.z()); + gp_Pln plane(pt, normal_dir); + gp_Vec vec(normal_dir); + pt = pt.Translated(vec); + + TopoDS_Face face = BRepBuilderAPI_MakeFace(plane); + TopoDS_Solid solid = BRepPrimAPI_MakeHalfSpace(face, pt); + + DLIList<CubitBoolean> is_tool_volume; + is_tool_volume.append(CUBIT_TRUE); + DLIList<CubitBox*> tool_boxes ; + Bnd_Box box; + BRepBndLib::Add(solid, box); + double min[3], max[3]; + box.Get(min[0], min[1], min[2], max[0], max[1], max[2]); + CubitBox* cBox = new CubitBox(min, max); + + tool_boxes.append(cBox); + DLIList<TopoDS_Shape*> solids; + solids.append(&solid); + CubitStatus stat = do_subtract(section_body_list, solids, is_tool_volume, + &tool_boxes, new_body_list, keep_old) ; + delete cBox; + return stat; +} + +//=============================================================================== +// Function : split_body +// Member Type: PUBLIC +// Description: Splits multiple lumps in one body into separate bodies +// Author : Corey Ernst +// Date : 08/04 +//=============================================================================== +CubitStatus OCCModifyEngine::split_body( BodySM *body_ptr, + DLIList<BodySM*> &new_bodies ) +{ + return CUBIT_SUCCESS; +} + + +//=============================================================================== +// Function : reverse_body +// Member Type: PUBLIC +// Description: Turn body inside-out +// Author : Jason Kraftcheck +// Date : 05/25/04 +//=============================================================================== +CubitStatus OCCModifyEngine::reverse_body( BodySM* body_ptr ) +{ + return CUBIT_SUCCESS; +} + + + +//=============================================================================== +// Function : split_periodic +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::split_periodic( BodySM * /*body_ptr*/, + BodySM *& /*new_body*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : regularize_body +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::regularize_body( BodySM * /*body_ptr*/, + BodySM *& /*new_body_ptr*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : regularize_refentity +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::regularize_entity( GeometryEntity * /*old_entity_ptr*/, + BodySM *& /*new_body_ptr*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : offset_curves +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::offset_curves( DLIList<Curve*>& /*ref_edge_list*/, + DLIList<Curve*>&, + double /*offset_distance*/, + const CubitVector& /*offset_direction*/, + int /*gap_type*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : trim_curve +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +Curve* OCCModifyEngine::trim_curve( Curve* /*trim_curve*/, + const CubitVector& /*trim_vector*/, + const CubitVector& /*keep_vector*/, + bool ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return 0; +} + +//=============================================================================== +// Function : create_body_from_surfs +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 4/22/08 +//=============================================================================== +CubitStatus OCCModifyEngine::create_solid_bodies_from_surfs(DLIList<Surface*> & ref_face_list, + DLIList<BodySM*>& new_bodies, + bool keep_old, + bool heal) const +{ + //keep_old and heal are ignored, always delete old. + //all surfaces should be stand along surface bodies or shell bodies' surface + Lump* lump = make_Lump(ref_face_list); + if (!lump) + return CUBIT_FAILURE; + + new_bodies.append(CAST_TO(lump, OCCLump)->get_body()); + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : create_arc_three +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 12/08 +//=============================================================================== +Curve* OCCModifyEngine::create_arc_three( Point* pt1, + Point* pt2, + Point* pt3, + bool full ) +{ + if(!full) + { + CubitVector v2(pt2->coordinates()); + return make_Curve(ARC_CURVE_TYPE,pt1,pt3, &v2, CUBIT_FORWARD); + } + else + { + CubitVector v1(pt1->coordinates()); + CubitVector v2(pt2->coordinates()); + CubitVector v3(pt3->coordinates()); + + gp_Pnt gp_pt1(v1.x(),v1.y(), v1.z()); + gp_Pnt gp_pt2(v2.x(),v2.y(), v2.z()); + gp_Pnt gp_pt3(v3.x(),v3.y(), v3.z()); + + Handle(Geom_Circle) curve_ptr; + curve_ptr = GC_MakeCircle(gp_pt1,gp_pt2,gp_pt3); + + OCCPoint* occ_pt1 = CAST_TO(const_cast<Point*>(pt1),OCCPoint); + TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex(); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt1); + return OCCQueryEngine::instance()->populate_topology_bridge(new_edge); + } +} + +//=============================================================================== +// Function : create_arc_three +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 12/08 +//=============================================================================== +Curve* OCCModifyEngine::create_arc_three( Curve* curve1, + Curve* curve2, + Curve* curve3, + bool full ) +{ + OCCCurve* occ_crv1 = CAST_TO(curve1, OCCCurve); + OCCCurve* occ_crv2 = CAST_TO(curve2, OCCCurve); + OCCCurve* occ_crv3 = CAST_TO(curve3, OCCCurve); + GeometryType type1 = occ_crv1->geometry_type(); + GeometryType type2 = occ_crv2->geometry_type(); + GeometryType type3 = occ_crv3->geometry_type(); + if(type1 != STRAIGHT_CURVE_TYPE || type2 != STRAIGHT_CURVE_TYPE || + type3 != STRAIGHT_CURVE_TYPE) + { + PRINT_WARNING("Need three straight curves to calculate incenter.\n"); + return (Curve*) NULL; + } + + //0.check that non of the curves are parallel of each other. + double u11, u12, u21, u22, u31, u32; + occ_crv1->get_param_range(u11, u12); + occ_crv2->get_param_range(u21, u22); + occ_crv3->get_param_range(u31, u32); + + CubitVector pt1, pt2, pt3; + occ_crv1->position_from_u(u11, pt1); + occ_crv2->position_from_u(u21, pt2); + occ_crv3->position_from_u(u31, pt3); + + CubitVector tangent1, tangent2, tangent3; + occ_crv1->get_tangent(pt1, tangent1); + occ_crv2->get_tangent(pt2, tangent2); + occ_crv3->get_tangent(pt3, tangent3); + + CubitVector normal1 = tangent1 * tangent2; + CubitVector normal2 = tangent2 * tangent3; + CubitVector normal3 = tangent3 * tangent1; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + if( normal1.length()< tol || normal2.length()< tol || + normal3.length() < tol ) + { + PRINT_WARNING("Three curves must be able to form a triangle.\n"); + return (Curve*) NULL; + } + + //normals must parallel to each other, meaning all curves must be on + //the same plane. + normal1.normalize(); + normal2.normalize(); + normal3.normalize(); + + CubitVector parallel1 = normal1 * normal2; + CubitVector parallel2 = normal2 * normal3; + CubitVector parallel3 = normal3 * normal1; + if(parallel1.length() > tol || parallel2.length() > tol || + parallel3.length() > tol) + { + PRINT_WARNING("Three curves must be able to form a triangle.\n"); + return (Curve*) NULL; + } + //1.find the angle between each of the two curves + double angle1, angle2, angle3; + angle1 = tangent1.interior_angle(tangent2); + angle2 = tangent2.interior_angle(tangent3); + angle3 = tangent3.interior_angle(tangent1); + + //2.create curves to bisection each of the angle passing through the + // vertices of the triangle + DLIList<CubitVector*> intscts; + CubitVector vt1, vt2, vt3; + OCCQueryEngine::instance()->get_intersections(curve1, curve2, intscts,0,0); + vt1 = *intscts.get(); + intscts.clean_out(); + OCCQueryEngine::instance()->get_intersections(curve2,curve3, intscts,0,0); + vt2 = *intscts.get(); + intscts.clean_out(); + OCCQueryEngine::instance()->get_intersections(curve3, curve1, intscts,0,0); + vt3 = *intscts.get(); + //Create 6 curves, find 3 of them which have intersection points inside + // the third curve + CubitVector t_curve11 = + vectorRotate(angle1/2.0, normal1, tangent1); + t_curve11.normalize(); + CubitVector p11 = vt1+t_curve11; + + CubitVector t_curve12 = + vectorRotate(90.0 - angle1/2.0, -normal1, tangent1); + t_curve12.normalize(); + CubitVector p12 = vt1 + t_curve12; + + CubitVector t_curve21 = + vectorRotate(angle2/2.0, normal2, tangent2); + t_curve21.normalize(); + CubitVector p21 = vt2 + t_curve21; + + CubitVector t_curve22 = + vectorRotate(90.0 - angle2/2.0, -normal2, tangent2); + t_curve22.normalize(); + CubitVector p22 = vt2 + t_curve22; + + CubitVector t_curve31 = + vectorRotate(angle3/2.0, normal3, tangent3); + t_curve31.normalize(); + CubitVector p31 = vt3 + t_curve31; + + CubitVector t_curve32 = + vectorRotate(90.0 - angle3/2.0, -normal3, tangent3); + t_curve32.normalize(); + CubitVector p32 = vt3 + t_curve32; + + //3. find the intersection of each of the bisection curve with the third curve + CubitVector int_pt1, int_pt2, int_pt3; + intscts.clean_out(); + CubitBoolean none = CUBIT_FALSE; + OCCQueryEngine::instance()->get_intersections(curve3, vt1, p11, intscts,none,none); + CubitVector int_pt = *intscts.pop(); + double u = occ_crv3->u_from_position (int_pt); + if(u >= u31-tol && u <= u32+tol) //found intersection point + int_pt1 = int_pt; + else + { + OCCQueryEngine::instance()->get_intersections(curve3, vt1, p12, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv3->u_from_position (int_pt); + if(u >= u31-tol && u <= u32+tol) + int_pt1 = int_pt; + else + { + PRINT_ERROR("Can't find the intesection point to create circle.\n"); + return (Curve*) NULL; + } + } + + OCCQueryEngine::instance()->get_intersections(curve1, vt2, p21, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv1->u_from_position (int_pt); + if(u >= u11-tol && u <= u12+tol) //found intersection point + int_pt2 = int_pt; + else + { + OCCQueryEngine::instance()->get_intersections(curve1, vt2, p22, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv1->u_from_position (int_pt); + if(u >= u11-tol && u <= u12+tol) + int_pt2 = int_pt; + else + { + PRINT_ERROR("Can't find the intesection point to create circle.\n"); + return (Curve*) NULL; + } + } + + OCCQueryEngine::instance()->get_intersections(curve2, vt3, p31, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv2->u_from_position (int_pt); + if(u >= u21-tol && u <= u22+tol) //found intersection point + int_pt3 = int_pt; + else + { + OCCQueryEngine::instance()->get_intersections(curve2, vt3, p32, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv2->u_from_position (int_pt); + if(u >= u21-tol && u <= u22+tol) + int_pt3 = int_pt; + else + { + PRINT_ERROR("Can't find the intesection point to create circle.\n"); + return (Curve*) NULL; + } + } + //4. use the 3 intersection points to find the arc or circle. + OCCPoint occ_p1(int_pt1); + OCCPoint occ_p2(int_pt2); + OCCPoint occ_p3(int_pt3); + return create_arc_three(&occ_p1, &occ_p2, &occ_p3, full); +} + +//=============================================================================== +// Function : create_arc_center_edge +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +Curve* OCCModifyEngine::create_arc_center_edge( Point* /*ref_vertex1*/, + Point* /*ref_vertex2*/, + Point* /*ref_vertex3*/, + const CubitVector& /*normal*/, + double /*radius*/, + bool /*full*/ ) +{ + return NULL; +} + +CubitStatus +OCCModifyEngine::create_curve_combine( DLIList<Curve*>& curve_list, + Curve *&new_curve_ptr ) +{ + PRINT_ERROR("Curve combine is not implemented for facet based models\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : get_gqe +// Member Type: PUBLIC +// Description: get the facet geometry query engince instance pointer +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +GeometryQueryEngine *OCCModifyEngine::get_gqe() +{ + return OCCQueryEngine::instance(); +} + +//=============================================================================== +// Function : is_modify_engine +// Member Type: PUBLIC +// Description: return CUBIT_TRUE if the tb_ptr belongs to this modify engine +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitBoolean OCCModifyEngine::is_modify_engine(const TopologyBridge *tb_ptr) const +{ + return tb_ptr->get_geometry_query_engine() == OCCQueryEngine::instance(); +} + +//=============================================================================== +// Function : get_offset_intersections +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::get_offset_intersections( Curve* /*ref_edge1*/, + Curve* /*ref_edge2*/, + DLIList<CubitVector*>& /*intersection_list*/, + double /*offset*/, + CubitBoolean /*ext_first*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : get_offset_intersections +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::get_offset_intersections( Curve* /*ref_edge_ptr*/, + Surface* /*ref_face_ptr*/, + DLIList<CubitVector*> & /*intersection_list*/, + double /*offset*/, + CubitBoolean /*ext_surf*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : surface_intersection +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::surface_intersection( Surface * /*surface1_ptr*/, + Surface * /*surface2_ptr*/, + DLIList<Curve*> &/*inter_graph*/, + const double /*tol*/) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : get_mid_plane +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::get_mid_plane( const CubitVector & /*point_1*/, + const CubitVector & /*point_2*/, + const CubitVector & /*point_3*/, + BodySM * /*body_to_trim_to*/, + BodySM *& /*midplane_body*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::get_spheric_mid_surface( Surface* surface_ptr1, + Surface* surface_ptr2, + BodySM* body_to_trim_to, + BodySM*& midsurface_body ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::get_conic_mid_surface( Surface* surface_ptr1, + Surface* surface_ptr2, + BodySM* body_to_trim_to, + BodySM*& midsurface_body ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::get_toric_mid_surface( Surface* surface_ptr1, + Surface* surface_ptr2, + BodySM* body_to_trim_to, + BodySM*& midsurface_body ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_chamfer +// Member Type: PUBLIC +// Description: Chamfer curves on solid bodies. The left and right offsets are +// with respect to the curve direction. If the given right offset +// is negative, the left offset is used. Users can preview to +// clarify the meaning of left and right. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_chamfer( DLIList<Curve*> & /*curve_list*/, + double /*left_offset*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + double /*right_offset*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_chamfer +// Member Type: PUBLIC +// Description: Chamfer vertices on solid or sheet bodies. On a solid body +// there can be up to 3 offsets; on a sheet body up to 2 offsets. +// The offsets are in the direction of the supplied edges. If +// multiple vertices are supplied, only one offset value is +// allowed and the edges are not used. +// Author : +// Date : +//============================================================================= +CubitStatus +OCCModifyEngine::tweak_chamfer( DLIList<Point*> & /*point_list*/, + double /*offset1*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + Curve * /*edge1*/, + double /*offset2*/, + Curve * /*edge2*/, + double /*offset3*/, + Curve * /*edge3*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_fillet +// Member Type: PUBLIC +// Description: Create a round fillet (or blend) at the given curves on solid +// bodies. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_fillet( DLIList<Curve*> & /*curve_list*/, + double /*radius*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_fillet +// Member Type: PUBLIC +// Description: Create a round fillet (or blend) at the given curves on a solid +// body. The fillet has a variable radius from the start to the +// end of the curve. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_fillet( Curve * /*curve_ptr*/, + double /*start_radius*/, + double /*end_radius*/, + BodySM *& /*new_bodysm_ptr*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_fillet +// Member Type: PUBLIC +// Description: Create a round fillet (or blend) at the given vertices on sheet +// bodies. +// Author : +// Date : +//============================================================================= +CubitStatus +OCCModifyEngine::tweak_fillet( DLIList<Point*> & /*ref_vertex_list*/, + double /*radius*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_move +// Member Type: PUBLIC +// Description: Tweak specified faces of a volume or volumes along a vector. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_move( DLIList<Surface*> & /*surface_list*/, + const CubitVector & /*delta*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/ , + CubitBoolean show_preview) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_move +// Member Type: PUBLIC +// Description: Tweak specified curves of a sheet body along a vector. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_move( DLIList<Curve*> & /*curve_list*/, + const CubitVector & /*delta*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_offset +// Member Type: PUBLIC +// Description: Tweak specified faces of a volume or volumes by offsetting +// those faces by the offset distance. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_offset( DLIList<Surface*> & /*surface_list*/, + double /*offset_distance*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_offset +// Member Type: PUBLIC +// Description: Tweak specified curves of a sheet body or bodies by offsetting +// those curves by the offset distance. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_offset( DLIList<Curve*> & /*curve_list*/, + double /*offset_distance*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_remove +// Member Type: PUBLIC +// Description: Function to remove surfaces from a body and then extend the +// remaining surfaces to fill the gap or hole. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_remove( DLIList<Surface*> & /*surface_list*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*extend_adjoining*/, + CubitBoolean /*keep_surface*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_remove +// Member Type: PUBLIC +// Description: Function to remove curves from a sheet body and then extend the +// remaining curves or fill the gap or hole. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_remove( DLIList<Curve*> & /*curve_list*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_target +// Member Type: PUBLIC +// Description: Tweak specified faces of a volume or volumes up to a target +// surface. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_target( DLIList<Surface*> & /*surface_list*/, + DLIList<Surface*> & , + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*reverse_flg*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_target +// Member Type: PUBLIC +// Description: Tweak specified edges of a surface or set of surfaces (in sheet +// bodies) up to a target surface. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_target( DLIList<Curve*> & /*curve_list*/, + DLIList<Surface*> & /*target_surfs*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean , + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_target +// Member Type: PUBLIC +// Description: Tweak specified edges of a sheet body or bodies up to a target +// curve that is part of a sheet body. The target is a surface +// created by thickening the owning surface of the target curve. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_target( DLIList<Curve*> & /*curve_list*/, + DLIList<Curve*> & /*target_curve_ptr*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::remove_curve_slivers( BodySM* /*body*/, + double /*lengthlimit*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a net surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_net_surface( DLIList<Surface*>& /*ref_face_list*/, + BodySM *& /*new_body*/, + DLIList<DLIList<CubitVector*>*> & /*vec_lists_u*/, + DLIList<DLIList<CubitVector*>*> & /*vec_lists_v*/, + double /*net_tol*/, + CubitBoolean /*heal*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a net surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_net_surface( DLIList<Curve*>& /*u_curves*/, + DLIList<Curve*>& /*v_curves*/, + BodySM *& /*new_body*/, + double /*net_tol*/, + CubitBoolean /*heal*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates an offset surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_offset_surface( Surface* /*ref_face_ptr*/, + BodySM*& /*new_body*/, + double /*offset_distance*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates an offset body. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_offset_body( BodySM* body_ptr, + BodySM*& new_bodysm, + double offset_distance ) const +{ + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a skin surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_skin_surface( DLIList<Curve*>& /*curves*/, + BodySM*& /*new_body*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a body from lofting surfaces. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::loft_surfaces( Surface * /*face1*/, + const double & /*takeoff1*/, + Surface * /*face2*/, + const double & /*takeoff2*/, + BodySM*& /*new_body*/, + CubitBoolean /*arc_length_option*/, + CubitBoolean /*twist_option*/, + CubitBoolean /*align_direction*/, + CubitBoolean /*perpendicular*/, + CubitBoolean /*simplify_option*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a body by lofting surfaces between bodies. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::loft_surfaces_to_body( Surface * /*face1*/, + const double & /*takeoff1*/, + Surface * /*face2*/, + const double & /*takeoff2*/, + BodySM*& /*new_body*/, + CubitBoolean /*arc_length_option*/, + CubitBoolean /*twist_option*/, + CubitBoolean /*align_direction*/, + CubitBoolean /*perpendicular*/, + CubitBoolean /*simplify_option*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_surface( DLIList<CubitVector*>& /*vec_list*/, + BodySM *& /*new_body*/, + Surface * /*ref_face_ptr*/, + CubitBoolean /*project_points*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a weld surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_weld_surface( CubitVector & /*root*/, + Surface * /*ref_face1*/, + double /*leg1*/, + Surface * /*ref_face2*/, + double /*leg2*/, + BodySM *& /*new_body*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_surfaces( + DLIList<BodySM*> &blank_bodies, + DLIList<Surface*> &surfaces, + const CubitVector& sweep_vector, + bool sweep_perp, + bool through_all, + bool outward, + bool up_to_next, + Surface *stop_surf, + Curve *curve_to_sweep_along, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_curves( + DLIList<BodySM*> &blank_bodies, + DLIList<Curve*> &curves, + const CubitVector& sweep_vector, + bool through_all, + Surface *stop_surf, + Curve *curve_to_sweep_along, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_surfaces_rotated( + DLIList<BodySM*> &blank_bodies, + DLIList<Surface*> &surfaces, + const CubitVector &point, + const CubitVector &sweep_axis, + double angle, + Surface *stop_surf, + bool up_to_next, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_curves_rotated( + DLIList<BodySM*> &blank_bodies, + DLIList<Curve*> &curves, + const CubitVector &point, + const CubitVector &sweep_axis, + double angle, + Surface *stop_surf, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::scale( BodySM *&body, const CubitVector& factors ) +{ + return OCCQueryEngine::instance()->scale( body, factors ); +} + +CubitStatus OCCModifyEngine::tolerant_imprint( DLIList<BodySM*> &bodies_in, + DLIList<BodySM*> &new_bodies, + DLIList<TopologyBridge*>*, + DLIList<TopologyBridge*>* ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +// EOF Copied: cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2494 (from rev 2494, cgm/trunk/geom/OCC/OCCModifyEngine.cpp) =================================================================== --- cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2494 (rev 0) +++ cgm/trunk/geom/OCC/OCCModifyEngine.cpp_2494 2008-12-23 20:11:34 UTC (rev 2498) @@ -0,0 +1,5631 @@ +//------------------------------------------------------------------------- +//------------------------------------------------------------------------- + +// Filename : OCCModifyEngine.cpp +// +// Purpose : ModifyEngine for OCC geometry +// +// Special Notes : Modeled after GeometryModifyEngine and AcisModifyEngine. +// +// Author : Jane Hu +// +// Creation Date : 1/08 +// +//------------------------------------------------------------------------- +#include "gp_Pnt.hxx" +#include "gp_Ax2.hxx" +#include "gp_Dir.hxx" +#include "gp_Hypr.hxx" +#include "gp_Parab.hxx" +#include "gp_Elips.hxx" +#include "gp_Pln.hxx" +#include "gp_Cylinder.hxx" +#include "gp_Cone.hxx" +#include "gp_Sphere.hxx" +#include "gp_Torus.hxx" +#include "BRepBuilderAPI_MakeShell.hxx" +#include "BRepBuilderAPI_MakeSolid.hxx" +#include "BRepOffsetAPI_MakeDraft.hxx" +#include "BRepBuilderAPI_TransitionMode.hxx" +#include "BRepBuilderAPI_MakeWire.hxx" +#include "BRepPrimAPI_MakeHalfSpace.hxx" +#include "BRepBndLib.hxx" +#include "TopoDS_Shape.hxx" +#include "TopAbs_Orientation.hxx" +#include "TColgp_Array1OfPnt.hxx" +#include "GC_MakeArcOfCircle.hxx" +#include "GC_MakeCircle.hxx" +#include "GC_MakeArcOfHyperbola.hxx" +#include "GC_MakeArcOfParabola.hxx" +#include "GC_MakeArcOfEllipse.hxx" +#include "GC_MakeSegment.hxx" +#include "GC_MakeTrimmedCone.hxx" +#include "GC_MakeTrimmedCylinder.hxx" +#include "gce_MakeElips.hxx" +#include "Geom_BezierCurve.hxx" +#include "BndLib_AddSurface.hxx" +#include "Handle_Geom_Plane.hxx" +#include "BRepExtrema_DistShapeShape.hxx" +#include "Extrema_ExtPC.hxx" +#include "BRepPrimAPI_MakePrism.hxx" +#include "BRepSweep_Revol.hxx" +#include "BRepPrimAPI_MakeCone.hxx" +#include "BRepOffsetAPI_ThruSections.hxx" +#include "BRepLib_FuseEdges.hxx" +#include "BRepOffsetAPI_MakePipe.hxx" +#include "BRepPrimAPI_MakeTorus.hxx" +#include "BRepPrimAPI_MakeCylinder.hxx" +#include "BRepBuilderAPI_Transform.hxx" +#include "BRepAdaptor_Curve.hxx" +#include "GC_MakeEllipse.hxx" +#include "BRepBuilderAPI_MakeEdge.hxx" +#include "BRepAdaptor_Surface.hxx" +#include "BRepBuilderAPI_MakeFace.hxx" +#include "BRepOffsetAPI_MakeThickSolid.hxx" +#include "BRepBuilderAPI_Sewing.hxx" +#include "BRepBuilderAPI_Copy.hxx" +#include "LocOpe_SplitShape.hxx" +#include "BRep_Tool.hxx" +#include "BRep_Builder.hxx" +#include "GProp_GProps.hxx" +#include "BRepGProp.hxx" +#include "TopoDS.hxx" +#include "TopologyBridge.hpp" +#include "ProgressTool.hpp" +#include "BRepAlgoAPI_Fuse.hxx" +#include "BRepAlgoAPI_Cut.hxx" +#include "BRepAlgoAPI_Section.hxx" +#include "BRepAlgoAPI_Common.hxx" +#include "BRepPrimAPI_MakeSphere.hxx" +#include "BRepPrimAPI_MakeBox.hxx" +#include "BRepPrimAPI_MakeWedge.hxx" +#include "BRepTools_WireExplorer.hxx" +#include "Handle_Geom_TrimmedCurve.hxx" +#include "Handle_Geom_RectangularTrimmedSurface.hxx" +#include "BndLib_Add3dCurve.hxx" +#include "TopOpeBRep_EdgesIntersector.hxx" +#include "TopExp_Explorer.hxx" +#include "TopExp.hxx" +#include "OCCModifyEngine.hpp" +#include "OCCQueryEngine.hpp" +#include "OCCCoFace.hpp" +#include "CubitMessage.hpp" +#include "CubitDefines.h" +#include "TopTools_DataMapOfShapeInteger.hxx" +#include "BRepFeat_SplitShape.hxx" +#include "TopOpeBRep_ShapeIntersector.hxx" +#include "TopTools_ListIteratorOfListOfShape.hxx" +#include "CubitUtil.hpp" +#include "CubitPoint.hpp" +#include "CubitPointData.hpp" +#include "CubitFacet.hpp" +#include "CubitQuadFacet.hpp" +#include "CubitFacetData.hpp" +#include "CubitFacetEdge.hpp" +#include "CubitFacetEdgeData.hpp" +#include "GeometryQueryTool.hpp" +#include "GeometryModifyTool.hpp" +#include "ChollaSurface.hpp" +#include "ChollaCurve.hpp" +#include "ChollaPoint.hpp" +#include "OCCPoint.hpp" +#include "OCCCurve.hpp" +#include "CurveFacetEvalTool.hpp" +#include "FacetEvalTool.hpp" +#include "OCCCoEdge.hpp" +#include "OCCLoop.hpp" +#include "OCCSurface.hpp" +#include "OCCShell.hpp" +#include "OCCLump.hpp" +#include "OCCBody.hpp" +#include "ChollaEngine.hpp" +#include "TDGeomFacet.hpp" +#include "CubitFileIOWrapper.hpp" +#include "TDFacetBoundaryPoint.hpp" +#include "Cholla.h" +#include "Body.hpp" +#include "GfxDebug.hpp" +#include "RefFace.hpp" +#include "FacetDataUtil.hpp" +#include "FBDataUtil.hpp" +#include "FBIntersect.hpp" +#include "IntegerHash.hpp" +#include "CpuTimer.hpp" +#include "AppUtil.hpp" +#include "SphereEvaluator.hpp" +#include "CylinderEvaluator.hpp" +#include <vector> +OCCModifyEngine* OCCModifyEngine::instance_ = 0; +#define DEBUG +//=============================================================================== +// Function : OCCModifyEngine +// Member Type: PUBLIC +// Description: constructor +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +OCCModifyEngine::OCCModifyEngine() +{ +// assert( !instance_ ); + + // add this modify engine to geometrymodifytool + GeometryModifyTool::instance()->add_gme(this); +} + + +//=============================================================================== +// Function : ~OCCModifyEngine +// Member Type: PUBLIC +// Description: destructor +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +OCCModifyEngine::~OCCModifyEngine() +{ + instance_ = 0; +} + +//=============================================================================== +// Function : make_Point +// Member Type: PUBLIC +// Description: make a geometric entity point +// Author : Jane Hu +// Date : 10/07 +//=============================================================================== +Point* OCCModifyEngine::make_Point( CubitVector const& point) const +{ + gp_Pnt pt = gp_Pnt( point.x(), point.y(), point.z()); + TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt); + + // Create a new PointACIS object + return OCCQueryEngine::instance()->populate_topology_bridge( theVertex ); +} + +//=============================================================================== +// Function : make_Curve +// This function creates a curve given an existing curve, copy. +// Member Type: PUBLIC +// Description: make a curve +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve(Curve * curve_ptr) const +{ + OCCCurve* occ_curve = CAST_TO(curve_ptr, OCCCurve); + if (!occ_curve) + { + PRINT_ERROR("Cannot create an OCC curve from the given curve.\n" + "Possible incompatible geometry engines.\n"); + return (Curve *)NULL; + } + + TopoDS_Edge *theEdge = occ_curve->get_TopoDS_Edge(); + + BRepBuilderAPI_Copy api_copy(*theEdge); + + TopoDS_Shape newShape = api_copy.ModifiedShape(*theEdge); + + TopoDS_Edge newEdge = TopoDS::Edge(newShape); + + return OCCQueryEngine::instance()->populate_topology_bridge(newEdge); +} + +//=============================================================================== +// Function : make_Curve +// Member Type: PUBLIC +// Description: make a curve by projecting a straight line defined by +// point1_ptr, and point2_ptr onto face_ptr, third_point +// is used for curves that could be periodic to dertermine +// the correct direction. +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve( Point const* point1_ptr, + Point const* point2_ptr, + Surface* face_ptr, + const CubitVector * third_point) const +{ + assert (point1_ptr != NULL && point2_ptr != NULL); + GeometryType type = STRAIGHT_CURVE_TYPE; + CubitBoolean closed = CUBIT_FALSE; + DLIList<CubitVector*> mid_points; + Curve* curve = NULL; + if (point1_ptr != point2_ptr) + curve = make_Curve(type, point1_ptr, point2_ptr, mid_points); + else //could be a closed shape + { + if(third_point != NULL && face_ptr != NULL) + { + closed = CUBIT_TRUE; + Point * Pnt = make_Point(*third_point); + curve = make_Curve(type, point1_ptr, Pnt, mid_points); + } + else + { + PRINT_ERROR("Cannot create an OCC curve from the given duplicated points.\n"); + return (Curve *)NULL; + } + } + + Curve* new_curve = NULL; + if(face_ptr == NULL) + return curve; + + DLIList<Point*> points; + new_curve = + CAST_TO(curve, OCCCurve)->project_curve(face_ptr, points, closed, third_point); + + delete curve; + return new_curve; +} + +//=============================================================================== +// Function : make_Curve +// Member Type: PUBLIC +// Description: make a spline curve by using the points on surface. +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve( GeometryType curve_type, + Point const* point1_ptr, + Point const* point2_ptr, + DLIList<CubitVector*>& vector_list, + Surface* face_ptr) const +{ + assert(point1_ptr != NULL && point2_ptr != NULL); + + if (curve_type != SPLINE_CURVE_TYPE + && curve_type != STRAIGHT_CURVE_TYPE) + { + PRINT_ERROR("Cannot create an OCC curve from the given curve_type.\n" + "Candidates are SPLINE_CURVE_TYPE and STRAIGHT_CURVE_TYPE.\n"); + return (Curve *)NULL; + } + + if (curve_type == STRAIGHT_CURVE_TYPE) + return make_Curve(curve_type, point1_ptr, point2_ptr, NULL, CUBIT_FORWARD); + + OCCPoint* occ_point1 = CAST_TO(const_cast<Point*>(point1_ptr), OCCPoint); + OCCPoint* occ_point2 = CAST_TO(const_cast<Point*>(point2_ptr), OCCPoint); + + if (occ_point1 == NULL || occ_point2 == NULL) + { + PRINT_ERROR("Cannot create an OCC curve from the given points.\n" + "Possible incompatible geometry engines.\n"); + return (Curve *)NULL; + } + + //project all points on the surface if possible + OCCSurface* occ_face = NULL; + if (face_ptr != NULL) + occ_face = CAST_TO(face_ptr, OCCSurface); + + gp_Pnt pt; + int size = 2+vector_list.size(); + TColgp_Array1OfPnt points(1, size); + CubitVector* vector = NULL; + CubitVector closest_location; + for(int i = 1; i <= size; i++) + { + if (i == 1) + { + TopoDS_Vertex *point = occ_point1->get_TopoDS_Vertex(); + pt = BRep_Tool::Pnt(*point); + vector = new CubitVector(point1_ptr->coordinates()); + } + else if (i == size) + { + TopoDS_Vertex *point = occ_point2->get_TopoDS_Vertex(); + pt = BRep_Tool::Pnt(*point); + vector = new CubitVector(point2_ptr->coordinates()); + } + else + { + vector = vector_list.get_and_step(); + pt.SetCoord(vector->x(), vector->y(), vector->z()); + } + + if (occ_face != NULL) + { + occ_face->closest_point(*vector, &closest_location); + pt.SetCoord(closest_location.x(), closest_location.y(), closest_location.z()) ; + } + + points.SetValue(i, pt); + } + + //make curve according to the curve type. + if(curve_type == SPLINE_CURVE_TYPE) + { + Geom_BezierCurve BezierCurve(points); + Geom_BezierCurve* curve = new Geom_BezierCurve(BezierCurve); + Handle(Geom_BoundedCurve) curve_ptr(curve); + TopoDS_Vertex * vt1 = occ_point1->get_TopoDS_Vertex(); + TopoDS_Vertex * vt2 = occ_point2->get_TopoDS_Vertex(); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt2); + return OCCQueryEngine::instance()->populate_topology_bridge(new_edge); + } + + return (Curve*) NULL; +} + +//=============================================================================== +// Function : make_Curve +// Member Type: PUBLIC +// Description: make a curve +// For STRAIGHT_CURVE_TYPE: +// intermediate_point_ptr is not used +// +// For PARABOLA_CURVE_TYPE +// intermediate_point_ptr is the tip of the parabola +// +// For HYPERBOLA_CURVE_TYPE +// intermediate_point_ptr is the center of its two foci +// +// For ELLIPSE_CURVE_TYPE +// intermediate_point_ptr is the center of the ellipse +// the two points are vertices, one gives the major radius, +// the other point gives the minor radius. +// sense is used to determine which part of the ellipse is required +// +// For ARC_CURVE_TYPE +// arc passes three points +// +// Author : Jane Hu +// Date : 01/08 +//=============================================================================== +Curve* OCCModifyEngine::make_Curve( GeometryType curve_type, + Point const* point1_ptr, + Point const* point2_ptr, + CubitVector const* intermediate_point_ptr, + CubitSense sense) const +{ + assert (point1_ptr != NULL && point2_ptr != NULL); + DLIList<CubitVector*> mid_points; + if (intermediate_point_ptr) + { + CubitVector mid_point = *intermediate_point_ptr; + mid_points.append(&mid_point); + } + + CubitVector v1(point1_ptr->coordinates()); + CubitVector v2(point2_ptr->coordinates()); + + gp_Pnt pt1(v1.x(),v1.y(), v1.z()); + gp_Pnt pt2(v2.x(),v2.y(), v2.z()); + + CubitVector v3; + gp_Pnt pt3; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + + Handle(Geom_TrimmedCurve) curve_ptr; + if(intermediate_point_ptr != NULL) + { + v3 = *intermediate_point_ptr; + pt3.SetCoord(v3.x(),v3.y(), v3.z()); + } + + if (curve_type == STRAIGHT_CURVE_TYPE) + curve_ptr = GC_MakeSegment(pt1,pt2); + + else if (curve_type == ARC_CURVE_TYPE) + { + assert(intermediate_point_ptr != NULL); + curve_ptr = GC_MakeArcOfCircle(pt1, pt3, pt2); + } + + else if (curve_type == ELLIPSE_CURVE_TYPE) + { + assert(intermediate_point_ptr != NULL); + + gp_Pnt center(v3.x(), v3.y(), v3.z()); + + gp_Elips ellipse; + gce_MakeElips ellipse1(pt1 , pt2 , center); + if(ellipse1.IsDone()) + ellipse = ellipse1.Value(); + else if(!ellipse1.IsDone() && ellipse1.Status() == gce_InvertRadius) + { + gce_MakeElips ellipse2(pt2, pt1, center); + if(ellipse2.IsDone()) + ellipse = ellipse2.Value(); + else + { + PRINT_ERROR("Can't create an ellipse from give 3 points.\n"); + return (Curve *)NULL; + } + } + else + { + PRINT_ERROR("Can't create an ellipse from give 3 points.\n"); + return (Curve *)NULL; + } + CubitBoolean use_sense = (sense == CUBIT_FORWARD ? CUBIT_TRUE : CUBIT_FALSE); + curve_ptr = GC_MakeArcOfEllipse(ellipse, pt1, pt2, use_sense); + } + + else if(curve_type == PARABOLA_CURVE_TYPE || + curve_type == HYPERBOLA_CURVE_TYPE) + { + assert(intermediate_point_ptr != NULL); + + //find the directrix and focus of the parabola + //or the axis, major radius and minor radius of the hyperbola + CubitVector width_vec = v2 - v1; + if(width_vec.length_squared() < tol * tol) + { + PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n" + "2 end points are the same.\n"); + return (Curve *)NULL; + } + + CubitVector midpoint_vec = (v1 + v2)/2.0; + CubitVector height_vec = midpoint_vec - v3; + gp_Pnt center(v3.x(), v3.y(), v3.z()); + + if (height_vec.length_squared() < tol * tol) + { + PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n" + "3 points are in the same line.\n"); + return (Curve *)NULL; + } + CubitVector x = height_vec; + x.normalize(); + gp_Dir x_dir(x.x(), x.y(), x.z()); + + CubitVector N = x * (v2 - v1); + if (N.length_squared() < tol * tol) + { + PRINT_ERROR("Cannot create a parabola or hyperbola curve from the given points.\n" + "3 points are in the same line.\n"); + return (Curve *)NULL; + } + N.normalize(); + gp_Dir N_dir(N.x(), N.y(), N.z()); + + gp_Ax2 axis(center, N_dir, x_dir); + + if(curve_type == HYPERBOLA_CURVE_TYPE) + { + // (focus2) (v3) . (v2) + // . . . (midpoint = focus1) + // . (v1) + CubitVector focus2 = 2 * v3 - midpoint_vec; + + //according to the definition of hyperbola, + //2 * a = length(v2 - focus2)-length(v2 - focus1) + + double major = (v2 - focus2).length()/2.0 - (v2 - midpoint_vec).length()/2.0; + + // if a = 1/2 length major axis, b = 1/2 length minor axis and + // c = distance center to focus, then a*a + b*b = c*c + + double c_squared = (midpoint_vec - v3).length_squared(); + double minor = sqrt(c_squared - major*major ); + gp_Hypr hypt(axis, major, minor); + curve_ptr = + GC_MakeArcOfHyperbola(hypt, pt1, pt2, CUBIT_TRUE); + } + + else + { + // Find the focus of this parabola. + // Since for a parabola with its peak at the origin, y = (1/(4*a))*x^2, + // and since we have restricted this parabola to be symmetric (per the + // FastQ method, see the FastQ file getwt.f), we can use the following + // relationship to + // determine "a", the distance the focus lies from the peak on the line + // formed by the peak and the midpoint of the start and end points` + double a = width_vec.length_squared()/(16. * height_vec.length()); + gp_Parab parab(axis, a); + curve_ptr = + GC_MakeArcOfParabola(parab, pt1, pt2, CUBIT_TRUE); + } + } + + else + { + PRINT_ERROR("In OCCModifyEngine::make_Curve\n" + " Invalid curve type.\n"); + return (Curve *)NULL; + } + + OCCPoint* occ_pt1 = CAST_TO(const_cast<Point*>(point1_ptr),OCCPoint); + OCCPoint* occ_pt2 = CAST_TO(const_cast<Point*>(point2_ptr),OCCPoint); + TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex(); + TopoDS_Vertex * vt2 = occ_pt2->get_TopoDS_Vertex(); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt2); + return OCCQueryEngine::instance()->populate_topology_bridge(new_edge); +} + +//=============================================================================== +// Function : make_Surface +// This function creates a surface given an existing surface, copy. +// Member Type: PUBLIC +// Description: make a surface, OCC allows to create a stand along surface, +// however the CGM has a design of making all surfaces in a (sheet) +// body. This will add complexity on all free surface related +// calculation and modification, and adding potential bugs too. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +Surface* OCCModifyEngine::make_Surface( Surface * surface_ptr, + CubitBoolean extended_from) const +{ + OCCSurface* occ_surface = CAST_TO(surface_ptr, OCCSurface); + if (!occ_surface) + { + PRINT_ERROR("Cannot create an OCC surface from the given surface.\n" + "Possible incompatible geometry engines.\n"); + return (Surface *)NULL; + } + + //Start of the codes + double UMax, VMax, UMin, VMin; + occ_surface->get_param_range_U(UMin, UMax); + occ_surface->get_param_range_V(VMin, VMax); + + TopoDS_Face *theFace = occ_surface->get_TopoDS_Face(); + if( !theFace) + { + PRINT_ERROR("Cannot create an OCC surface from the given surface.\n" + "Possible incompatible geometry engines.\n"); + return (Surface *)NULL; + } + + TopoDS_Face newFace; + BRepAdaptor_Surface asurface(*theFace); + + CubitBox bounding_box = GeometryQueryTool::instance()->model_bounding_box(); + double const height = 2*(bounding_box.diagonal()).length(); + CubitBox box = occ_surface->bounding_box(); + double ratio = height/(box.diagonal().length()); + + double middleU = (UMin + UMax)/2.0; + double middleV = (VMin + VMax)/2.0; + double U1 = middleU - (UMax-UMin)/2.0 * ratio; + double U2 = middleU + (UMax-UMin)/2.0 * ratio; + double V1 = middleV - (VMax - VMin)/2.0 * ratio; + double V2 = middleV + (VMax - VMin)/2.0 * ratio; + + if (extended_from == CUBIT_TRUE) + { + // We need to get the type of surface. + GeometryType type = occ_surface->geometry_type(); + if (type == PLANE_SURFACE_TYPE) + { + gp_Pln plane = asurface.Plane(); + newFace = BRepBuilderAPI_MakeFace(plane, U1, U2, V1, V2); + } + else if(type == CONE_SURFACE_TYPE) + { + //make an infinite cone. + //Given this lets create another face that is extended from it. + if(asurface.GetType() == GeomAbs_Cone) + { + gp_Cone cone = asurface.Cone(); + gp_Pnt Apex = cone.Apex(); + double semi_angle = cone.SemiAngle(); + gp_Pnt p2; + double radius2; + gp_XYZ xyz; + if (semi_angle > 0) + xyz = Apex.XYZ() + cone.Position().Direction().XYZ()*height; + + else + xyz = Apex.XYZ() - cone.Position().Direction().XYZ()*height; + + p2.SetXYZ(xyz); + radius2 = height * tan(fabs(semi_angle)); + Handle(Geom_RectangularTrimmedSurface) trimmed_cone; + trimmed_cone = GC_MakeTrimmedCone(Apex, p2, 0, radius2); + newFace = BRepBuilderAPI_MakeFace(trimmed_cone); + } + else + { + gp_Cylinder cylinder = asurface.Cylinder(); + //gp_Pnt pnt = asurface.Value(UMin,V1); + double radius = cylinder.Radius(); + gp_Ax1 axis = cylinder.Axis(); + Handle(Geom_RectangularTrimmedSurface) trimmed_cyl; + trimmed_cyl = GC_MakeTrimmedCylinder(axis, radius, height); + newFace = BRepBuilderAPI_MakeFace(trimmed_cyl); + } + } + else if(type == SPHERE_SURFACE_TYPE) + { + //make a whole sphere. + gp_Sphere sphere = asurface.Sphere(); + newFace = BRepBuilderAPI_MakeFace(sphere); + } + else if(type == TORUS_SURFACE_TYPE) + { + //make a whole torus + gp_Torus torus = asurface.Torus(); + newFace = BRepBuilderAPI_MakeFace(torus); + } + else if(type == SPLINE_SURFACE_TYPE ) + { + //extend the surfaces using the equation if possible. + Handle(Geom_BezierSurface) bezier = asurface.Bezier(); + newFace = BRepBuilderAPI_MakeFace(bezier, U1, U2, V1, V2); + } + } + + else + { + BRepBuilderAPI_Copy api_copy(*theFace); + TopoDS_Shape newShape = api_copy.ModifiedShape(*theFace); + newFace = TopoDS::Face(newShape); + } + + Surface *surface = OCCQueryEngine::instance()->populate_topology_bridge( + newFace, CUBIT_TRUE); + + return surface; +} + +//=============================================================================== +// Function : make_Surface +// Member Type: PUBLIC +// Description: make a surface of type surface_type, given the list of curves. +// check edges option is done in GeometryModifyTool level, so +// disregard this option. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +Surface* OCCModifyEngine::make_Surface( GeometryType surface_type, + DLIList<Curve*>& curve_list, + Surface * old_surface_ptr, + bool check_edges) const +{ + //Create TopoDS_Edge list to make a surface. + DLIList<DLIList<TopoDS_Edge*>*> topo_edges_loops; + curve_list.reset() ; + + //check no intersections of the TopoDS_Edge's. + //need to check that no intersection in the middle of the curves, not at + //vertices or out of boundary. + + int count = 0; //intersection point should be the same as curve_list size. + for ( int i = 0 ; i < curve_list.size()-1 ; i++ ) + { + for(int j = i+1; j < curve_list.size(); j ++) + { + DLIList<CubitVector*> intscts; + CubitBoolean bounded = CUBIT_TRUE;//dummy arg. + CubitBoolean closest = CUBIT_TRUE;//dummy arg. + CubitStatus yes_int = + OCCQueryEngine::instance()->get_intersections(curve_list[i], + curve_list[j], intscts, bounded, closest); + if(yes_int) + { + //check intscts point should be vertex or outside boundary. + if (intscts.size() > 2 ) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface with intersecting curves.\n"); + return (Surface *)NULL; + } + else + { + for(int k = 0; k < intscts.size(); k++) + { + CubitVector *v = intscts.get_and_step(); + CubitPointContainment is_on = CAST_TO(curve_list[i],OCCCurve)-> + point_containment(*v); + if (is_on == CUBIT_PNT_BOUNDARY) + { + is_on = CAST_TO(curve_list[j],OCCCurve)-> + point_containment(*v); + if (is_on == CUBIT_PNT_BOUNDARY) + count++; + } + else if(is_on == CUBIT_PNT_INSIDE) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface with intersecting curves.\n"); + return (Surface *)NULL; + } + } + } + } + } + } + + if (count > curve_list.size()) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface with intersecting curves.\n"); + return (Surface *)NULL; + } + + CubitStatus stat = sort_curves(curve_list, topo_edges_loops); + if( stat == CUBIT_FAILURE ) //case of one disconnected curve + return (Surface*) NULL; + + // Use the topo_edges to make a topo_face + TopoDS_Face* topo_face; + topo_face = make_TopoDS_Face(surface_type,topo_edges_loops, old_surface_ptr); + + for (int i = 0; i < topo_edges_loops.size(); i++) + { + DLIList<TopoDS_Edge*>* topo_edges = topo_edges_loops.get_and_step(); + for(int j = 0; j < topo_edges->size(); j++) + topo_edges->pop(); + delete topo_edges; + } + + if(!topo_face) + { + PRINT_ERROR("In OCCModifyEngine::make_Surface\n" + " Cannot make Surface object.\n"); + return (Surface *)NULL; + } + + // make the topology bridges for the face + Surface *surface = OCCQueryEngine::instance()->populate_topology_bridge( + *topo_face, CUBIT_TRUE); + topo_face->Nullify(); + delete topo_face; + return surface ; +} + +//=============================================================================== +// Function : sort_curves +// Member Type: PROTECTED +// Description: sort the curves so they are in order and make closed loop +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::sort_curves(DLIList<Curve*> curve_list, + DLIList<DLIList<TopoDS_Edge*>*>& topo_edges_loops)const +{ + topo_edges_loops.clean_out(); + CubitStatus stat = CUBIT_SUCCESS; + std::vector< DLIList<TopoDS_Edge*>* > topo_edges(curve_list.size()); + int size_in = curve_list.size(); + for(int i = 0; i < size_in; i++) + topo_edges[i] = new DLIList<TopoDS_Edge*>; + + curve_list.reset() ; + Curve const* curve_ptr = NULL ; + OCCCurve* occ_curve = NULL; + TopoDS_Edge* topo_edge = NULL; + + OCCPoint* start = NULL; + OCCPoint* end = NULL; + DLIList<OCCPoint*> point_list; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + CubitBoolean new_end; + int size = curve_list.size(); + + int count = 0; + for ( int i = 0 ; i < size ; i++ ) + { + if (i == 0) + new_end = CUBIT_TRUE; + for(int j = 0; j < curve_list.size(); j ++) + { + curve_ptr = curve_list.get() ; + occ_curve = CAST_TO(const_cast<Curve*>(curve_ptr), OCCCurve); + + if(occ_curve == NULL) + { + PRINT_ERROR("In OCCModifyEngine::sort_curves\n" + " Got a NULL pointer to OCCCurve\n") ; + return CUBIT_FAILURE; + } + + point_list.clean_out(); + occ_curve->get_points(point_list); + //assert(point_list.size()==2); + + if (i == 0) + { + start = point_list.get(); + end = point_list.pop(); + break; + } + + if(end->is_equal(*(point_list.get()), tol) || + end->is_equal(*(point_list.step_and_get()),tol)) + { + end = point_list.step_and_get(); + new_end = CUBIT_TRUE; + break; + } + + else if(start->is_equal(*(point_list.get()), tol) || + start->is_equal(*(point_list.step_and_get()),tol)) + { + start = end; + end = point_list.step_and_get(); + new_end = CUBIT_TRUE; + break; + } + curve_list.step(); + } + + if (new_end)//found next curve + { + topo_edge = occ_curve->get_TopoDS_Edge(); + topo_edges[count]->append(topo_edge); + curve_list.remove(); + if(start->is_equal( *end, tol)) //formed a closed loop + { + i = -1; + size = curve_list.size() ; + topo_edges_loops.append(topo_edges[count]); + count++; + } + else + new_end = CUBIT_FALSE; + } + else + { + stat = CUBIT_FAILURE; + i = -1; + size = curve_list.size(); + topo_edges_loops.append(topo_edges[count]); + count++; + } + } + + if( new_end == CUBIT_FALSE ) //case of one disconnected curve + { + topo_edges_loops.append(topo_edges[count]); + stat = CUBIT_FAILURE; + } + + for(int i = 0; i < size_in; i++) + { + if(topo_edges[i]->size() == 0) + delete topo_edges[i]; + } + return stat; +} +//=============================================================================== +// Function : make_TopoDS_Face +// Member Type: PROTECTED +// Description: make a opoDS_Face of type surface_type, given the list of +// TopoDS_Edge. the TopoDS_Edge's should be in order in loops. +// check edges option is done in GeometryModifyTool level, so +// disregard this option. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +TopoDS_Face* OCCModifyEngine::make_TopoDS_Face(GeometryType surface_type, + DLIList<DLIList<TopoDS_Edge*>*> topo_edges_list, + Surface * old_surface_ptr)const +{ + TopoDS_Face* topo_face = NULL; + // Make sure a supported type of surface is being requested. + if ( surface_type != PLANE_SURFACE_TYPE && + surface_type != BEST_FIT_SURFACE_TYPE) + { + PRINT_WARNING("In OCCGeometryEngine::make_TopoDS_Face\n" + " At this time, cannot make a TopoDS_Face that isn't" + " planar or best fit.\n"); + return topo_face; + } + + // Set the TopoDS_Face pointer, if requested. + TopoDS_Face *fit_Face = NULL; + Handle_Geom_Surface S; + if ( old_surface_ptr != NULL ) + { + OCCSurface *surf = CAST_TO(old_surface_ptr, OCCSurface ); + fit_Face = surf->get_TopoDS_Face(); + S = BRep_Tool::Surface(*fit_Face); + } + + // Make a wire from the topo_edges. + // Coincident TopoDS_Vertex will be deleted by OCC. + if(topo_edges_list.size() == 0) + return topo_face; + + DLIList<TopoDS_Wire*> wires; + GProp_GProps myProps; + double max_area = 0.0; + TopoDS_Wire* out_Wire = NULL; + TopoDS_Wire test_Wire; + DLIList<TopoDS_Edge*>* topo_edges; + //check and make sure the outer loop is in the first + for(int i = 0; i < topo_edges_list.size() ; i++) + { + topo_edges = topo_edges_list.get_and_step(); + BRepBuilderAPI_MakeWire aWire(*(topo_edges->get())); + for(int j = 1; j < topo_edges->size(); j++) + aWire.Add(*(topo_edges->step_and_get())); + + test_Wire = aWire.Wire(); + wires.append(&test_Wire); + + if (topo_edges_list.size() == 1) + break; + + BRepBuilderAPI_MakeFace made_face(test_Wire); + + if (!made_face.IsDone()) + { + PRINT_ERROR("In OCCModifyEngine::make_TopoDS_Face\n" + " Cannot find the best fit surface for given curves.\n"); + return topo_face; + } + TopoDS_Face test_face = made_face.Face(); + BRepGProp::SurfaceProperties(test_face, myProps); + double area = myProps.Mass(); + out_Wire = max_area > area ? out_Wire : &test_Wire; + max_area = max_area > area ? max_area : area; + } + + if (out_Wire) + { + wires.remove(out_Wire); + wires.insert_first(out_Wire); + } + + //create the TopoDS_Face + CubitBoolean error = CUBIT_FALSE; + + for(int i = 0; i < topo_edges_list.size() ; i++) + { + TopoDS_Wire *the_wire = wires.get_and_step(); + if (i == 0) + { + if( old_surface_ptr != NULL ) + { + BRepBuilderAPI_MakeFace made_face(S, *the_wire); + if (!made_face.IsDone()) + { + error = CUBIT_TRUE; + break; + } + topo_face = new TopoDS_Face(made_face.Face()); + } + else + { + CubitBoolean is_planar = (surface_type == PLANE_SURFACE_TYPE ? + CUBIT_TRUE : CUBIT_FALSE); + BRepBuilderAPI_MakeFace made_face(*the_wire, is_planar); + if (!made_face.IsDone()) + { + error = CUBIT_TRUE; + break; + } + + topo_face = new TopoDS_Face(made_face.Face()); + } + } + else + { + BRepBuilderAPI_MakeFace made_face(*topo_face, *the_wire); + if (!made_face.IsDone()) + { + error = CUBIT_TRUE; + break; + } + delete topo_face; + topo_face = new TopoDS_Face(made_face.Face()); + } + } + + if(error) + { + PRINT_ERROR("In OCCModifyEngine::make_TopoDS_Face\n" + " Cannot find the best fit surface for given curves.\n"); + return (TopoDS_Face*) NULL; + } + + return topo_face; +} +//=============================================================================== +// Function : make_Lump +// Member Type: PUBLIC +// Description: make a lump of one shell +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +Lump* OCCModifyEngine::make_Lump( DLIList<Surface*>& surface_list ) const +{ + if (surface_list.size() < 2) + return (Lump*) NULL; + + //all surfaces should be stand along surface bodies or shell bodies' surface + DLIList<BodySM*> body_list; + for(int i = 0; i < surface_list.size(); i++) + { + OCCSurface* occ_surface = CAST_TO(surface_list.get_and_step(), OCCSurface); + if (occ_surface == NULL) + { + PRINT_ERROR("Cannot create an OCC lump from the given surfaces.\n" + "Possible incompatible geometry engines.\n"); + return (Lump *)NULL; + } + OCCBody* occ_body = occ_surface->my_body(); + if(occ_body && occ_body->my_sheet_surface() == NULL) + { + PRINT_ERROR("Cannot create an OCC lump from the given surfaces.\n" + "The surfaces are not free.\n"); + return (Lump *)NULL; + } + else if(!occ_body) + { + OCCShell* shell = occ_surface->my_shell(); + if(!shell) + { + PRINT_ERROR("This is a bug, please report it. \n"); + return (Lump*)NULL; + } + occ_body = shell->my_body(); + } + body_list.append_unique(occ_body); + } + + TopoDS_Shape aShape; + CubitStatus stat = stitch_surfs(body_list, aShape); + if(!stat) + { + PRINT_ERROR("The surfaces are not all connected, can't make a lump. \n"); + return (Lump*)NULL; + } + + TopExp_Explorer Ex, Ex2; + TopoDS_Shell aShell ; + for (Ex.Init(aShape, TopAbs_SHELL, TopAbs_SOLID); Ex.More()&& stat; Ex.Next()) + aShell = TopoDS::Shell(Ex.Current()); + + //check to make sure the aShell is closed. + int num_edges = 0; + int pairs = 0; + //sometimes there's duplicate TopoDS_Edges in the shell. + DLIList<TopoDS_Edge*> edge_list; + for (Ex.Init(aShell, TopAbs_EDGE); Ex.More()&& stat; Ex.Next()) + { + TopoDS_Edge edge1 = TopoDS::Edge(Ex.Current()); + TopoDS_Edge* new_edge = new TopoDS_Edge(edge1); + edge_list.append(new_edge); + } + + int size = edge_list.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Edge edge1 = *edge_list[i]; + int same = 0; + for (int j = i+1; j < edge_list.size(); j++) + { + TopoDS_Edge edge2 = *edge_list[j]; + if(edge1.IsEqual(edge2)) + { + same ++; + edge_list.remove(&edge1); + i--; + size--; + break; + } + } + if(same > 0) + continue; + + else + num_edges++; + + for (int j = 0; j < size; j++) + { + TopoDS_Edge edge2 = *edge_list[j]; + if (!edge1.IsEqual(edge2)&& edge1.IsSame(edge2)) + { + pairs++; + break; + } + } + } + + for (int k = 0; k < edge_list.size(); k++) + { + TopoDS_Edge* edge = edge_list.get_and_step(); + edge->Nullify(); + delete edge; + } + + if (num_edges == pairs ) + aShell.Closed(CUBIT_TRUE); + + else + PRINT_ERROR("Surfaces must make a water-tight shape to make a lump.\n"); + + if(aShell.Closed()) + { + BRepBuilderAPI_MakeSolid aMakeSolid(aShell); + if (!aMakeSolid.IsDone()) + { + PRINT_ERROR("Cannot create an OCC Lump from the given surfaces.\n" + "OCC internal error.\n"); + return (Lump *)NULL; + } + + TopoDS_Solid aSolid = aMakeSolid.Solid(); + + return + OCCQueryEngine::instance()->populate_topology_bridge(aSolid, CUBIT_TRUE); + } + + return (Lump*) NULL; +} + +//=============================================================================== +// Function : make_BodySM +// Member Type: PUBLIC +// Description: make a BodySM from a surface +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +BodySM* OCCModifyEngine::make_BodySM( Surface *surface ) const +{ + OCCSurface* occ_surface = CAST_TO(surface, OCCSurface); + if(!occ_surface) + { + PRINT_ERROR("Cannot create an OCC body from the given surface.\n" + "Possible incompatible geometry engines.\n"); + return (BodySM *)NULL; + } + + OCCBody* occ_body = occ_surface->my_body(); + if(occ_body) + return occ_body; + + TopoDS_Face* face = occ_surface->get_TopoDS_Face(); + surface = OCCQueryEngine::instance()->populate_topology_bridge(*face, CUBIT_TRUE); + + return CAST_TO(surface, OCCSurface)->my_body(); +} + + + +//=============================================================================== +// Function : make_BodySM +// Member Type: PUBLIC +// Description: make a BodySM given a list of Lumps. +// Author : Jane Hu +// Date : 02/08 +//=============================================================================== +BodySM* OCCModifyEngine::make_BodySM( DLIList<Lump*>& lump_list ) const +{ + if (lump_list.size() == 0) + return (BodySM*) NULL; + + //Create a compsolid shape, copy all BodySM's solids to create new compbody + DLIList<BodySM*> bodysm_list; + TopoDS_CompSolid CS; + BRep_Builder B; + B.MakeCompSolid(CS); + + //Add every shape to the CompSolid + for(int i = 0; i < lump_list.size(); i++) + { + Lump* lump = lump_list.get_and_step(); + OCCLump* occ_lump = CAST_TO(lump, OCCLump); + if(!occ_lump) + { + PRINT_ERROR("Cannot create an OCC BodySM from the given lumps.\n" + "Possible incompatible geometry engines.\n"); + return (BodySM *)NULL; + } + TopoDS_Solid* solid = occ_lump->get_TopoDS_Solid(); + BRepBuilderAPI_Copy api_copy(*solid); + TopoDS_Shape newShape = api_copy.ModifiedShape(*solid); + B.Add(CS, newShape); + } + + BodySM* bodysm = OCCQueryEngine::instance()->populate_topology_bridge(CS); + + return bodysm; + +} + + +//=============================================================================== +// Function : sphere +// Member Type: PUBLIC +// Description: build an OCC sphere +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::sphere(double radius) const +{ + if (radius <= 0) + return (BodySM*) NULL; + + TopoDS_Solid S = BRepPrimAPI_MakeSphere(radius); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + if (lump == NULL) + return (BodySM*)NULL; + + return CAST_TO(lump, OCCLump)->get_body(); +} + + +//=============================================================================== +// Function : brick +// Member Type: PUBLIC +// Description: build an OCC brick +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::brick( double wid, double dep, double hi ) const +{ + if (wid <= 0 || dep <=0 || hi <= 0) + return (BodySM*)NULL; + + TopoDS_Solid S = BRepPrimAPI_MakeBox(wid, dep, hi); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + + if (lump == NULL) + return (BodySM*)NULL; + + BodySM* body = CAST_TO(lump, OCCLump)->get_body(); + if(body) + CAST_TO(body,OCCBody)->move(-wid/2.0, -dep/2.0, -hi/2.0); + return body; +} + + +//=============================================================================== +// Function : brick +// Member Type: PUBLIC +// Description: create an OCC brick given center axes and extension +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::brick( const CubitVector& center, + const CubitVector axes[3], + const CubitVector &extension) const +{ + CubitVector left_corner = center - 0.5 * extension; + gp_Pnt left_point(left_corner.x(), left_corner.y(), left_corner.z()); + gp_Dir main_dir(axes[2].x(), axes[2].y(), axes[2].z()); + gp_Dir x_dir(axes[0].x(), axes[0].y(), axes[0].z()); + gp_Ax2 Axis(left_point, main_dir, x_dir); + TopoDS_Solid S = BRepPrimAPI_MakeBox( Axis, extension.x(), extension.y(), + extension.z()); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + if (lump == NULL) + return (BodySM*)NULL; + + return CAST_TO(lump, OCCLump)->get_body(); +} + +//=============================================================================== +// Function : prism +// Member Type: PUBLIC +// Description: create an OCC prism +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::prism( double height, int sides, double major, + double minor) const +{ + //currently OCC only support 4 sided prism + if (sides != 4) + { + PRINT_ERROR("Option not supported for OCC based geometry.\n"); + return (BodySM*) NULL; + } + + return brick(2 * major, 2 * minor, height); +} + +//=============================================================================== +// Function : pyramid +// Member Type: PUBLIC +// Description: create an OCC pyramid +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::pyramid( double height, int sides, double major, + double minor, double top) const +{ + //currently OCC only support 4 sided pyramid + if (sides != 4) + { + PRINT_ERROR("Option not supported for OCC based geometry.\n"); + return (BodySM*) NULL; + } + + TopoDS_Solid S = BRepPrimAPI_MakeWedge( 2 * major, 2* minor, height, + 2 * top); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + if (lump == NULL) + return (BodySM*)NULL; + + BodySM* body = CAST_TO(lump, OCCLump)->get_body(); + if(body) + CAST_TO(body, OCCBody)->move(-major, -minor, -height/2.0); + return body; + +} + +//=============================================================================== +// Function : cylinder +// Member Type: PUBLIC +// Description: create an OCC cylinder, its base shape can be ellipse with +// r1, r2 while r3 = 0; or it can be a cone with r1, +// r3 while r2 = 0. +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::cylinder( double hi, double r1, double r2, double r3 ) const +{ + TopoDS_Solid S; + if(r2 != r1)//elliptical based cylinder + { + gp_Pnt center(0.0, 0.0, 0.0); + gp_Dir main_dir(0.0, 0.0, 1.0); + gp_Dir x_dir(1.0, 0.0, 0.0); + gp_Ax2 Axis(center, main_dir, x_dir); + Handle(Geom_Curve) curve_ptr = GC_MakeEllipse(Axis, r1, r2); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr); + BRepBuilderAPI_MakeWire aWire(new_edge); + + TopoDS_Wire test_Wire = aWire.Wire(); + + BRepOffsetAPI_ThruSections builder(CUBIT_TRUE, CUBIT_TRUE); + builder.AddWire(test_Wire); + if (r3 == 0) + { + gp_Pnt pt = gp_Pnt( 0.0, 0.0, hi); + TopoDS_Vertex theVertex = BRepBuilderAPI_MakeVertex(pt); + builder.AddVertex(theVertex); + } + else + { + gp_Pnt center2(0.0, 0.0,hi); + gp_Ax2 Axis2(center2, main_dir, x_dir); + Handle(Geom_Curve) curve_ptr = GC_MakeEllipse(Axis2, r3, r3*r2/r1); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr); + BRepBuilderAPI_MakeWire aWire(new_edge); + TopoDS_Wire test_Wire = aWire.Wire(); + builder.AddWire(test_Wire); + } + builder.Build() ; + S = TopoDS::Solid(builder.Shape()); + } + + else // cone + { + if(r1 == r3) //cylinder + S = BRepPrimAPI_MakeCylinder(r1, hi); + else + S = BRepPrimAPI_MakeCone(r1, r3, hi); + } + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + + if (lump == NULL) + { + PRINT_ERROR("In OCCModifyEngine::cylinder\n" + " Cannot create a cylinder for given radii.\n"); + return (BodySM*)NULL; + } + + BodySM* body = CAST_TO(lump, OCCLump)->get_body(); + if(body) + CAST_TO(body, OCCBody)->move(0, 0, -hi/2.0); + return body; +} + +//=============================================================================== +// Function : torus +// Member Type: PUBLIC +// Description: create an OCC torus +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::torus( double r1, double r2 ) const +{ + if (r1 <= 0 || r2 <= 0) + return (BodySM*) NULL; + + TopoDS_Solid S = BRepPrimAPI_MakeTorus(r1, r2); + + Lump* lump = OCCQueryEngine::instance()->populate_topology_bridge(S, + CUBIT_TRUE); + + if (lump == NULL) + { + PRINT_ERROR("In OCCModifyEngine::torus\n" + " Cannot create a torus for given radii.\n"); + return (BodySM*)NULL; + } + + return CAST_TO(lump, OCCLump)->get_body(); +} + +//=============================================================================== +// Function : planar_sheet +// Member Type: PUBLIC +// Description: create an OCC planar_sheet with four vectors. +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::planar_sheet ( const CubitVector& p1, + const CubitVector& p2, + const CubitVector& p3, + const CubitVector& p4) const +{ + Point* point1 = make_Point(p1); + Point* point2 = make_Point(p2); + Point* point3 = make_Point(p3); + Point* point4 = make_Point(p4); + Curve * curve1 = make_Curve( point1, point2); + if (curve1 == NULL) + return (BodySM*) NULL; + Curve * curve2 = make_Curve( point2, point3); + if (curve2 == NULL) + return (BodySM*) NULL; + Curve * curve3 = make_Curve( point3, point4); + if (curve3 == NULL) + return (BodySM*) NULL; + Curve * curve4 = make_Curve( point4, point1); + if (curve4 == NULL) + return (BodySM*) NULL; + DLIList<Curve*> curves; + curves.append(curve1); + curves.append(curve2); + curves.append(curve3); + curves.append(curve4); + Surface* surface = make_Surface(PLANE_SURFACE_TYPE, curves); + if (surface == NULL) + return (BodySM*) NULL; + return CAST_TO(surface,OCCSurface)->my_body(); +} + +//=============================================================================== +// Function : copy_body +// Member Type: PUBLIC +// Description: copy an OCC-based body +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +BodySM* OCCModifyEngine::copy_body ( BodySM* bodyPtr ) const +{ + OCCBody* occ_body = CAST_TO(bodyPtr, OCCBody); + if (!occ_body) + { + PRINT_ERROR("Cannot create an OCC bodySM from the given bodySM.\n" + "Possible incompatible geometry engines.\n"); + return (BodySM *)NULL; + } + + TopoDS_CompSolid *theCS = occ_body->get_TopoDS_Shape(); + + if (theCS == NULL) //sheet body + { + OCCShell* occ_shell = occ_body->shell(); + if (occ_shell != NULL) + { + TopoDS_Shell* shell = occ_shell->get_TopoDS_Shell(); + BRepBuilderAPI_Copy api_copy(*shell); + TopoDS_Shape newShape = api_copy.ModifiedShape(*shell); + TopoDS_Shell newShell = TopoDS::Shell(newShape); + return OCCQueryEngine::instance()->populate_topology_bridge(newShell, CUBIT_TRUE)->my_body(); + } + + Surface* surface = make_Surface(occ_body->my_sheet_surface()); + if (surface == NULL) + { + PRINT_ERROR("Cannot create an OCC sheet bodySM from the given bodySM.\n"); + return (BodySM *)NULL; + } + + return CAST_TO(surface,OCCSurface)->my_body(); + } + + if(OCCQueryEngine::instance()->OCCMap->IsBound(*theCS)) + { + BRepBuilderAPI_Copy api_copy(*theCS); + + TopoDS_Shape newShape = api_copy.ModifiedShape(*theCS); + + TopoDS_CompSolid newCS = TopoDS::CompSolid(newShape); + + return OCCQueryEngine::instance()->populate_topology_bridge(newCS); + } + + //single lump body + Lump *lump = occ_body->lumps().get(); + TopoDS_Solid solid = *(CAST_TO(lump, OCCLump)->get_TopoDS_Solid()); + BRepBuilderAPI_Copy api_copy(solid); + TopoDS_Shape newShape = api_copy.ModifiedShape(solid); + TopoDS_Solid newSolid = TopoDS::Solid(newShape); + lump = OCCQueryEngine::instance()->populate_topology_bridge(newSolid, + CUBIT_TRUE); + + return CAST_TO(lump, OCCLump)->get_body(); +} + +//=============================================================================== +// Function : stitch_surfs +// Member Type: PUBLIC +// Description: stitch all surfs and try to make a shell body. +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::stitch_surfs( + DLIList<BodySM*>& surf_bodies, + BodySM*& new_body) const +{ + new_body = NULL; + if (surf_bodies.size()==0) + return CUBIT_SUCCESS; + + if (surf_bodies.size()==1) + { + new_body = surf_bodies.get(); + return CUBIT_SUCCESS; + } + + TopoDS_Shape fuse; + CubitStatus stat = stitch_surfs(surf_bodies, fuse); + + DLIList<TopologyBridge*> tbs = OCCQueryEngine::instance()-> + populate_topology_bridge(fuse); + + if (stat) + { + OCCBody* body = CAST_TO(tbs.get(), OCCBody); + + if (body) + new_body = body ; + } + + else + { + surf_bodies.clean_out(); + for(int i= 0; i<tbs.size(); i++) + surf_bodies.append(CAST_TO(tbs.get_and_step(), OCCBody)); + } + + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : stitch_surfs +// Member Type: PUBLIC +// Description: stitch all surfs and try to make a TopoDS_Shell . +// called by stitch into surface body +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::stitch_surfs( + DLIList<BodySM*>& surf_bodies, + TopoDS_Shape& fuse) const +{ + if (surf_bodies.size() < 2) + return CUBIT_SUCCESS; + + DLIList<TopoDS_Shape*> faces_to_stitch; + for (int i = 0; i < surf_bodies.size(); i++) + { + BodySM * tool_body = surf_bodies.get_and_step(); + OCCBody* occ_body = CAST_TO(tool_body, OCCBody); + OCCSurface* surface = occ_body->my_sheet_surface(); + OCCShell* shell = occ_body->shell(); + if (surface == NULL && shell == NULL) + { + PRINT_ERROR("Can't stitch non-sheet bodySM's. \n"); + return CUBIT_FAILURE; + } + + delete occ_body; + if (surface) + { + delete surface->my_shell(); + delete surface->my_lump(); + surface->set_shell(NULL); + surface->set_lump(NULL); + surface->set_body(NULL); + + TopoDS_Face* topods_face = surface->get_TopoDS_Face(); + if (topods_face != NULL) + faces_to_stitch.append(topods_face); + } + else + { + delete shell->my_lump(); + shell->set_body(NULL); + shell->set_lump(NULL); + + TopoDS_Shell* topods_shell = shell->get_TopoDS_Shell(); + if(topods_shell) + faces_to_stitch.append(topods_shell); + } + } + + faces_to_stitch.reset(); + surf_bodies.reset(); + TopoDS_Shape* first_face = faces_to_stitch.pop(); + + TopoDS_Shape* second_face = NULL; + for( int i = faces_to_stitch.size()-1; i >= 0; i --) + { + second_face = faces_to_stitch[i]; + BRepAlgoAPI_Fuse fuser(*second_face, *first_face); + + TopoDS_Shape new_shape ; + for(int j = 0; j < 2; j++) + { + TopTools_IndexedMapOfShape M; + if(j == 0) + TopExp::MapShapes(*second_face, TopAbs_FACE, M); + else + TopExp::MapShapes(*first_face, TopAbs_FACE, M); + for(int ii=1; ii<=M.Extent(); ii++) + { + TopoDS_Face face = TopoDS::Face(M(ii)); + TopTools_ListOfShape shapes; + shapes.Assign(fuser.Modified(face)); + if (shapes.Extent() == 1) + { + new_shape = shapes.First(); + OCCSurface::update_OCC_entity(face, TopoDS::Face(new_shape), &fuser); + } + else if(fuser.IsDeleted(face) || shapes.Extent() > 1) + { + TopoDS_Face null_face; + OCCSurface::update_OCC_entity(face, null_face, &fuser); + } + } + } + + fuse = fuser.Shape(); + first_face = &fuse; + } + + TopExp_Explorer Ex; + int count_shell = 0; + for (Ex.Init(fuse, TopAbs_SHELL, TopAbs_SOLID); Ex.More(); Ex.Next()) + count_shell++; + + if ( count_shell != 1) + { + PRINT_ERROR("Can't stitch all surfaces into one BodySM's. \n"); + return CUBIT_FAILURE; + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : subtract +// Member Type: PUBLIC +// Description: subtract boolean operation on OCC-based bodies +// Author : Jane Hu +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::subtract(DLIList<BodySM*> &tool_body_list, + DLIList<BodySM*> &from_bodies, + DLIList<BodySM*> &new_bodies, + bool imprint, + bool keep_old) const +{ + // copy the bodies in case keep_old is true + DLIList<TopoDS_Shape*> tool_bodies_copy; + + //for subtract function, tool-body has to be solid, + //otherwise it's just imprint + DLIList<CubitBox*>* tool_boxes = new DLIList<CubitBox*>(); + DLIList<CubitBoolean> is_tool_volume; + //keep the tool_body untouched + CubitStatus stat = + get_shape_list(tool_body_list, tool_bodies_copy, is_tool_volume, CUBIT_TRUE, tool_boxes); + + if(!stat) + return stat; + + //check that tool_bodies are all solid, shell and surface body can't be used + //for subtracting purpose. + if(is_tool_volume.is_in_list(CUBIT_FALSE)) + { + PRINT_WARNING("Surfaces or Shells can't be used to cut a body.\n"); + while (tool_boxes->size()) + delete tool_boxes->pop(); + delete tool_boxes; + while (tool_bodies_copy.size()) + delete tool_bodies_copy.pop(); + return CUBIT_FAILURE; + } + + stat = do_subtract(from_bodies, tool_bodies_copy, is_tool_volume, + tool_boxes, new_bodies, keep_old, imprint) ; + + //ok, we're done wih all cuts, delete unnecessaries. + while (tool_boxes->size()) + delete tool_boxes->pop(); + delete tool_boxes; + while (tool_bodies_copy.size()) + delete tool_bodies_copy.pop(); + if(!keep_old) //delete tool_bodies + OCCQueryEngine::instance()->delete_solid_model_entities(tool_body_list); + return stat; +} + +CubitStatus OCCModifyEngine::do_subtract(DLIList<BodySM*> &from_bodies, + DLIList<TopoDS_Shape*> &tool_bodies_copy, + DLIList<CubitBoolean> &is_tool_volume, + DLIList<CubitBox*>* tool_boxes, + DLIList<BodySM*> &new_bodies, + bool keep_old, + bool imprint) const +{ + DLIList<TopoDS_Shape*> from_bodies_copy; + DLIList<CubitBoolean> is_volume; + //get the from_bodies underling shapes + CubitStatus stat = get_shape_list(from_bodies, from_bodies_copy, is_volume, keep_old); + if(!stat) + { + for (int i = 0; i < tool_bodies_copy.size(); i++) + { + TopoDS_Shape* shape = tool_bodies_copy.get_and_step(); + delete shape; + } + tool_bodies_copy.clean_out(); + return CUBIT_FAILURE; + } + + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + int fraction_remaining = 100; + + // subtract the tool body from each body in the list + + CubitMessage* cmi = CubitMessage::instance(); + TopoDS_Shape* from_shape = from_bodies_copy.get(); + DLIList<TopologyBridge*> tbs; + for (int i = 0; i < from_bodies_copy.size(); i++) + { + BodySM* from_body = from_bodies.get(); + CubitBox box1 = CAST_TO(from_body, OCCBody)->get_bounding_box(); + int count = 0; //count for not preforming cut + for(int j = 0; j < tool_bodies_copy.size(); j ++) + { + if (cmi->Interrupt()) + { + PRINT_ERROR("Subtraction interrupted. Aborting...\n"); + while (tool_boxes->size()) + delete tool_boxes->pop(); + delete tool_boxes; + while (tool_bodies_copy.size()) + delete tool_bodies_copy.pop(); + while (from_bodies_copy.size()) + delete from_bodies_copy.pop(); + return CUBIT_FAILURE; + } + CubitBox tool_box = *tool_boxes->get_and_step(); + if(!tool_box.overlap(tol,box1)) + { + count++; + continue; + } + TopoDS_Shape* tool_shape = tool_bodies_copy.get_and_step(); + + //bodies overlap, proceed with the subtract + BRepAlgoAPI_Cut cutter(*from_shape, *tool_shape); + TopoDS_Shape cut_shape = cutter.Shape(); + + //compare to see if the from_shape has gotten cut. + CubitBoolean has_changed; + check_operation(cut_shape, from_shape, is_volume[i], has_changed, &cutter, keep_old); + + CubitStatus stat; + if(!has_changed && !from_shape->IsNull()) + { + stat = CUBIT_FAILURE; + //Add imprint code here + if(imprint) + stat = imprint_toposhapes(from_shape, tool_shape); + if(!stat) + { + PRINT_ERROR("Can't do imprint operation on the body. \n"); + count++; + } + continue; + } + } + + //ok, we're done with all cuts, construct new Body' + if (count < tool_bodies_copy.size() ) + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*from_shape); + else + { + PRINT_INFO("The %d body did not change because cutting tools are not interscting with it.\n", i+1); + from_bodies.change_to(NULL); + } + from_bodies.step(); + from_shape = from_bodies_copy.step_and_get(); + + // done with this j iteration; write out count, if necessary + if (from_bodies.size() * tool_bodies_copy.size() > 1) + { + int frac_done = (100 * (i+1)) / (from_bodies.size()); + if ((100 - frac_done) < fraction_remaining) + { + fraction_remaining = 100 - frac_done; + PRINT_INFO("%d%% remaining.\n ", fraction_remaining+1); + } + } + } + + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + new_bodies.append(bodysm); + } + + //ok, we're done wih all cuts, delete unnecessaries. + if(keep_old) + { + int size = from_bodies_copy.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Shape* shape = from_bodies_copy.pop(); + shape->Nullify(); + delete shape; + } + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : imprint_toposhapes +// Member Type: PROTECTED +// Description: imprint boolean operation on OCC-based bodies. +// from_shape must be TopoDS_Face or above, tool_shape can be +// TopoDS_Edge or above. +// on_faces works only when tool_shape is an Edge, indicates that +// those edges only imprint on the on_faces. +// Author : Jane HU +// Date : 03/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint_toposhapes(TopoDS_Shape*& from_shape, + TopoDS_Shape* tool_shape, + DLIList<TopoDS_Face*>*on_faces)const +{ + int count = 0; //number of imprinting + + //indicate if there's more faces to be imprinted + CubitBoolean more_face = CUBIT_TRUE; + DLIList<TopoDS_Face*> list_for_delete; + + //list of face on from_shape that has been imprinted + DLIList<TopoDS_Face*> from_faces; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + while( more_face) + { + TopoDS_Face from_face,tool_face; + TopoDS_Edge* common_edge = NULL; + DLIList<TopoDS_Shape*> tool_faces_edges; + TopTools_ListOfShape list_of_edges; + BRepFeat_SplitShape splitor(*from_shape); + CubitBoolean qualified = CUBIT_TRUE; + if (tool_shape->TShape()->ShapeType() == TopAbs_EDGE) + { + if(count == 1) + break; + + DLIList<TopoDS_Face*> faces; + //need to delete TopoDS_Face* in faces + common_edge = find_imprinting_edge(*from_shape, TopoDS::Edge(*tool_shape),faces); + if (common_edge) + { + if (on_faces) + qualified = CUBIT_FALSE; + for(int j = 0; j < faces.size(); j++) + { + from_face = *faces.get(); + for (int i = 0; on_faces && i < on_faces->size(); i++) + { + if (from_face.IsSame(*(on_faces->get_and_step()))) + { + qualified = CUBIT_TRUE; + break; + } + } + faces.get()->Nullify(); + delete faces.get(); + faces.step(); + } + if (qualified && (from_faces.size() == 0 || (from_faces.size() && !from_face.IsSame(*from_faces.get()))) ) + list_of_edges.Append(*common_edge); + else + from_face.Nullify(); + common_edge->Nullify(); + delete common_edge; + } + } + else + { + TopOpeBRep_ShapeIntersector intersector; + intersector.InitIntersection(*from_shape, *tool_shape); + + //find the intersecting edges and faces. + int max_edge = 0; + for(; intersector.MoreIntersection(); intersector.NextIntersection()) + { + TopoDS_Shape face1; + face1 = intersector.ChangeFacesIntersector().Face(1); + CubitBoolean has_imprinted = CUBIT_FALSE; + for (int j = 0; j < from_faces.size(); j++) + { + TopoDS_Face* topo_face = from_faces.get_and_step(); + if(face1.IsSame(*topo_face)) + { + has_imprinted = CUBIT_TRUE; + break; + } + } + + if (has_imprinted) + continue; + + TopoDS_Shape edge_face; + + edge_face = intersector.ChangeFacesIntersector().Face(2); + BRepAlgoAPI_Section section(face1, edge_face); + + //intersection edges between face1 and edge_face + TopTools_ListOfShape temp_list_of_edges; + temp_list_of_edges.Assign(section.SectionEdges()); + int num_edges = temp_list_of_edges.Extent(); + + CubitBoolean is_same = face1.IsSame(from_face); + CubitBoolean is_same_tool = CUBIT_FALSE; + for (int j = 0; j < tool_faces_edges.size(); j++) + { + TopoDS_Shape* topo_face_edge = tool_faces_edges.get_and_step(); + if(edge_face.IsSame(*topo_face_edge)) + { + is_same_tool = CUBIT_TRUE; + break; + } + } + if (max_edge < num_edges ) + { + list_of_edges.Assign(temp_list_of_edges); + max_edge = num_edges ; + from_face = TopoDS::Face(face1); + TopoDS_Shape* topo_shape = new TopoDS_Shape(edge_face); + DLIList<TopoDS_Shape*> shape_list; + for(int iii = 0; iii < tool_faces_edges.size(); iii++) + { + int size = shape_list.size(); + shape_list.append_unique(tool_faces_edges.get_and_step()); + if (size < shape_list.size()) + { + shape_list.last(); + shape_list.get()->Nullify(); + delete shape_list.get(); + } + } + tool_faces_edges.clean_out(); + for(int i = 0 ; i < num_edges; i++) + //later has to use it num_edges times + tool_faces_edges.append(topo_shape); + } + else if(num_edges == max_edge && is_same && !is_same_tool) + //multi tool faces cut the same face + { + TopTools_ListIteratorOfListOfShape Itor, temp_Itor; + temp_Itor.Initialize(temp_list_of_edges); + for(; temp_Itor.More(); temp_Itor.Next()) + { + TopoDS_Edge temp_edge = TopoDS::Edge(temp_Itor.Value()); + Itor.Initialize(list_of_edges); + CubitBoolean same_edge = CUBIT_FALSE; + + GProp_GProps myProps1; + BRepGProp::LinearProperties(temp_edge, myProps1); + gp_Pnt center1 = myProps1.CentreOfMass(); + for(; Itor.More(); Itor.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(Itor.Value()); + GProp_GProps myProps2; + BRepGProp::LinearProperties(edge, myProps2); + gp_Pnt center2 = myProps2.CentreOfMass(); + if(center1.IsEqual(center2, tol)) + { + same_edge = CUBIT_TRUE; + break; + } + } + if(!same_edge) + { + list_of_edges.Append(temp_edge); + TopoDS_Shape* topo_shape = new TopoDS_Shape(edge_face); + tool_faces_edges.append(topo_shape); + } + } + } + } + } + if (from_face.IsNull()) + { + more_face = CUBIT_FALSE; + DLIList<TopoDS_Shape*> shape_list; + for(int iii = 0; iii < tool_faces_edges.size(); iii++) + { + int size = shape_list.size(); + shape_list.append_unique(tool_faces_edges.get_and_step()); + if (size < shape_list.size()) + { + shape_list.last(); + shape_list.get()->Nullify(); + delete shape_list.get(); + } + } + tool_faces_edges.clean_out(); + + for (int iii=0; iii < from_faces.size(); iii++) + { + TopoDS_Face* topo_face = from_faces.get_and_step(); + topo_face->Nullify(); + delete topo_face; + } + + for (int iii=0; iii < list_for_delete.size(); iii++) + { + TopoDS_Face* topo_face = list_for_delete.get_and_step(); + topo_face->Nullify(); + delete topo_face; + } + continue; + } + + TopTools_ListIteratorOfListOfShape Itor; + + //list_of_edges is the intersection edges on tool_faces_edges + Itor.Initialize(list_of_edges); + int total_edges = list_of_edges.Extent(); + DLIList<Curve*> curve_list; + CubitBoolean topo_changed = CUBIT_FALSE; + tool_faces_edges.reset(); + + //check to see if the intersection edge is: + //1. on from_face: if not, skip it + //2. overlap with from_edges : if not, add the edge for splitting face + //3. if overlap, is it the same edge:if not add it for splitting edge + // if yes, skip it too + + Surface* face = NULL; + if (OCCQueryEngine::instance()->OCCMap->IsBound(from_face)) + { + int i = OCCQueryEngine::instance()->OCCMap->Find(from_face); + face = (OCCSurface*)(OCCQueryEngine::instance()->OccToCGM->find(i))->second; + } + else + face = OCCQueryEngine::instance()->populate_topology_bridge(from_face); + OCCSurface* occ_face = CAST_TO(face, OCCSurface); + + DLIList<Curve*> common_curves; + for(; Itor.More(); Itor.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(Itor.Value()); + //copy the edge for imprinting. + BRepBuilderAPI_Copy api_copy(edge); + TopoDS_Shape newShape = api_copy.ModifiedShape(edge); + edge = TopoDS::Edge(newShape); + Curve* curve = NULL; + curve = OCCQueryEngine::instance()->populate_topology_bridge(edge); + if(curve) + common_curves.append(curve); + } + + DLIList<DLIList<TopoDS_Edge*>*> temp_edge_lists; + list_of_edges.Clear(); + if (common_curves.size() >= 1) + { + sort_curves(common_curves, temp_edge_lists); + DLIList<TopoDS_Edge*>* edge_list; + int size = temp_edge_lists.size(); + for(int i = 0; i < size; i++) + { + edge_list = temp_edge_lists.pop(); + //make sure the copied edges are sharing vertices. + BRepBuilderAPI_MakeWire myWire; + edge_list->reset(); + for(int i = 0; i < edge_list->size(); i++) + { + TopoDS_Edge e = *(edge_list->get_and_step()); + myWire.Add(e); + } + TopoDS_Wire wire = myWire.Wire(); + BRepTools_WireExplorer Ex(wire); + for(; Ex.More(); Ex.Next()) + list_of_edges.Append(Ex.Current()); + } + } + for(Itor.Initialize(list_of_edges); Itor.More(); Itor.Next()) + { + TopoDS_Edge edge = TopoDS::Edge(Itor.Value()); + //check to see if the intersection edge is on from_face + TopExp_Explorer Ex; + CubitBoolean added = CUBIT_FALSE; + CubitBoolean skipped = CUBIT_FALSE; + GProp_GProps myProps1; + BRepGProp::LinearProperties(edge, myProps1); + double d1 = myProps1.Mass(); + gp_Pnt pt = myProps1.CentreOfMass(); + CubitVector p(pt.X(), pt.Y(), pt.Z()); + + CubitVector point_on_surf; + occ_face->closest_point_trimmed(p, point_on_surf); + if(p.distance_between(point_on_surf) > tol) //edge not on from_face + { + skipped = CUBIT_TRUE; + total_edges--; + } + + else + { + for (Ex.Init(from_face, TopAbs_EDGE); Ex.More(); Ex.Next()) + { + //check if the edge is on from_face edges, add such edge on existing + //edge to split it. + TopoDS_Edge from_edge = TopoDS::Edge(Ex.Current()); + + GProp_GProps myProps2; + BRepGProp::LinearProperties(from_edge, myProps2); + double d2 = myProps2.Mass(); + Curve* curve = NULL; + if (OCCQueryEngine::instance()->OCCMap->IsBound(from_edge)) + { + int i = OCCQueryEngine::instance()->OCCMap->Find(from_edge); + curve = (OCCCurve*)(OCCQueryEngine::instance()->OccToCGM->find(i))->second; + } + else + curve = OCCQueryEngine::instance()->populate_topology_bridge(from_edge); + OCCCurve* occ_curve = CAST_TO(curve, OCCCurve); + CubitPointContainment pc = occ_curve->point_containment(p); + + if(pc == CUBIT_PNT_ON) //overlap + { + //check if they are the same edge, so don't need to be split + //the overlapped edges are considered the same if they have the + //same length + if((d2 - d1) > tol) + { + added = CUBIT_TRUE; + splitor.Add(edge, from_edge); + } + else + skipped = CUBIT_TRUE; + total_edges--; + break; + } + } + } + if(added) + { + topo_changed = CUBIT_TRUE; + continue; + } + if (!skipped) + { + //check if edge's inside from_face by checking bounding boxes + BRepAdaptor_Curve acurve(edge); + BRepAdaptor_Surface asurface( from_face); + Bnd_Box aBox_edge, aBox_face; + BndLib_Add3dCurve::Add(acurve, Precision::Approximation(), aBox_edge); + BndLib_AddSurface::Add(asurface, Precision::Approximation(), aBox_face); + double min[3], max[3]; + aBox_edge.Get( min[0], min[1], min[2], max[0], max[1], max[2]); + CubitBox aBox_e(min, max); + aBox_face.Get( min[0], min[1], min[2], max[0], max[1], max[2]); + CubitBox aBox_f(min, max); + if (aBox_e <= aBox_f) + { + Curve* curve = OCCQueryEngine::instance()->populate_topology_bridge(edge); + curve_list.append(curve); + } + } + } + + DLIList<DLIList<TopoDS_Edge*>*> edge_lists; + if (total_edges >= 1) + { + CubitStatus stat = sort_curves(curve_list, edge_lists); + DLIList<TopoDS_Edge*>* edge_list; + int size = edge_lists.size(); + for (int iii = 0; iii < size; iii++) + { + edge_list = edge_lists.pop(); + + //check if the edges make a split of the surface, error out if it's + //just a scar on the surface + int count_intersection = 0; + if (stat == CUBIT_FAILURE) //Open wire + { + count_intersection = check_intersection(edge_list, from_face); + + if (count_intersection < 2) + PRINT_WARNING("Cant make a scar on existing face without splitting it. \n"); + } + if (stat || count_intersection == 2) + { + BRepBuilderAPI_MakeWire myWire; + edge_list->reset(); + for(int i = 0; i < edge_list->size(); i++) + { + TopoDS_Edge e = *(edge_list->get_and_step()); + myWire.Add(e); + } + splitor.Add(myWire.Wire(),from_face); + topo_changed = CUBIT_TRUE; + break; + } + for(int iii = 0; iii < edge_list->size(); iii++) + edge_list->pop(); + delete edge_list; + } + } + if(topo_changed) + { + splitor.Build(); + topo_changed = CUBIT_FALSE; + if(splitor.IsDone()) + { + //take care of on_faces list first:after operation, the on_faces + // will have at least one face changed, update the pointer. + if (on_faces) + { + for(int k = 0; k < on_faces->size(); k++) + { + TopoDS_Face* compare_face = on_faces->get_and_step(); + if(from_face.IsSame(*compare_face)) + { + on_faces->remove(compare_face); + TopTools_ListOfShape shapes; + shapes.Assign(splitor.Modified(from_face)); + while(shapes.Extent() > 0) + { + TopoDS_Face* face = + new TopoDS_Face(TopoDS::Face(shapes.First())); + shapes.RemoveFirst(); + on_faces->append(face); + list_for_delete.append(face); + } + } + } + } + + TopoDS_Shape new_from_shape = splitor.Shape(); + if(from_shape->TShape()->ShapeType() == TopAbs_COMPSOLID) + { + TopoDS_CompSolid old_csolid = TopoDS::CompSolid(*from_shape); + OCCBody::update_OCC_entity(old_csolid, new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + + else if(from_shape->TShape()->ShapeType() == TopAbs_SOLID) + { + TopoDS_Solid old_solid = TopoDS::Solid(*from_shape); + OCCLump::update_OCC_entity(old_solid, new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + else if(from_shape->TShape()->ShapeType() == TopAbs_SHELL) + { + TopoDS_Shell old_shell = TopoDS::Shell(*from_shape); + OCCShell::update_OCC_entity(old_shell,new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + else if(from_shape->TShape()->ShapeType() == TopAbs_FACE) + { + TopoDS_Face old_face = TopoDS::Face(*from_shape); + OCCSurface::update_OCC_entity(old_face,new_from_shape, &splitor); + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(new_from_shape); + } + + TopTools_ListOfShape shapes; + for(int i = 0; i < from_faces.size(); i++) + { + TopoDS_Face* topo_face = from_faces.get(); + shapes.Assign(splitor.Modified(*topo_face)); + topo_face = new TopoDS_Face(TopoDS::Face(shapes.First())); + from_faces.get()->Nullify(); + delete from_faces.get(); + from_faces.change_to(topo_face); + from_faces.step(); + } + count++; + } + } + else + { + TopoDS_Face* topo_face = new TopoDS_Face(from_face); + from_faces.append(topo_face); + } + } + + + TopExp_Explorer Ex; + int num_face = 0; + for (Ex.Init(*from_shape, TopAbs_FACE); Ex.More(); Ex.Next()) + { + TopoDS_Face face = TopoDS::Face(Ex.Current()); + num_face++; + } + +#ifdef DEBUG + PRINT_INFO("Total %d cuts performed, with from_shape having %d faces.\n", count, num_face); +#endif + + if (count > 0) + return CUBIT_SUCCESS; + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : find_imprinting_edge +// Member Type: PROTECTED +// Description: imprint boolean operation on OCC-based bodies. +// from_shape must be TopoDS_Face or above, tool_shape must be +// TopoDS_Edge. +// Author : Jane HU +// Date : 05/08 +//=============================================================================== +TopoDS_Edge* OCCModifyEngine::find_imprinting_edge(TopoDS_Shape& from_shape, + TopoDS_Edge& tool_shape, + DLIList<TopoDS_Face*>& from_faces)const +{ + TopoDS_Edge* edge = NULL; + //list of face on from_shape that has been imprinted + from_faces.clean_out(); + TopExp_Explorer Ex; + for (Ex.Init(from_shape, TopAbs_FACE); Ex.More(); Ex.Next()) + { + TopoDS_Face face = TopoDS::Face(Ex.Current()); + BRepAlgoAPI_Common intersector(face, tool_shape); + TopTools_ListOfShape shapes; + shapes.Assign(intersector.Modified(tool_shape)); + if (shapes.IsEmpty()) + continue; + if ( shapes.Extent() > 1) + { + PRINT_ERROR("Edge has multiple intersection with the shape, make it simpler. \n"); + continue; + } + if (shapes.First().TShape()->ShapeType() != TopAbs_EDGE) + continue; + if(edge == NULL) + { + TopoDS_Edge common_edge = TopoDS::Edge(shapes.First()); + BRepBuilderAPI_Copy api_copy(common_edge); + TopoDS_Shape newShape = api_copy.ModifiedShape(common_edge); + edge = new TopoDS_Edge(TopoDS::Edge(newShape)); + } + from_faces.append(new TopoDS_Face(face)); + } + return edge; +} + +int OCCModifyEngine::check_intersection(DLIList<TopoDS_Edge*>* edge_list, + TopoDS_Face from_face)const +{ + int count_intersection = 0; + //Consider if edge_list has only one edge, and it intersects the from_face + //at two different places. + CubitBoolean double_check = CUBIT_FALSE; + if (edge_list->size() == 1) + double_check = CUBIT_TRUE; + + gp_Pnt intsec_pnt[2]; + for(int j = 0; j < edge_list->size(); j++) + { + TopoDS_Edge* edge = edge_list->get_and_step(); + BRepAdaptor_Curve acurve(*edge); + double lower_bound = acurve.FirstParameter(); + double upper_bound = acurve.LastParameter(); + TopExp_Explorer Ex; + gp_Pnt newP[2]; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + for (Ex.Init(from_face, TopAbs_EDGE); Ex.More(); Ex.Next()) + { + TopoDS_Edge from_edge = TopoDS::Edge(Ex.Current()); + BRepAdaptor_Curve acurve2(from_edge); + double lower_bound2 = acurve2.FirstParameter(); + double upper_bound2 = acurve2.LastParameter(); + BRepExtrema_DistShapeShape distShapeShape(*edge, from_edge); + CubitBoolean qualified[2] = {CUBIT_FALSE, CUBIT_FALSE}; + if (distShapeShape.IsDone() && distShapeShape.Value() < tol) + { + newP[0] = distShapeShape.PointOnShape1(1); + if (double_check && distShapeShape.NbSolution() == 2) + newP[1] = distShapeShape.PointOnShape1(2); + double newVal[2]; + for(int j =0; j < distShapeShape.NbSolution(); j++) + { + Extrema_ExtPC ext(newP[j], acurve, Precision::Approximation()); + if (ext.IsDone() && (ext.NbExt() > 0)) { + for ( int i = 1 ; i <= ext.NbExt() ; i++ ) { + if ( ext.IsMin(i) ) { + newVal[j] = ext.Point(i).Parameter(); + if ((newVal[j]-lower_bound) >= -tol && + (upper_bound - newVal[j]) >= -tol) + { + qualified[j] = CUBIT_TRUE; + break; + } + } + } + } + } + for(int j = 0; j < distShapeShape.NbSolution(); j++) + { + if (qualified[j]) + { + qualified[j] = CUBIT_FALSE; + Extrema_ExtPC ext(newP[j], acurve2, Precision::Approximation()); + double newVal; + if (ext.IsDone() && (ext.NbExt() > 0)) { + for ( int i = 1 ; i <= ext.NbExt() ; i++ ) { + if ( ext.IsMin(i) ) { + newVal = ext.Point(i).Parameter(); + if ((newVal-lower_bound2) >= -tol && + (upper_bound2 - newVal) >= -tol) + { + qualified[j] = CUBIT_TRUE; + break; + } + } + } + } + } + } + for(int k = 0; k < distShapeShape.NbSolution(); k++) + { + if (qualified[k]) + count_intersection++; + intsec_pnt[count_intersection-1] = newP[k]; + if (count_intersection == 2) + { + //make sure the two intersect point are not the same one + if (intsec_pnt[0].IsEqual(intsec_pnt[1], tol)) + count_intersection--; + } + } + } + if (count_intersection == 2) + break; + } //for loop + } + return count_intersection; +} +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: imprint boolean operation on OCC-based bodies +// Author : Jane Hu +// Date : 04/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint(BodySM* BodyPtr1, BodySM* BodyPtr2, + BodySM*& newBody1, BodySM*& newBody2, + bool keep_old) const +{ + newBody1 = NULL; + newBody2 = NULL; + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_volume; + + DLIList<BodySM*> bodysm_list; + bodysm_list.append(BodyPtr1); + bodysm_list.append(BodyPtr2); + + CubitStatus stat = get_shape_list(bodysm_list,shape_list,is_volume,keep_old); + + if(!stat) + return stat; + + TopoDS_Shape* shape1 = shape_list.get(); + TopoDS_Shape* shape2 = shape_list.step_and_get(); + DLIList<TopologyBridge*> tbs; + stat = imprint_toposhapes(shape1, shape2); + if(stat) + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape1); + newBody1 = CAST_TO(tbs.get(),BodySM); + } + + else if(!stat && keep_old) + { + delete shape1; + PRINT_INFO("There's no imprint on the first body.\n"); + newBody1 = BodyPtr1; + } + + tbs.clean_out(); + stat = imprint_toposhapes(shape2, shape1); + if(stat) + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape2); + newBody2 = CAST_TO(tbs.get(),BodySM); + } + + else if(!stat && keep_old) + { + delete shape2; + PRINT_INFO("There's no imprint on the second body.\n"); + newBody2 = BodyPtr2; + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : get_the_shape_list +// Member Type: PRIVATE +// Description: get the TopoDS_Shape list for imprinting use. +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus OCCModifyEngine::get_shape_list(DLIList<BodySM*>& BodySM_list, + DLIList<TopoDS_Shape*>& shape_list, + DLIList<CubitBoolean>& is_volume, + bool keep_old, + DLIList<CubitBox*>* b_boxes) const +{ + OCCBody* occ_body = NULL; + shape_list.clean_out(); + is_volume.clean_out(); + CubitStatus stat = CUBIT_SUCCESS; + for(int i = 0; i <BodySM_list.size(); i++) + { + occ_body = CAST_TO(BodySM_list.get_and_step(), OCCBody); + if (!occ_body) + continue; + + OCCSurface* surface = occ_body->my_sheet_surface(); + OCCShell* shell = occ_body->shell(); + is_volume.append( CUBIT_TRUE); + + if(b_boxes) + { + CubitBox *tool_box = new CubitBox(occ_body->get_bounding_box()); + b_boxes->append(tool_box); + } + + if(surface) + { + TopoDS_Face* topo_face = surface->get_TopoDS_Face(); + if(!topo_face) + { + stat = CUBIT_FAILURE; + break; + } + if(keep_old) + { + BRepBuilderAPI_Copy api_copy(*topo_face); + TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_face); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + shape_list.append(Shape1); + } + else + shape_list.append(topo_face); + is_volume.change_to( CUBIT_FALSE); + } + else if(shell) + { + TopoDS_Shell* topo_shell = shell->get_TopoDS_Shell(); + if(!topo_shell) + { + stat = CUBIT_FAILURE; + break; + } + if(keep_old) + { + BRepBuilderAPI_Copy api_copy(*topo_shell); + TopoDS_Shape newShape = api_copy.ModifiedShape(*topo_shell); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + shape_list.append(Shape1); + } + else + shape_list.append(topo_shell); + is_volume.change_to( CUBIT_FALSE); + } + + else + { + DLIList<Lump*> lumps = occ_body->lumps(); + if (lumps.size() > 1) + { + PRINT_ERROR("Can't do boolean operation on CompSolid types. \n"); + stat = CUBIT_FAILURE; + break; + } + + TopoDS_Solid* solid = CAST_TO(lumps.get(), OCCLump)->get_TopoDS_Solid(); + if(!solid) + { + stat = CUBIT_FAILURE; + break; + } + if(keep_old) + { + BRepBuilderAPI_Copy api_copy(*solid); + TopoDS_Shape newShape = api_copy.ModifiedShape(*solid); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + shape_list.append(Shape1); + } + else + shape_list.append(solid); + } + } + if(!stat) + { + for (int i = 0; keep_old && i < shape_list.size(); i++) + { + TopoDS_Shape* shape = shape_list.get_and_step(); + delete shape; + } + shape_list.clean_out(); + return CUBIT_FAILURE; + } + return CUBIT_SUCCESS; +} +//=============================================================================== +// Function : imprint multiple bodies at once +// Member Type: PUBLIC +// Description: imprint boolean operation on OCC-based bodies +// Author : Jane HU +// Date : 04/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint(DLIList<BodySM*> &from_body_list , + DLIList<BodySM*> &new_from_body_list, + bool keep_old, + DLIList<TopologyBridge*>* new_tbs, + DLIList<TopologyBridge*>* att_tbs) const +{ + CubitStatus success = CUBIT_SUCCESS; + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_vo; + CubitStatus stat = get_shape_list(from_body_list, shape_list, is_vo,keep_old); + + if(!stat) + return stat; + + int size = shape_list.size(); + // total number of imprints to be done + int total_imprints = (size * (size -1))/2; + + if( size > 2 ) + { + char message[128]; + sprintf(message, "Imprinting %d OCC Bodies", from_body_list.size() ); + AppUtil::instance()->progress_tool()->start(0, total_imprints, message); + } + + for(int i = 0; i < size; i++) + { + TopoDS_Shape* shape1 = shape_list[i]; + CubitBoolean modified = CUBIT_FALSE; + for(int j = i+1; j < size+i; j ++) + { + if (CubitMessage::instance()->Interrupt()) + { + success = CUBIT_FAILURE; + break; + } + + TopoDS_Shape* shape2 = shape_list[j%size]; + DLIList<TopologyBridge*> tbs; + CubitStatus stat = imprint_toposhapes(shape1, shape2); + if(stat) + modified = CUBIT_TRUE; + } + if(modified) + { + DLIList<TopologyBridge*> tbs; + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape1); + new_from_body_list.append(CAST_TO(tbs.get(),BodySM)); + } + shape_list.reset(); + if( size > 2 ) + AppUtil::instance()->progress_tool()->step(); + } + + if( size > 2 ) + AppUtil::instance()->progress_tool()->end(); + + if( CubitMessage::instance()->Interrupt() ) + PRINT_INFO("Imprint aborted.\n"); + + return success; +} + +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: imprint curves onto body_list +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<BodySM*> &body_list, + DLIList<Curve*> &ref_edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old, + bool show_messages) const +{ + CubitStatus success = CUBIT_SUCCESS; + DLIList<TopoDS_Shape*> shape_list, tool_shapes; + DLIList<CubitBoolean> is_vo; + CubitStatus stat = get_shape_list(body_list, shape_list, is_vo, keep_old); + if (!stat) + return stat; + + int size = ref_edge_list.size(); + // total number of imprints to be done + + if( size > 2 && show_messages) + { + char message[128]; + sprintf(message, "Imprinting %d OCC Bodies", body_list.size() ); + AppUtil::instance()->progress_tool()->start(0, size, message); + } + for (int i = 0; i < ref_edge_list.size(); i++) + { + OCCCurve* curve = CAST_TO(ref_edge_list.get_and_step(), OCCCurve) ; + if (!curve) + continue; + + TopoDS_Edge* edge = curve->get_TopoDS_Edge(); + if (edge->IsNull()) + continue; + + if (CubitMessage::instance()->Interrupt()) + { + success = CUBIT_FAILURE; + break; + } + + for(int j = 0; j < shape_list.size(); j ++) + { + TopoDS_Shape* shape = shape_list.get(); + + stat = imprint_toposhapes(shape, (TopoDS_Shape*)edge); + if (stat) + shape_list.change_to(shape); + shape_list.step(); + body_list.step(); + } + + if( size > 2 ) + AppUtil::instance()->progress_tool()->step(); + } + + for(int j = 0; j < shape_list.size(); j ++) + { + DLIList<TopologyBridge*> tbs; + TopoDS_Shape* shape = shape_list.get_and_step(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape); + new_body_list.append(CAST_TO(tbs.get(),BodySM)); + } + + if( size > 2 ) + AppUtil::instance()->progress_tool()->end(); + + if( CubitMessage::instance()->Interrupt() ) + PRINT_INFO("Imprint aborted.\n"); + return success; +} + +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: to be consistante with Acis imprint. +// The surfaces must be part of a body, but the curves +// just have to be valid OCC edge. +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old ) const +{ + DLIList<TopoDS_Face*> face_list; + DLIList<TopoDS_Shape*> shape_list; + + face_edge_imprint(ref_face_list, edge_list, face_list, shape_list, keep_old); + + for(int j = 0; j < shape_list.size(); j ++) + { + DLIList<TopologyBridge*> tbs; + TopoDS_Shape* shape = shape_list.get_and_step(); + if (shape->TShape()->ShapeType() == TopAbs_COMPSOLID) + { + if(!OCCQueryEngine::instance()->OCCMap->IsBound(*shape)) + { + TopExp_Explorer Ex; + for (Ex.Init(*shape, TopAbs_SOLID);Ex.More(); Ex.Next()) + { + TopoDS_Shape subshape = Ex.Current(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(subshape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } + } + else + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } + + if (keep_old) + { + for(int i = 0; i < face_list.size(); i++) + { + TopoDS_Face* face = face_list.get(); + face->Nullify(); + delete face; + } + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : face_edge_imprint +// Member Type: PRIVATE +// Description: to be consistante with Acis imprint. +// The surfaces must be part of a body, but the curves +// just have to be valid OCC edge. +// Author : Jane Hu +// Date : 05/08 +//=============================================================================== +CubitStatus +OCCModifyEngine::face_edge_imprint( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &edge_list, + DLIList<TopoDS_Face*>& face_list, + DLIList<TopoDS_Shape*>& shape_list, + bool keep_old ) const +{ + for(int i = 0; i <ref_face_list.size(); i++) + { + OCCSurface* surface = CAST_TO(ref_face_list.get_and_step(), OCCSurface); + if(!surface) + continue; + + TopoDS_Face* topo_face = surface->get_TopoDS_Face(); + face_list.append(topo_face); + + if(surface->my_shell() && !surface->my_body())//shell body + shape_list.append(surface->my_shell()->get_TopoDS_Shell()); + else if(surface->my_body()) //a sheet body + shape_list.append(topo_face); + else + { + //int size = shape_list.size(); + OCCQueryEngine* oqe = OCCQueryEngine::instance(); + DLIList <OCCBody* > *bodies = oqe->BodyList; + TopTools_IndexedDataMapOfShapeListOfShape M; + OCCBody * body = NULL; + for(int j = 0; j < bodies->size(); j++) + { + body = bodies->get_and_step(); + TopExp_Explorer Ex; + TopoDS_Face the_face; + TopoDS_Shape ashape = *(body->get_TopoDS_Shape()); + M.Clear(); + TopExp::MapShapesAndAncestors(ashape, TopAbs_FACE, TopAbs_COMPSOLID, M); + if(!M.Contains(*topo_face)) + continue; + shape_list.append_unique(body->get_TopoDS_Shape()); + } + } + } + + if(keep_old) + { + for(int i = 0; i < shape_list.size(); i++) + { + TopoDS_Shape* shape = shape_list.get(); + BRepBuilderAPI_Copy api_copy(*shape); + TopoDS_Shape newShape = api_copy.ModifiedShape(*shape); + TopoDS_Shape* Shape1 = new TopoDS_Shape(newShape); + for(int j = 0; j < face_list.size(); j++) + { + TopoDS_Face* face = face_list.get(); + TopExp_Explorer Ex; + for (Ex.Init(*shape, TopAbs_FACE); Ex.More(); Ex.Next()) + { + if(face->IsSame(Ex.Current())) + { + face = new TopoDS_Face(TopoDS::Face(api_copy.ModifiedShape(*face))); + face_list.change_to(face); + } + } + face_list.step(); + } + shape_list.change_to(Shape1); + shape_list.step(); + } + } + + for (int i = 0; i < edge_list.size(); i++) + { + OCCCurve* curve = CAST_TO(edge_list.get_and_step(), OCCCurve) ; + if (!curve) + continue; + + TopoDS_Edge* edge = curve->get_TopoDS_Edge(); + if (edge->IsNull()) + continue; + + for(int j = 0; j < shape_list.size(); j ++) + { + TopoDS_Shape* shape = shape_list.get_and_step(); + imprint_toposhapes(shape, (TopoDS_Shape*)edge, &face_list); + } + } + return CUBIT_SUCCESS; +} +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: To be consistent with AcisModifyEngine, althought it's hard +// to have a GUI interface for users to input. All surface must +// on the same body. +// Author : Jane HU +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<Surface*>& surface_list, + DLIList<DLIList<Curve*>*>& curve_lists_list, + BodySM*& new_body, + bool keep_old ) const +{ + DLIList<TopoDS_Face*> face_list; + DLIList<TopoDS_Shape*> shape_list; + DLIList<TopoDS_Shape*> shape_list_all; + + assert (surface_list.size() == curve_lists_list.size()); + + for(int j = 0; j < surface_list.size(); j++) + { + Surface* surface = surface_list.get_and_step(); + DLIList<Surface*> ref_face_list; + ref_face_list.append(surface); + DLIList<Curve*> *edge_list = curve_lists_list.get_and_step(); + face_edge_imprint(ref_face_list, *edge_list, face_list, shape_list, keep_old); + + for(int i = 0; i < shape_list.size(); i++) + { + TopoDS_Shape* shape = shape_list.get_and_step(); + shape_list_all.append_unique(shape); + } + shape_list.clean_out(); + + if (keep_old) + { + for(int i = 0; i < face_list.size(); i++) + { + TopoDS_Face* face = face_list.get(); + face->Nullify(); + delete face; + } + } + + face_list.clean_out(); + } + + DLIList<BodySM*> new_body_list; + shape_to_bodySM(shape_list, new_body_list); + + if (new_body_list.size() == 1) + { + new_body = new_body_list.get(); + return CUBIT_SUCCESS; + } + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : shape_to_bodySM +// Member Type: PRIVATE +// Description: After imprint, update shape list to bodySM_list +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +void OCCModifyEngine::shape_to_bodySM( DLIList<TopoDS_Shape*> shape_list, + DLIList<BodySM*>& new_body_list)const +{ + for(int j = 0; j < shape_list.size(); j ++) + { + DLIList<TopologyBridge*> tbs; + TopoDS_Shape* shape = shape_list.get_and_step(); + if (shape->TShape()->ShapeType() == TopAbs_COMPSOLID) + { + if(!OCCQueryEngine::instance()->OCCMap->IsBound(*shape)) + { + TopExp_Explorer Ex; + for (Ex.Init(*shape, TopAbs_SOLID);Ex.More(); Ex.Next()) + { + TopoDS_Shape subshape = Ex.Current(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(subshape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } + } + else + { + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*shape); + new_body_list.append_unique(CAST_TO(tbs.get(),BodySM)); + } + } +} + +//=============================================================================== +// Function : imprint +// Member Type: PUBLIC +// Description: Imprints locations to bodies (for splitting curves, there's +// no known ways to put hard points on surfaces in OCC, so I just +// add free_vertex on OCCSurface definition, mesh should look on +// this structure). +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::imprint( DLIList<BodySM*> &body_list, + DLIList<CubitVector*> &vector_list, + DLIList<BodySM*>& new_body_list, + bool keep_old, + DLIList<TopologyBridge*>*, + DLIList<TopologyBridge*>* ) const +{ + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_vo; + CubitStatus stat = get_shape_list(body_list, shape_list, is_vo, keep_old); + if(!stat) + return stat; + + for (int i = 0; i < body_list.size(); i++) + { + OCCBody* body = CAST_TO(body_list.get_and_step(), OCCBody); + TopoDS_Shape* from_shape = shape_list.get_and_step(); + if (!body) + continue; + DLIList<OCCSurface*> surfaces; + DLIList<OCCCurve*> curves; + + body->get_all_surfaces(surfaces); + body->get_all_curves(curves); + + CubitBoolean on_vertex = CUBIT_FALSE; + CubitBoolean on_curve = CUBIT_FALSE; + for (int j = 0; j < vector_list.size(); j ++) + { + CubitVector* v = vector_list[j]; + if(v == NULL) + continue; + for (int k = 0; k < curves.size(); k ++) + { + OCCCurve* curve = curves.get_and_step(); + CubitPointContainment pc = curve->point_containment(*v); + if(pc == CUBIT_PNT_BOUNDARY) + { + on_vertex = CUBIT_TRUE; + break; + } + + else if( pc == CUBIT_PNT_INSIDE) + { + LocOpe_SplitShape splitor(*from_shape); + on_curve = CUBIT_TRUE; + TopoDS_Edge edge = *curve->get_TopoDS_Edge(); + gp_Pnt pt = gp_Pnt(v->x(), v->y(), v->z()); + TopoDS_Vertex vertex = BRepBuilderAPI_MakeVertex(pt); + double param = curve->u_from_position(*v); + splitor.Add(vertex, param, edge); + + //update the curve_list + TopTools_ListOfShape edge_shapes; + edge_shapes.Assign(splitor.DescendantShapes(edge)); + while(edge_shapes.Extent()) + { + TopoDS_Shape edge_shape = edge_shapes.First(); + TopoDS_Edge occ_edge = TopoDS::Edge(edge_shape); + OCCCurve* test_curve; + test_curve = CAST_TO(OCCQueryEngine::instance()->populate_topology_bridge(occ_edge), OCCCurve); + if(test_curve) + curves.append(test_curve); + edge_shapes.RemoveFirst(); + } + curves.remove(curve); + + TopTools_ListOfShape shapes; + shapes.Assign(splitor.DescendantShapes(*from_shape)); + if(from_shape->TShape()->ShapeType() ==TopAbs_COMPSOLID) + OCCBody::update_OCC_entity(*from_shape, shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + else if(shapes.First().TShape()->ShapeType() == TopAbs_SOLID) + OCCLump::update_OCC_entity(TopoDS::Solid(*from_shape), + shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + + else if(shapes.First().TShape()->ShapeType() == TopAbs_SHELL) + OCCShell::update_OCC_entity(TopoDS::Shell(*from_shape), + shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + + else if(shapes.First().TShape()->ShapeType() == TopAbs_FACE) + OCCSurface::update_OCC_entity(TopoDS::Face(*from_shape), + shapes.First(), + (BRepBuilderAPI_MakeShape*) NULL, &splitor); + + from_shape->Nullify(); + delete from_shape; + from_shape = new TopoDS_Shape(shapes.First()); + break; + } + } + if(on_vertex || on_curve) + continue; + + //check possible on surface + for(int n = 0; n < surfaces.size(); n ++) + { + OCCSurface* surface = surfaces.get_and_step(); + if(!surface->is_position_on(*v)) + continue; + + CubitPointContainment ps = surface->point_containment(*v); + if(ps == CUBIT_PNT_INSIDE) + { + Point* p = make_Point(*v); + if(p) + surface->add_hardpoint(CAST_TO(p, OCCPoint)); + break; + } + } + } + } + + shape_to_bodySM(shape_list, new_body_list); + + return stat; +} + +//=============================================================================== +// Function : imprint_projected_edges +// Member Type: PUBLIC +// Description: Projects a list of Curves on to a list of Surfaces +// and imprint the faces with the new Curves +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus +OCCModifyEngine::imprint_projected_edges( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &ref_edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old_body, + bool keep_free_edges) const +{ + DLIList<Curve*> projected_curves; + CubitStatus + stat = project_edges(ref_face_list, ref_edge_list, projected_curves); + if(!stat) + return stat; + + // imprint Surface with curves + stat = imprint(ref_face_list, projected_curves, new_body_list, keep_old_body ); + + if(keep_free_edges) + return stat; + + PRINT_INFO( "Removing projected curves \n"); + for(int i=0; i< projected_curves.size();i++) + { + // Now delete this Curve and its underlying solid model entities + + Curve* curve = projected_curves.get_and_step(); + stat = OCCQueryEngine::instance()->delete_solid_model_entities( curve ); + if (stat == CUBIT_FAILURE) + { + PRINT_ERROR("In OCCQueryEngine::delete_geometry\n" + " Could not delete OCCCurve.\n" + " The Model database is likely corrupted " + "due to\n this unsuccessful deletion.\n" ); + } + } + return stat; +} +//=============================================================================== +// Function : project_edges +// Member Type: PUBLIC +// Description: Projects a list of Curves on to a list of Surfaces +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::project_edges( DLIList<Surface*> &ref_face_list, + DLIList<Curve*> &ref_edge_list, + DLIList<Curve*> &projected_curves, + bool print_error ) const + +{ + CubitVector* v = NULL; + Curve* projected_curve = NULL; + DLIList<Point*> points; + //project curves onto surfaces. + for(int i = 0; i < ref_edge_list.size(); i++) + { + OCCCurve* curve = CAST_TO(ref_edge_list.get_and_step(), OCCCurve); + if(!curve) + continue; + + for (int j = 0; j < ref_face_list.size(); j++) + { + OCCSurface* surface = CAST_TO(ref_face_list.get_and_step(), OCCSurface); + if(!surface) + continue; + if(surface->is_closed_in_U() || surface->is_closed_in_V()) + { + if(print_error) + PRINT_ERROR("This function can't project curves on closed surfaces.\n"); + return CUBIT_FAILURE; + } + + projected_curve = NULL; + projected_curve = curve->project_curve(surface, points, CUBIT_FALSE, v); + if(projected_curve) + projected_curves.append_unique(projected_curve); + } + } + while(points.size() > 0) + delete points.pop(); + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : imprint_projected_edges +// Member Type: PUBLIC +// Description: Projects a list of curves on to a list of surfaces +// and imprint the bodies with the new curves +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus +OCCModifyEngine::imprint_projected_edges(DLIList<Surface*> &ref_face_list, + DLIList<BodySM*> &body_list, + DLIList<Curve*> &ref_edge_list, + DLIList<BodySM*>& new_body_list, + bool keep_old, + bool keep_free_edges) const +{ + DLIList<Curve*> projected_curves; + CubitStatus + stat = project_edges(ref_face_list, ref_edge_list, projected_curves); + if(!stat) + return stat; + return CUBIT_FAILURE; + + // imprint bodies with curves + stat = imprint(body_list,projected_curves, new_body_list, keep_old); + + if (keep_free_edges) + return stat; + + PRINT_INFO( "Removing projected curves \n"); + for(int i=0; i< projected_curves.size();i++) + { + // Now delete this Curve + Curve* curve = projected_curves.get_and_step(); + stat = OCCQueryEngine::instance()-> + delete_solid_model_entities( curve ); + if (stat == CUBIT_FAILURE) + { + PRINT_ERROR("In OCCModifyEngine::delete_geometry\n" + " Could not delete Curve.\n" + " The Model database is likely corrupted " + "due to\n this unsuccessful deletion.\n" ); + } + } + return stat; +} + +//=============================================================================== +// Function : intersect +// Member Type: PUBLIC +// Description: intersect boolean operation of body with list of bodies. +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::intersect(BodySM* tool_body_ptr, + DLIList<BodySM*> &from_bodies, + DLIList<BodySM*> &new_bodies, + bool keep_old) const +{ + DLIList<BodySM*> tool_bodies; + DLIList<TopoDS_Shape*> tool_shapes; + DLIList<CubitBoolean> is_tool_volume, is_volume; + + tool_bodies.append(tool_body_ptr); + //get tool_body's underlying shape, copy it, so boolean wouldn't touch it. + CubitStatus stat = + get_shape_list(tool_bodies, tool_shapes, is_tool_volume, CUBIT_TRUE); + if(!stat) + return stat; + + DLIList<TopoDS_Shape*> shape_list; + stat = get_shape_list(from_bodies, shape_list, is_volume, keep_old); + if(!stat) + { + for (int i = 0; i < tool_shapes.size(); i++) + { + TopoDS_Shape* shape = tool_shapes.get_and_step(); + delete shape; + } + tool_shapes.clean_out(); + return CUBIT_FAILURE; + } + + TopoDS_Shape* tool_shape = tool_shapes.get(); + CubitBoolean has_changed; + DLIList<TopologyBridge*> tbs; + for (int i = 0; i < shape_list.size(); i++) + { + TopoDS_Shape* from_shape = shape_list.get_and_step(); + //BodySM* from_body = from_bodies.get_and_step(); + BRepAlgoAPI_Common intersector(*from_shape, *tool_shape); + TopoDS_Shape common_shape = intersector.Shape(); + check_operation(common_shape, from_shape, is_volume[i], has_changed, + &intersector, keep_old); + + if(from_shape->IsNull()) + { + PRINT_INFO("The %d body did not have common part with the tool_body.\n", i+1); + continue; + } + else + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*from_shape); + } + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + new_bodies.append(bodysm); + } + + //ok, we're done wih all cuts, delete unnecessaries. + if(!keep_old) + OCCQueryEngine::instance()->delete_solid_model_entities(tool_body_ptr); + + for(int i = 0; i < tool_shapes.size(); i++) + { + TopoDS_Shape* shape = tool_shapes.get_and_step(); + shape->Nullify(); + delete shape; + } + + if(keep_old) + { + int size = shape_list.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Shape* shape = shape_list.pop(); + shape->Nullify(); + delete shape; + } + } + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : check_operation +// Member Type: PRIVATE +// Description: check and update the from_shape according to type of the body. +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +void OCCModifyEngine::check_operation(TopoDS_Shape& cut_shape, + TopoDS_Shape*& from_shape, //output + CubitBoolean is_volume, + CubitBoolean& has_changed, //output + BRepAlgoAPI_BooleanOperation* op, + CubitBoolean keep_old) const +{ + //compare to see if the from_shape has gotten cut. + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + if(is_volume) + { + GProp_GProps myProps; + BRepGProp::VolumeProperties(*from_shape, myProps); + double orig_mass = myProps.Mass(); + BRepGProp::VolumeProperties(cut_shape, myProps); + double after_mass = myProps.Mass(); + if(fabs(-after_mass + orig_mass) <= tol) + { + has_changed= CUBIT_FALSE; //common is itself + return; + } + + //got cut. Update the entities + if(after_mass < tol) //no common section + cut_shape.Nullify(); + has_changed = CUBIT_TRUE; + TopExp_Explorer Ex; + Ex.Init(*from_shape, TopAbs_SOLID); + TopoDS_Solid old_solid = TopoDS::Solid(Ex.Current()); + OCCLump::update_OCC_entity(old_solid , cut_shape, op); + } + else + { + GProp_GProps myProps; + BRepGProp::SurfaceProperties(*from_shape, myProps); + double orig_mass = myProps.Mass(); + BRepGProp::SurfaceProperties(cut_shape, myProps); + double after_mass = myProps.Mass(); + if(fabs(-after_mass + orig_mass) <= tol) + { + has_changed= CUBIT_FALSE; //common is itself, or not cut + return; + } + //got cut. Update the entities + if(after_mass < tol)//no common section + cut_shape.Nullify(); + has_changed = CUBIT_TRUE; + if(from_shape->TShape()->ShapeType() == TopAbs_SHELL) + { + TopoDS_Shell old_shell = TopoDS::Shell(*from_shape); + OCCShell::update_OCC_entity(old_shell,cut_shape, op); + } + else + { + TopoDS_Face old_face = TopoDS::Face(*from_shape); + OCCSurface::update_OCC_entity(old_face,cut_shape, op); + } + } + if(keep_old) + delete from_shape; + from_shape = new TopoDS_Shape(cut_shape); +} + +//=============================================================================== +// Function : chop +// Member Type: PUBLIC +// Description: chop boolean operation between OCC-based bodies +// bodies has a size() = 2, a blank body and a tool body. +// chops the blank with the tool, returing the body formed +// by subtracting the tool from the blank, and the body formed +// by intersecting the tool with the blank, simultaneously. +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::chop(DLIList<BodySM*>& bodies, + DLIList<BodySM*> &intersectBodies, + DLIList<BodySM*> &outsideBodies, + BodySM*& leftoversBody, + bool keep_old , + bool nonreg) const +{ + //according to Acis chop function, leftoverBody = 0; + leftoversBody = 0; + + //there's no effect of nonreg. keep_old mean if to keep the tool_body + if(bodies.size() != 2) + { + PRINT_WARNING("Chop operation works only on two bodies. Nothing modified\n"); + return CUBIT_FAILURE; + } + + //outsideBodies keeps the surface, curve ids if keep_old is false. + BodySM* blank_body = bodies.get(); + + //copy blank_body for intersect operation, because it will get changed. + DLIList<BodySM*> tool_bodies, from_bodies; + from_bodies.append(blank_body); + BodySM* tool_body = bodies.step_and_get(); + tool_bodies.append(tool_body); + + CubitStatus stat = intersect(tool_body, from_bodies, + intersectBodies, CUBIT_TRUE); + + if(!stat) + return CUBIT_FAILURE; + + stat = subtract(tool_bodies, from_bodies, outsideBodies, + CUBIT_FALSE, keep_old); + + return stat; +} + +//=============================================================================== +// Function : unite +// Member Type: PUBLIC +// Description: unite boolean operation between OCC-based bodies +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::unite(DLIList<BodySM*> &bodies, + DLIList<BodySM*> &newBodies, + bool keep_old) const +{ + if(bodies.size() < 2) + { + newBodies = bodies; + return CUBIT_SUCCESS; + } + //all bodies must have only one lump in order for boolean operation to work. + DLIList<Lump*> lumps; + for (int i = 0; i < bodies.size(); i++) + { + lumps = CAST_TO(bodies.get_and_step(), OCCBody)->lumps(); + if (lumps.size() > 1) + { + PRINT_WARNING("All bodies must have only one lump for boolean operations to work.\n"); + return CUBIT_FAILURE; + } + } + + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_volume; + CubitStatus stat = + get_shape_list(bodies, shape_list, is_volume, keep_old); + + if(!stat) + return stat; + + //find a non-sheet body to be the first shape + TopoDS_Shape* first_shape; + CubitBoolean first_is_volume; + if((first_is_volume = is_volume.move_to(CUBIT_TRUE))) + { + int index = is_volume.get_index(); + first_shape = shape_list[index]; + shape_list.remove(first_shape); + is_volume.step(index); + is_volume.remove(); + bodies.step(index); + bodies.remove(); + } + + else + { + first_shape = shape_list.pop(); + bodies.pop(); + } + + int size = shape_list.size(); + for(int i = 0; i < size; i++) + { + TopoDS_Shape* second_shape = shape_list.get_and_step(); + + BRepAlgoAPI_Fuse fuser(*first_shape, *second_shape); + TopoDS_Shape new_shape = fuser.Shape(); + + CubitBoolean has_changed; + check_operation(new_shape, first_shape, first_is_volume, has_changed, &fuser, keep_old); + + check_operation(new_shape,second_shape, is_volume[i], has_changed, &fuser, keep_old); + } + + //ok, we're done with all unites, construct new Body' + DLIList<TopologyBridge*> tbs; + tbs += OCCQueryEngine::instance()->populate_topology_bridge(*first_shape); + + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + newBodies.append(bodysm); + } + + //ok, we're done with all unites, delete unnecessaries. + if(keep_old) + { + shape_list.append(first_shape); + int size = shape_list.size(); + for (int i = 0; i < size; i++) + { + TopoDS_Shape* shape = shape_list.pop(); + shape->Nullify(); + delete shape; + } + } + + return CUBIT_SUCCESS; +} + +CubitStatus OCCModifyEngine::thicken( DLIList<BodySM*>& bodies, + DLIList<BodySM*>& new_bodies, + double depth, + CubitBoolean both) const +{ + PRINT_ERROR("Option not supported for OCC based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : hollow +// Member Type: PUBLIC +// Description: Hollow existing solid body by remove one or several surfaces +// Can only take one body at a time. +// depth > 0, thick body going outside bodies +// depth < 0, thick body going inside bodies +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine::hollow( DLIList<BodySM*>& bodies, + DLIList<Surface*>& surfs_to_remove, + DLIList<BodySM*>& new_bodies, + double depth) const +{ + if(bodies.size() != 1 || surfs_to_remove.size() < 1) + { + PRINT_ERROR("Making thick solid in OCC will take one body and at least one surface at a time.\n"); + return CUBIT_FAILURE; + } + + DLIList<TopoDS_Shape*> shape_list; + DLIList<CubitBoolean> is_volume; + CubitStatus stat = get_shape_list(bodies, shape_list, is_volume, CUBIT_FALSE); + + if(!stat) + return stat; + + if(!is_volume.get())//sheet body + { + PRINT_ERROR("Making thick solid in OCC needs an initial solid body to hollow with.\n"); + return CUBIT_FAILURE; + } + + //make sure the body to be hollowed has only one lump + OCCBody* occ_body = CAST_TO(bodies.get(), OCCBody); + DLIList<Lump*> lumps; + lumps = occ_body->lumps(); + if(lumps.size()!=1) + { + PRINT_ERROR("bodies with more than one lump can't be hollowed to make a thick body.\n"); + return CUBIT_FAILURE; + } + + //make sure surfs_to_remove are all in bodies + DLIList<OCCSurface*> surfaces; + TopTools_ListOfShape face_shapes; + occ_body->get_all_surfaces(surfaces); + for(int i = 0; i < surfs_to_remove.size(); i++) + { + OCCSurface* occ_surf = CAST_TO(surfs_to_remove.get(), OCCSurface); + if(!occ_surf) + continue; + if(!surfaces.is_in_list(occ_surf)) + continue; + TopoDS_Face * face = occ_surf->get_TopoDS_Face(); + face_shapes.Append(*face); + } + + if(face_shapes.IsEmpty()) + { + PRINT_ERROR("The surfaces provided should be from the body to be hollowed.\n"); + return CUBIT_FAILURE; + } + + double tol = 1.e-3; //hard coded for now, can be changed by application + TopoDS_Shape* solid = shape_list.get(); + BRepOffsetAPI_MakeThickSolid hollower(*solid, face_shapes, depth, tol, + BRepOffset_Skin, Standard_False, + Standard_False, GeomAbs_Intersection); + TopoDS_Shape new_shape = hollower.Shape(); + TopoDS_Solid old_solid = TopoDS::Solid(*solid); + OCCLump::update_OCC_entity(old_solid , new_shape, &hollower); + + //ok, we're done with all hollowing, construct new Body' + DLIList<TopologyBridge*> tbs; + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + + for (int i = 0; i< tbs.size(); i++) + { + BodySM* bodysm = CAST_TO(tbs.get_and_step(), BodySM); + if (bodysm) + new_bodies.append(bodysm); + } + + return CUBIT_SUCCESS; +} + + +//=============================================================================== +// Function : flip_normals +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 06/08 +//=============================================================================== +CubitStatus OCCModifyEngine :: flip_normals( DLIList<Surface*>& face_list ) const +{ + DLIList<Surface*> surface_list; + while (face_list.size()) + { + OCCSurface* occ_surface = CAST_TO(face_list.pop(), OCCSurface); + OCCShell* occ_shell = occ_surface->my_shell(); + DLIList<OCCSurface*> surfaces; + surfaces.append(occ_surface); + if(occ_shell) //find all surfaces in face_list that belong to this shell + { + int size = face_list.size(); + for ( int i = 0; i < size; i++) + { + occ_surface = CAST_TO(face_list.get(), OCCSurface); + if(occ_shell == occ_surface->my_shell()) + surfaces.append(CAST_TO(face_list.remove(),OCCSurface)); + else + face_list.step(); + } + + if (!occ_shell->is_sheet()) + { + DLIList<OCCCoFace*> cofaces; + cofaces = occ_shell->cofaces(); + for(int i = 0; i < cofaces.size(); i++) + { + OCCCoFace* coface =cofaces.get_and_step(); + occ_surface = coface->surface(); + if(surfaces.is_in_list(occ_surface)) + { + TopoDS_Face* topoface = occ_surface->get_TopoDS_Face(); + TopAbs_Orientation ori = topoface->Orientation(); + topoface->Orientation(ori == TopAbs_FORWARD ? TopAbs_REVERSED : + TopAbs_FORWARD); + occ_surface->set_TopoDS_Face(*topoface); + coface->set_sense(coface->sense() == CUBIT_FORWARD ? + CUBIT_REVERSED : CUBIT_FORWARD); + surface_list.append(occ_surface); + } + } + } + else //sheet body + { + TopoDS_Face* topoface = occ_surface->get_TopoDS_Face(); + TopAbs_Orientation ori = topoface->Orientation(); + topoface->Orientation(ori == TopAbs_FORWARD ? TopAbs_REVERSED : + TopAbs_FORWARD); + occ_surface->set_TopoDS_Face(*topoface); + surface_list.append(occ_surface); + } + PRINT_INFO( "Modified volume\n" ); + } + else + PRINT_WARNING( "Volume was not modified\n" ); + } + face_list = surface_list; + return CUBIT_SUCCESS; +} + + +//=============================================================================== +// Function : sweep_translational +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 09/08 +//=============================================================================== +CubitStatus OCCModifyEngine:: sweep_translational( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + const CubitVector& sweep_vector, + double draft_angle, //in Radius + int draft_type, //RightCorner=1 or RoundCorner =2 + bool switchside,//not used, shell and surfaces are one sided, not like Acis + bool rigid, //not used here, in Acis, it means whether the end surface is + // parallel to the starting surface, or perpendicular to the path + Surface* stop_surf, + BodySM* to_body) const +{ + //in OCC, there's no sweep surface with draft option, this can be done by + //creating draft shell then make solid to achieve. + //while if draft_angle is 0, and stop_surf = 0, to_body = 0 + // directly use sweep functions. + TopoDS_Shape *stop_shape = NULL; + if(stop_surf) + { + OCCSurface* occ_surface = CAST_TO(stop_surf, OCCSurface); + stop_shape = occ_surface->get_TopoDS_Face(); + } + else if(to_body) + { + OCCBody* occ_body = CAST_TO(to_body, OCCBody); + if(occ_body->is_sheet_body()) + stop_shape = occ_body->my_sheet_surface()->get_TopoDS_Face(); + else if(occ_body->shell()) + stop_shape = occ_body->shell()->get_TopoDS_Shell(); + else + stop_shape = occ_body->get_TopoDS_Shape(); + } + + gp_Dir adir(sweep_vector.x(), sweep_vector.y(), sweep_vector.z()); + gp_Vec aVec(sweep_vector.x(), sweep_vector.y(), sweep_vector.z()); + + for (int i = ref_ent_list.size(); i > 0; i--) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + //Make copy of the surface for later to build solid. + OCCSurface* surface = CAST_TO(ref_ent, OCCSurface); + TopoDS_Shape toposhape ; + if(surface != NULL) + { + CubitStatus stat = get_sweepable_toposhape(surface, &sweep_vector, toposhape); + if(!stat) + continue; + } + OCCCurve* curve = CAST_TO(ref_ent, OCCCurve); + if(curve != NULL) + { + CubitStatus stat = get_sweepable_toposhape(curve, toposhape); + if(!stat) + continue; + } + + DLIList<TopologyBridge*> tbs; + //create the draft or the sweep + if(stop_shape == NULL && draft_angle == 0.) + { + BRepSweep_Prism swept(toposhape, aVec); + TopoDS_Shape new_shape = swept.Shape(); + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if (bodysm) + result_body_list.append(bodysm); + continue; + } + + BRepOffsetAPI_MakeDraft draft(toposhape, adir, draft_angle); + BRepBuilderAPI_TransitionMode Cornertype; + if(draft_type == 1) + Cornertype = BRepBuilderAPI_RightCorner; + else if(draft_type == 2) + Cornertype = BRepBuilderAPI_RoundCorner; + + draft.SetOptions(Cornertype); + if(stop_shape) + draft.Perform(*stop_shape); + else + draft.Perform(sweep_vector.length()); + TopoDS_Shape new_shape = draft.Shape(); + + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if(bodysm && surface != NULL) //only gets swept side and original surfaces + { + //get surfaces from the shell body and create a top surface to + //make a swept solid. + OCCShell* occ_shell = CAST_TO(bodysm, OCCBody)->shell(); + if(!occ_shell) + { + PRINT_WARNING("Sweep surface failed inside OCC engine.\n"); + return CUBIT_FAILURE; + } + DLIList<OCCCoFace*> cofaces = occ_shell->cofaces(); + DLIList<Surface*> surface_list; + for(int i = 0; i < cofaces.size(); i++) + surface_list.append(cofaces.get_and_step()->surface()); + + //create the top surface from edges. + DLIList<OCCCoEdge*> coedges; + for(int i = 0; i < surface_list.size(); i++) + CAST_TO(surface_list.get_and_step(), OCCSurface)->get_coedges(coedges); + for(int i = 0; i < coedges.size(); i++) + { + OCCCoEdge* coedge = coedges[i]; + if(coedge == NULL) + continue; + for(int j = i+1; j < coedges.size(); j++) + { + OCCCoEdge* temp_coedge = coedges[j]; + if(temp_coedge == NULL) + continue; + if(coedge->curve() == temp_coedge->curve() && + coedge->sense() != temp_coedge->sense()) + { + coedges.move_to(coedge); + coedges.change_to((OCCCoEdge*)NULL); + coedges.move_to(temp_coedge); + coedges.change_to((OCCCoEdge*)NULL); + } + } + } + coedges.remove_all_with_value(NULL); + assert(coedges.size() > 0); + DLIList<Curve*> curves; + for(int i = 0; i < coedges.size(); i++) + curves.append(coedges.get_and_step()->curve()); + + Surface* surf = make_Surface(PLANE_SURFACE_TYPE, curves); + if(!surf) + surf = make_Surface(BEST_FIT_SURFACE_TYPE, curves); + if(!surf) + { + PRINT_ERROR("Can't calculate for the top surface.\n"); + continue; + } + surface_list.append(surf); + DLIList<BodySM*> bodies; + create_solid_bodies_from_surfs(surface_list, bodies); + + if(bodies.size() == 1) + bodysm = bodies.get(); + else + { + PRINT_WARNING("Sweep surface failed in creating solid.\n"); + return CUBIT_FAILURE; + } + } + if (bodysm) + result_body_list.append(bodysm); + } + return CUBIT_SUCCESS; +} + +CubitStatus OCCModifyEngine::get_sweepable_toposhape(OCCCurve*& curve, + TopoDS_Shape& toposhape)const +{ + DLIList<OCCLoop*> loops; + loops = curve->loops(); + if( loops.size()) //not a free curve + { + //copy the curve + Curve* c_curve = make_Curve(curve); + if(c_curve) + curve = CAST_TO(c_curve, OCCCurve); + else + { + PRINT_ERROR("Can't copy the curve for sweep.\n"); + return CUBIT_FAILURE; + } + } + TopoDS_Edge *edge = curve->get_TopoDS_Edge( ); + toposhape = BRepBuilderAPI_MakeWire(*edge); + return CUBIT_SUCCESS; +} + +CubitStatus OCCModifyEngine::get_sweepable_toposhape(OCCSurface*& surface, + const CubitVector* sweep_v_p, + TopoDS_Shape& toposhape)const +{ + GeometryEntity* ref_ent = NULL; + //Make copy of the surface if it's not a sheet surface. + Surface* c_surface = NULL; + if(surface != NULL) + { + //check if the surface is sheet body, if not, copy it. + if(surface->my_body() == NULL) //not a sheet body + { + c_surface = make_Surface(surface); + if (c_surface == NULL) + { + PRINT_ERROR("Cannot copy surface in sweep_translational.\n"); + return CUBIT_FAILURE; + } + surface = CAST_TO(c_surface, OCCSurface); + } + + if(sweep_v_p) + { + CubitVector center = surface->center_point(); + CubitVector normal; + surface->closest_point(center,NULL,&normal); + CubitVector sweep_vector = *sweep_v_p; + if(normal % sweep_vector > 0) + { + DLIList<Surface*> surfaces; + surfaces.append(surface); + flip_normals(surfaces); + surface = CAST_TO(surfaces.get(), OCCSurface); + ref_ent = (GeometryEntity *)surface; + } + + else if(normal % sweep_vector == 0) + { + PRINT_ERROR("Sweeping direction should not be on the surface.\n"); + return CUBIT_FAILURE; + } + } + else + ref_ent = (GeometryEntity *)surface; + + if(surface->my_body() != NULL) //sheet body + { + delete surface->my_body(); + delete surface->my_shell(); + delete surface->my_lump(); + surface->set_shell(NULL); + surface->set_lump(NULL); + surface->set_body(NULL); + } + + TopoDS_Shape* toposhape_prt = + OCCQueryEngine::instance()->get_TopoDS_Shape_of_entity(ref_ent); + + if(!toposhape_prt) + { + PRINT_WARNING("GeometryEntity without TopoDS_Shape found.\n"); + return CUBIT_FAILURE; + } + toposhape = *toposhape_prt; + } + return CUBIT_SUCCESS; +} +//=============================================================================== +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 10/08 +//=============================================================================== +CubitStatus OCCModifyEngine:: sweep_perpendicular( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + double distance, + double draft_angle, + int draft_type, + bool switchside, //has no effect + bool rigid, //has no effect + Surface* stop_surf, + BodySM* to_body) const +{ + //find the vector perpendicular to the ref_ent normal, and sweep_translate + //the 'distance' along this vector + DLIList<GeometryEntity*> edge_list; + CubitVector vec; + for(int i = 0; i < ref_ent_list.size(); i++) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + Surface *face = CAST_TO(ref_ent, Surface); + Curve* edge = CAST_TO(ref_ent, Curve); + DLIList<GeometryEntity*> face_list; + if(face != NULL) + { + OCCSurface* occ_face = CAST_TO(face, OCCSurface); + CubitVector center = occ_face->center_point(); + CubitVector closest_p, unit_normal; + CubitStatus stat = + occ_face->closest_point(center, &closest_p, &unit_normal); + if(stat) + { + vec = distance * unit_normal; + face_list.append(ref_ent); + stat = sweep_translational(face_list, result_body_list, vec, + draft_angle, draft_type, switchside, + rigid, stop_surf, to_body); + } + } + else if (edge != NULL) + { + edge_list.append(ref_ent); + } + } + if(edge_list.size()) + PRINT_ERROR("Curves cannot be swept perpendicularly, please use the vector sweep.\n"); + + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : sweep_rotational +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 10/08 +//=============================================================================== +CubitStatus OCCModifyEngine:: sweep_rotational( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + const CubitVector& point, + const CubitVector& direction, + double angle, //in radians + int steps, //not used + double draft_angle, //not used + int draft_type, //not used + bool switchside, //not used + bool make_solid, + bool rigid, //not used + Surface* stop_surf, //not used + BodySM* to_body ) const //not used +{ + gp_Dir adir(direction.x(), direction.y(), direction.z()); + gp_Pnt pt = gp_Pnt( point.x(), point.y(), point.z()); + gp_Ax1 axis = gp_Ax1(pt, adir); + + gp_Lin line = gp_Lin(axis); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(line); + OCCCurve* acurve = new OCCCurve(&edge); + assert(acurve); + + CubitVector start; + CubitVector end; + + for (int i = ref_ent_list.size(); i > 0; i--) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + //Make copy of the surface or curve for later to build solid. + OCCSurface* surface = CAST_TO(ref_ent, OCCSurface); + OCCCurve* curve = CAST_TO(ref_ent, OCCCurve); + TopoDS_Shape toposhape ; + if(surface != NULL) + { + CubitStatus stat = get_sweepable_toposhape(surface, (CubitVector*)NULL, toposhape); + if(!stat) + continue; + //only non-intersecting of surface and axis can be swept. + DLIList<CubitVector*> intersect_pts; + OCCQueryEngine::instance()->get_intersections(acurve, surface, + intersect_pts, CUBIT_TRUE); + if(intersect_pts.size() > 0) + { + PRINT_ERROR("Only surfaces with no intersection point with the axis can be revolve-swept.\n"); + continue; + } + } + else if(curve != NULL) + { + CubitStatus stat = get_sweepable_toposhape(curve, toposhape); + if(!stat) + continue; + //closed curve can't intersect with the axis, while open curve can only + //intersect the axis at the end points. + //only curve not intersecting with axis in curve's middle locations + //can be revolved + DLIList<CubitVector*> intersect_pts; + OCCQueryEngine::instance()->get_intersections(curve, acurve, + intersect_pts, CUBIT_TRUE, CUBIT_TRUE); + if(!toposhape.Closed()) + { + //get start and end points + DLIList<OCCPoint*> point_list; + curve->get_points(point_list); + assert(2 == point_list.size()); + GeometryType type = curve->geometry_type(); + start = point_list.get_and_step()->coordinates(); + end = point_list.get()->coordinates(); + CubitBoolean start_int = CUBIT_FALSE; + CubitBoolean end_int = CUBIT_FALSE; + if(intersect_pts.size() > 0) + { + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + CubitBoolean non_int = CUBIT_FALSE; + for(int i = 0; i < intersect_pts.size(); i++) + { + CubitVector prt = *(intersect_pts.get_and_step()); + if(prt.distance_between(start) > tol && + prt.distance_between(end) > tol) + { + non_int = CUBIT_TRUE; + PRINT_ERROR("Only curves with no intersection point with the axis can be revolve-swept.\n"); + break; + } + else if(prt.distance_between(start) <= tol) + start_int = CUBIT_TRUE; + else if(prt.distance_between(end) <= tol) + end_int = CUBIT_TRUE; + } + if(non_int) + continue; + if(start_int && end_int && type == STRAIGHT_CURVE_TYPE) + { + PRINT_ERROR("Sweep along curve itself is not allowed.\n"); + continue; + } + } + } + else + { + if(intersect_pts.size() > 0) + { + PRINT_ERROR("Only curves with no intersection point with the axis can be revolve-swept.\n"); + continue; + } + } + } + else + { + PRINT_ERROR("Only surface or curve can be revolve-swept.\n"); + continue; + } + TopoDS_Shape new_shape; + DLIList<TopologyBridge*> tbs; + if(make_solid && curve != NULL ) + //giving an open wire and want a solid + { + if(!toposhape.Closed()) + { + //project the start and end points onto the axis + CubitBoolean start_closed = CUBIT_FALSE; + CubitBoolean end_closed = CUBIT_FALSE; + if(acurve->point_containment(start) != CUBIT_PNT_OFF) + start_closed = CUBIT_TRUE; + if(acurve->point_containment(end) != CUBIT_PNT_OFF) + end_closed = CUBIT_TRUE; + CubitVector start_proj, end_proj; + TopoDS_Edge edge1, edge2; + BRepBuilderAPI_MakeWire m_wire; + if(!start_closed) + { + acurve->closest_point(start, start_proj); + gp_Pnt pt1 = gp_Pnt( start.x(), start.y(), start.z()); + gp_Pnt pt2 = gp_Pnt( start_proj.x(), start_proj.y(), start_proj.z()); + edge1 = BRepBuilderAPI_MakeEdge(pt1, pt2); + m_wire.Add(edge1); + m_wire.Add(TopoDS::Wire(toposhape)); + } + else + { + m_wire.Add(TopoDS::Wire(toposhape)); + start_proj = start; + } + + if(!end_closed) + { + acurve->closest_point(end,end_proj); + gp_Pnt pt1 = gp_Pnt( end.x(), end.y(), end.z()); + gp_Pnt pt2 = gp_Pnt( end_proj.x(), end_proj.y(), end_proj.z()); + edge2 = BRepBuilderAPI_MakeEdge(pt1, pt2); + m_wire.Add(edge2); + } + + else + end_proj = end; + + gp_Pnt pt1 = gp_Pnt( end_proj.x(), end_proj.y(), end_proj.z()); + gp_Pnt pt2 = gp_Pnt( start_proj.x(), start_proj.y(), start_proj.z()); + TopoDS_Edge edge3 = BRepBuilderAPI_MakeEdge(pt2, pt1); + m_wire.Add(edge3); + + TopoDS_Wire wire = m_wire.Wire(); + toposhape = BRepBuilderAPI_MakeFace(wire); + } + else //closed + { + TopoDS_Wire wire = TopoDS::Wire(toposhape); + toposhape = BRepBuilderAPI_MakeFace(wire); + } + } + BRepSweep_Revol revol(toposhape, axis, angle); + new_shape = revol.Shape(); + + tbs += OCCQueryEngine::instance()->populate_topology_bridge(new_shape); + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if (bodysm) + result_body_list.append(bodysm); + continue; + } + OCCQueryEngine::instance()->delete_solid_model_entities(acurve); + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : sweep_along_curve +// Member Type: PUBLIC +// Description: The ref_edge_list must provide a list of curves which are +// connected, and making G1 continuous wire. +// Author : Jane Hu +// Date : 10/08 +//=============================================================================== +CubitStatus OCCModifyEngine::sweep_along_curve( + DLIList<GeometryEntity*>& ref_ent_list, + DLIList<BodySM*>& result_body_list, + DLIList<Curve*>& ref_edge_list, + double draft_angle, //only used for straight curve case + int draft_type, //only used for straight curve case + bool rigid, //not used + Surface* stop_surf, //not used + BodySM* to_body) const //not used +{ + //make wire out of ref_edge_list + BRepBuilderAPI_MakeWire awire; + TopTools_ListOfShape L; + OCCCurve* occ_curve = NULL; + GeometryType type; + int num_curve = 0; + for(int i = 0; i < ref_edge_list.size(); i++) + { + Curve* curve = ref_edge_list.get_and_step(); + occ_curve = CAST_TO(curve, OCCCurve); + if(!occ_curve) + continue; + TopoDS_Edge* topoedge = occ_curve->get_TopoDS_Edge( ); + BRepBuilderAPI_Copy api_copy(*topoedge); + TopoDS_Shape newShape = api_copy.ModifiedShape(*topoedge); + L.Append(newShape); + type = occ_curve->geometry_type(); + num_curve++; + } + if(L.IsEmpty()) + { + PRINT_ERROR("There's no valid sweeping path.\n"); + return CUBIT_FAILURE; + } + + if(num_curve == 1 && type == STRAIGHT_CURVE_TYPE && draft_angle != 0.0) + { + DLIList<OCCPoint*> point_list; + occ_curve->get_points(point_list); + CubitVector v1 = point_list.get_and_step()->coordinates(); + CubitVector v2 = point_list.get()->coordinates(); + CubitVector sweep_vector = v2-v1; + return sweep_translational(ref_ent_list,result_body_list,sweep_vector, + draft_angle, draft_type, CUBIT_FALSE, + rigid, stop_surf, to_body); + } + awire.Add(L); + TopoDS_Wire wire; + wire = awire.Wire(); + + BRepTools_WireExplorer it(wire); + int num_edges = 0; + for(; it.More(); it.Next()) + num_edges++; + + BRepLib_FuseEdges fuser(wire); + fuser.SetConcatBSpl(); + fuser.Perform(); + TopoDS_Shape spline = fuser.Shape(); + wire = TopoDS::Wire(spline); + + DLIList<TopologyBridge*> tbs; + for (int i = ref_ent_list.size(); i > 0; i--) + { + GeometryEntity *ref_ent = ref_ent_list.get_and_step(); + //Make copy of the surface or curve for later to build solid. + OCCSurface* surface = CAST_TO(ref_ent, OCCSurface); + OCCCurve* curve = CAST_TO(ref_ent, OCCCurve); + TopoDS_Shape toposhape ; + if(surface != NULL) + { + CubitStatus stat = get_sweepable_toposhape(surface, (CubitVector*)NULL, toposhape); + if(!stat) + continue; + } + else if(curve != NULL) + { + CubitStatus stat = get_sweepable_toposhape(curve, toposhape); + if(!stat) + continue; + } + + //sweep along the wire + BRepOffsetAPI_MakePipe maker(wire, toposhape); + if(!maker.IsDone()) + { + PRINT_ERROR("Can't sweep along the provided curve(s).\n"); + continue; + } + TopoDS_Shape newShape = maker.Shape(); + + tbs += OCCQueryEngine::instance()->populate_topology_bridge(newShape); + assert(tbs.size() == 1); + + BodySM* bodysm = CAST_TO(tbs.get(), BodySM); + if (bodysm) + result_body_list.append(bodysm); + continue; + } + return CUBIT_SUCCESS; +} + +//HEADER- Webcut-related functions + +//=============================================================================== +// Function : webcut +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut(DLIList<BodySM*>& webcut_body_list, + const CubitVector &v1, + const CubitVector &v2, + const CubitVector &v3, + DLIList<BodySM*>& results_list, + bool imprint ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut(DLIList<BodySM*>& /*webcut_body_list*/, + BodySM const* /*tool_body*/, + DLIList<BodySM*>& /*results_list*/, + bool /*imprint*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_across_translate +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_across_translate( DLIList<BodySM*>& /*body_list*/, + Surface* /*plane_surf1*/, + Surface* /*plane_surf2*/, + DLIList<BodySM*>& /*results_list*/, + bool /*imprint*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_sheet +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_sheet(DLIList<BodySM*> & /*webcut_body_list*/, + BodySM * /*sheet_body*/, + DLIList<BodySM*> & /*new_bodies*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_extended_surf +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_extended_surf(DLIList<BodySM*> & /*webcut_body_list*/, + Surface * /*extend_from*/, + DLIList<BodySM*> & /*new_bodies*/, + int & /*num_cut*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_cylinder +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_cylinder(DLIList<BodySM*> &webcut_body_list, + double radius, + const CubitVector &axis, + const CubitVector ¢er, + DLIList<BodySM*>& results_list, + bool imprint ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_brick +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_brick( + DLIList<BodySM*>& /*webcut_body_list*/, + const CubitVector &/*center*/, + const CubitVector* /*axes[3]*/, + const CubitVector &/*extension*/, + DLIList<BodySM*> &/*results_list*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_planar_sheet +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_planar_sheet( + DLIList<BodySM*>& /*webcut_body_list*/, + const CubitVector &/*center*/, + const CubitVector* /*axes[2]*/, + double /*width*/, + double /*height*/, + DLIList<BodySM*> &/*results_list*/, + bool /*imprint*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : webcut_with_curve_loop +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::webcut_with_curve_loop( + DLIList<BodySM*> &/*webcut_body_list*/, + DLIList<Curve*> &/*ref_edge_list*/, + DLIList<BodySM*>& /*results_list*/, + bool /*imprint*/) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : section +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 11/08 +//=============================================================================== +CubitStatus OCCModifyEngine::section( DLIList<BodySM*> §ion_body_list, + const CubitVector &point_1, + const CubitVector &point_2, + const CubitVector &point_3, + DLIList<BodySM*>& new_body_list, + bool keep_normal_side, + bool keep_old, + bool keep_both_sides) +{ + if (keep_both_sides == CUBIT_TRUE ) + { + PRINT_ERROR("keeping both sides of section is not implemented.\n"); + return CUBIT_FAILURE; + } + + //Calculate normal of the section plan + CubitVector v1, v2, normal; + v1 = point_2 - point_1; + v2 = point_3 - point_1; + normal = ~(v1 * v2); + if(normal.length() != 1) + { + PRINT_ERROR("The three points are co-linear, and can't be used as a cutting plane.\n"); + return CUBIT_FAILURE; + } + + if(keep_normal_side) + normal *= -1; + + gp_Pnt pt = gp_Pnt( point_1.x(), point_1.y(), point_1.z()); + gp_Dir normal_dir(normal.x(), normal.y(), normal.z()); + gp_Pln plane(pt, normal_dir); + gp_Vec vec(normal_dir); + pt = pt.Translated(vec); + + TopoDS_Face face = BRepBuilderAPI_MakeFace(plane); + TopoDS_Solid solid = BRepPrimAPI_MakeHalfSpace(face, pt); + + DLIList<CubitBoolean> is_tool_volume; + is_tool_volume.append(CUBIT_TRUE); + DLIList<CubitBox*> tool_boxes ; + Bnd_Box box; + BRepBndLib::Add(solid, box); + double min[3], max[3]; + box.Get(min[0], min[1], min[2], max[0], max[1], max[2]); + CubitBox* cBox = new CubitBox(min, max); + + tool_boxes.append(cBox); + DLIList<TopoDS_Shape*> solids; + solids.append(&solid); + CubitStatus stat = do_subtract(section_body_list, solids, is_tool_volume, + &tool_boxes, new_body_list, keep_old) ; + delete cBox; + return stat; +} + +//=============================================================================== +// Function : split_body +// Member Type: PUBLIC +// Description: Splits multiple lumps in one body into separate bodies +// Author : Corey Ernst +// Date : 08/04 +//=============================================================================== +CubitStatus OCCModifyEngine::split_body( BodySM *body_ptr, + DLIList<BodySM*> &new_bodies ) +{ + return CUBIT_SUCCESS; +} + + +//=============================================================================== +// Function : reverse_body +// Member Type: PUBLIC +// Description: Turn body inside-out +// Author : Jason Kraftcheck +// Date : 05/25/04 +//=============================================================================== +CubitStatus OCCModifyEngine::reverse_body( BodySM* body_ptr ) +{ + return CUBIT_SUCCESS; +} + + + +//=============================================================================== +// Function : split_periodic +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::split_periodic( BodySM * /*body_ptr*/, + BodySM *& /*new_body*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : regularize_body +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::regularize_body( BodySM * /*body_ptr*/, + BodySM *& /*new_body_ptr*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : regularize_refentity +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::regularize_entity( GeometryEntity * /*old_entity_ptr*/, + BodySM *& /*new_body_ptr*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : offset_curves +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::offset_curves( DLIList<Curve*>& /*ref_edge_list*/, + DLIList<Curve*>&, + double /*offset_distance*/, + const CubitVector& /*offset_direction*/, + int /*gap_type*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : trim_curve +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +Curve* OCCModifyEngine::trim_curve( Curve* /*trim_curve*/, + const CubitVector& /*trim_vector*/, + const CubitVector& /*keep_vector*/, + bool ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return 0; +} + +//=============================================================================== +// Function : create_body_from_surfs +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 4/22/08 +//=============================================================================== +CubitStatus OCCModifyEngine::create_solid_bodies_from_surfs(DLIList<Surface*> & ref_face_list, + DLIList<BodySM*>& new_bodies, + bool keep_old, + bool heal) const +{ + //keep_old and heal are ignored, always delete old. + //all surfaces should be stand along surface bodies or shell bodies' surface + Lump* lump = make_Lump(ref_face_list); + if (!lump) + return CUBIT_FAILURE; + + new_bodies.append(CAST_TO(lump, OCCLump)->get_body()); + return CUBIT_SUCCESS; +} + +//=============================================================================== +// Function : create_arc_three +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 12/08 +//=============================================================================== +Curve* OCCModifyEngine::create_arc_three( Point* pt1, + Point* pt2, + Point* pt3, + bool full ) +{ + if(!full) + { + CubitVector v2(pt2->coordinates()); + return make_Curve(ARC_CURVE_TYPE,pt1,pt3, &v2, CUBIT_FORWARD); + } + else + { + CubitVector v1(pt1->coordinates()); + CubitVector v2(pt2->coordinates()); + CubitVector v3(pt3->coordinates()); + + gp_Pnt gp_pt1(v1.x(),v1.y(), v1.z()); + gp_Pnt gp_pt2(v2.x(),v2.y(), v2.z()); + gp_Pnt gp_pt3(v3.x(),v3.y(), v3.z()); + + Handle(Geom_Circle) curve_ptr; + curve_ptr = GC_MakeCircle(gp_pt1,gp_pt2,gp_pt3); + + OCCPoint* occ_pt1 = CAST_TO(const_cast<Point*>(pt1),OCCPoint); + TopoDS_Vertex * vt1 = occ_pt1->get_TopoDS_Vertex(); + TopoDS_Edge new_edge = BRepBuilderAPI_MakeEdge(curve_ptr, *vt1, *vt1); + return OCCQueryEngine::instance()->populate_topology_bridge(new_edge); + } +} + +//=============================================================================== +// Function : create_arc_three +// Member Type: PUBLIC +// Description: +// Author : Jane Hu +// Date : 12/08 +//=============================================================================== +Curve* OCCModifyEngine::create_arc_three( Curve* curve1, + Curve* curve2, + Curve* curve3, + bool full ) +{ + OCCCurve* occ_crv1 = CAST_TO(curve1, OCCCurve); + OCCCurve* occ_crv2 = CAST_TO(curve2, OCCCurve); + OCCCurve* occ_crv3 = CAST_TO(curve3, OCCCurve); + GeometryType type1 = occ_crv1->geometry_type(); + GeometryType type2 = occ_crv2->geometry_type(); + GeometryType type3 = occ_crv3->geometry_type(); + if(type1 != STRAIGHT_CURVE_TYPE || type2 != STRAIGHT_CURVE_TYPE || + type3 != STRAIGHT_CURVE_TYPE) + { + PRINT_WARNING("Need three straight curves to calculate incenter.\n"); + return (Curve*) NULL; + } + + //0.check that non of the curves are parallel of each other. + DLIList<CubitVector*> intscts; + CubitVector vt1, vt2, vt3; + CubitBoolean none = CUBIT_FALSE; + OCCQueryEngine::instance()->get_intersections(curve1, curve2, intscts,none,none); + vt1 = *intscts.get(); + intscts.clean_out(); + OCCQueryEngine::instance()->get_intersections(curve2,curve3, intscts,none,none); + vt2 = *intscts.get(); + intscts.clean_out(); + OCCQueryEngine::instance()->get_intersections(curve3, curve1, intscts,none,none); + vt3 = *intscts.get(); + + double u, u11, u12, u21, u22, u31, u32; + u12 = occ_crv1->u_from_position(vt1); + u11 = occ_crv1->u_from_position(vt3); + if(u12 < u11) + { + u = u12; + u12 = u11; + u11 = u; + } + u22 = occ_crv2->u_from_position(vt1); + u21 = occ_crv2->u_from_position(vt2); + if(u22 < u21) + { + u = u22; + u22 = u21; + u21 = u; + } + u32 = occ_crv3->u_from_position(vt2); + u31 = occ_crv3->u_from_position(vt3); + if(u32 < u31) + { + u = u32; + u32 = u31; + u31 = u; + } + CubitVector tangent1, tangent2, tangent3; + occ_crv1->get_tangent(vt1, tangent1); + occ_crv2->get_tangent(vt2, tangent2); + occ_crv3->get_tangent(vt3, tangent3); + + CubitVector normal1 = tangent1 * tangent2; + CubitVector normal2 = tangent2 * tangent3; + CubitVector normal3 = tangent3 * tangent1; + double tol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); + if( normal1.length()< tol || normal2.length()< tol || + normal3.length() < tol ) + { + PRINT_WARNING("Three curves must be able to form a triangle.\n"); + return (Curve*) NULL; + } + + //normals must parallel to each other, meaning all curves must be on + //the same plane. + normal1.normalize(); + normal2.normalize(); + normal3.normalize(); + + CubitVector parallel1 = normal1 * normal2; + CubitVector parallel2 = normal2 * normal3; + CubitVector parallel3 = normal3 * normal1; + if(parallel1.length() > tol || parallel2.length() > tol || + parallel3.length() > tol) + { + PRINT_WARNING("Three curves must be able to form a triangle.\n"); + return (Curve*) NULL; + } + //1.find the angle between each of the two curves + double angle1, angle2, angle3; + angle1 = tangent1.interior_angle(tangent2); + angle2 = tangent2.interior_angle(tangent3); + angle3 = tangent3.interior_angle(tangent1); + + //2.create curves to bisection each of the angle passing through the + // vertices of the triangle + CubitVector t_curve11 = + vectorRotate(angle1/2.0, normal1, tangent1); + t_curve11.normalize(); + CubitVector p11 = vt1+t_curve11; + + CubitVector t_curve12 = + vectorRotate(90.0 - angle1/2.0, -normal1, tangent1); + t_curve12.normalize(); + CubitVector p12 = vt1 + t_curve12; + + CubitVector t_curve21 = + vectorRotate(angle2/2.0, normal2, tangent2); + t_curve21.normalize(); + CubitVector p21 = vt2 + t_curve21; + + CubitVector t_curve22 = + vectorRotate(90.0 - angle2/2.0, -normal2, tangent2); + t_curve22.normalize(); + CubitVector p22 = vt2 + t_curve22; + + CubitVector t_curve31 = + vectorRotate(angle3/2.0, normal3, tangent3); + t_curve31.normalize(); + CubitVector p31 = vt3 + t_curve31; + + CubitVector t_curve32 = + vectorRotate(90.0 - angle3/2.0, -normal3, tangent3); + t_curve32.normalize(); + CubitVector p32 = vt3 + t_curve32; + + //3. find the intersection of each of the bisection curve with the third curve + CubitVector int_pt1, int_pt2, int_pt3; + intscts.clean_out(); + OCCQueryEngine::instance()->get_intersections(curve3, vt1, p11, intscts,none,none); + CubitVector int_pt = *intscts.pop(); + u = occ_crv3->u_from_position (int_pt); + if(u >= u31-tol && u <= u32+tol) //found intersection point + int_pt1 = int_pt; + else + { + OCCQueryEngine::instance()->get_intersections(curve3, vt1, p12, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv3->u_from_position (int_pt); + assert(u >= u31-tol && u <= u32+tol); + int_pt1 = int_pt; + } + + OCCQueryEngine::instance()->get_intersections(curve1, vt2, p21, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv1->u_from_position (int_pt); + if(u >= u11-tol && u <= u12+tol) //found intersection point + int_pt2 = int_pt; + else + { + OCCQueryEngine::instance()->get_intersections(curve1, vt2, p22, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv1->u_from_position (int_pt); + assert(u >= u11-tol && u <= u12+tol); + int_pt2 = int_pt; + } + + OCCQueryEngine::instance()->get_intersections(curve2, vt3, p31, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv2->u_from_position (int_pt); + if(u >= u21-tol && u <= u22+tol) //found intersection point + int_pt3 = int_pt; + else + { + OCCQueryEngine::instance()->get_intersections(curve2, vt3, p32, intscts,none,none); + int_pt = *intscts.pop(); + u = occ_crv2->u_from_position (int_pt); + assert(u >= u21-tol && u <= u22+tol); + int_pt3 = int_pt; + } + //4. use the 3 intersection points to find the arc or circle. + OCCPoint occ_p1(int_pt1); + OCCPoint occ_p2(int_pt2); + OCCPoint occ_p3(int_pt3); + return create_arc_three(&occ_p1, &occ_p2, &occ_p3, full); +} + +//=============================================================================== +// Function : create_arc_center_edge +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +Curve* OCCModifyEngine::create_arc_center_edge( Point* /*ref_vertex1*/, + Point* /*ref_vertex2*/, + Point* /*ref_vertex3*/, + const CubitVector& /*normal*/, + double /*radius*/, + bool /*full*/ ) +{ + return NULL; +} + +CubitStatus +OCCModifyEngine::create_curve_combine( DLIList<Curve*>& curve_list, + Curve *&new_curve_ptr ) +{ + PRINT_ERROR("Curve combine is not implemented for facet based models\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : get_gqe +// Member Type: PUBLIC +// Description: get the facet geometry query engince instance pointer +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +GeometryQueryEngine *OCCModifyEngine::get_gqe() +{ + return OCCQueryEngine::instance(); +} + +//=============================================================================== +// Function : is_modify_engine +// Member Type: PUBLIC +// Description: return CUBIT_TRUE if the tb_ptr belongs to this modify engine +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitBoolean OCCModifyEngine::is_modify_engine(const TopologyBridge *tb_ptr) const +{ + return tb_ptr->get_geometry_query_engine() == OCCQueryEngine::instance(); +} + +//=============================================================================== +// Function : get_offset_intersections +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::get_offset_intersections( Curve* /*ref_edge1*/, + Curve* /*ref_edge2*/, + DLIList<CubitVector*>& /*intersection_list*/, + double /*offset*/, + CubitBoolean /*ext_first*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : get_offset_intersections +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::get_offset_intersections( Curve* /*ref_edge_ptr*/, + Surface* /*ref_face_ptr*/, + DLIList<CubitVector*> & /*intersection_list*/, + double /*offset*/, + CubitBoolean /*ext_surf*/ ) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : surface_intersection +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::surface_intersection( Surface * /*surface1_ptr*/, + Surface * /*surface2_ptr*/, + DLIList<Curve*> &/*inter_graph*/, + const double /*tol*/) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//=============================================================================== +// Function : get_mid_plane +// Member Type: PUBLIC +// Description: +// Author : John Fowler +// Date : 10/02 +//=============================================================================== +CubitStatus OCCModifyEngine::get_mid_plane( const CubitVector & /*point_1*/, + const CubitVector & /*point_2*/, + const CubitVector & /*point_3*/, + BodySM * /*body_to_trim_to*/, + BodySM *& /*midplane_body*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::get_spheric_mid_surface( Surface* surface_ptr1, + Surface* surface_ptr2, + BodySM* body_to_trim_to, + BodySM*& midsurface_body ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::get_conic_mid_surface( Surface* surface_ptr1, + Surface* surface_ptr2, + BodySM* body_to_trim_to, + BodySM*& midsurface_body ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::get_toric_mid_surface( Surface* surface_ptr1, + Surface* surface_ptr2, + BodySM* body_to_trim_to, + BodySM*& midsurface_body ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_chamfer +// Member Type: PUBLIC +// Description: Chamfer curves on solid bodies. The left and right offsets are +// with respect to the curve direction. If the given right offset +// is negative, the left offset is used. Users can preview to +// clarify the meaning of left and right. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_chamfer( DLIList<Curve*> & /*curve_list*/, + double /*left_offset*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + double /*right_offset*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_chamfer +// Member Type: PUBLIC +// Description: Chamfer vertices on solid or sheet bodies. On a solid body +// there can be up to 3 offsets; on a sheet body up to 2 offsets. +// The offsets are in the direction of the supplied edges. If +// multiple vertices are supplied, only one offset value is +// allowed and the edges are not used. +// Author : +// Date : +//============================================================================= +CubitStatus +OCCModifyEngine::tweak_chamfer( DLIList<Point*> & /*point_list*/, + double /*offset1*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + Curve * /*edge1*/, + double /*offset2*/, + Curve * /*edge2*/, + double /*offset3*/, + Curve * /*edge3*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_fillet +// Member Type: PUBLIC +// Description: Create a round fillet (or blend) at the given curves on solid +// bodies. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_fillet( DLIList<Curve*> & /*curve_list*/, + double /*radius*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_fillet +// Member Type: PUBLIC +// Description: Create a round fillet (or blend) at the given curves on a solid +// body. The fillet has a variable radius from the start to the +// end of the curve. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_fillet( Curve * /*curve_ptr*/, + double /*start_radius*/, + double /*end_radius*/, + BodySM *& /*new_bodysm_ptr*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_fillet +// Member Type: PUBLIC +// Description: Create a round fillet (or blend) at the given vertices on sheet +// bodies. +// Author : +// Date : +//============================================================================= +CubitStatus +OCCModifyEngine::tweak_fillet( DLIList<Point*> & /*ref_vertex_list*/, + double /*radius*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean /*preview*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_move +// Member Type: PUBLIC +// Description: Tweak specified faces of a volume or volumes along a vector. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_move( DLIList<Surface*> & /*surface_list*/, + const CubitVector & /*delta*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/ , + CubitBoolean show_preview) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_move +// Member Type: PUBLIC +// Description: Tweak specified curves of a sheet body along a vector. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_move( DLIList<Curve*> & /*curve_list*/, + const CubitVector & /*delta*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_offset +// Member Type: PUBLIC +// Description: Tweak specified faces of a volume or volumes by offsetting +// those faces by the offset distance. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_offset( DLIList<Surface*> & /*surface_list*/, + double /*offset_distance*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_offset +// Member Type: PUBLIC +// Description: Tweak specified curves of a sheet body or bodies by offsetting +// those curves by the offset distance. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_offset( DLIList<Curve*> & /*curve_list*/, + double /*offset_distance*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_remove +// Member Type: PUBLIC +// Description: Function to remove surfaces from a body and then extend the +// remaining surfaces to fill the gap or hole. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_remove( DLIList<Surface*> & /*surface_list*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*extend_adjoining*/, + CubitBoolean /*keep_surface*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_remove +// Member Type: PUBLIC +// Description: Function to remove curves from a sheet body and then extend the +// remaining curves or fill the gap or hole. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_remove( DLIList<Curve*> & /*curve_list*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_target +// Member Type: PUBLIC +// Description: Tweak specified faces of a volume or volumes up to a target +// surface. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_target( DLIList<Surface*> & /*surface_list*/, + DLIList<Surface*> & , + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean /*reverse_flg*/, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_target +// Member Type: PUBLIC +// Description: Tweak specified edges of a surface or set of surfaces (in sheet +// bodies) up to a target surface. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_target( DLIList<Curve*> & /*curve_list*/, + DLIList<Surface*> & /*target_surfs*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean , + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//============================================================================= +// Function : tweak_target +// Member Type: PUBLIC +// Description: Tweak specified edges of a sheet body or bodies up to a target +// curve that is part of a sheet body. The target is a surface +// created by thickening the owning surface of the target curve. +// Author : +// Date : +//============================================================================= +CubitStatus OCCModifyEngine::tweak_target( DLIList<Curve*> & /*curve_list*/, + DLIList<Curve*> & /*target_curve_ptr*/, + DLIList<BodySM*> & /*new_bodysm_list*/, + CubitBoolean, + CubitBoolean /*keep_old_body*/, + CubitBoolean show_preview ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::remove_curve_slivers( BodySM* /*body*/, + double /*lengthlimit*/ ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a net surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_net_surface( DLIList<Surface*>& /*ref_face_list*/, + BodySM *& /*new_body*/, + DLIList<DLIList<CubitVector*>*> & /*vec_lists_u*/, + DLIList<DLIList<CubitVector*>*> & /*vec_lists_v*/, + double /*net_tol*/, + CubitBoolean /*heal*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a net surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_net_surface( DLIList<Curve*>& /*u_curves*/, + DLIList<Curve*>& /*v_curves*/, + BodySM *& /*new_body*/, + double /*net_tol*/, + CubitBoolean /*heal*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates an offset surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_offset_surface( Surface* /*ref_face_ptr*/, + BodySM*& /*new_body*/, + double /*offset_distance*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates an offset body. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_offset_body( BodySM* body_ptr, + BodySM*& new_bodysm, + double offset_distance ) const +{ + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a skin surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_skin_surface( DLIList<Curve*>& /*curves*/, + BodySM*& /*new_body*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a body from lofting surfaces. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::loft_surfaces( Surface * /*face1*/, + const double & /*takeoff1*/, + Surface * /*face2*/, + const double & /*takeoff2*/, + BodySM*& /*new_body*/, + CubitBoolean /*arc_length_option*/, + CubitBoolean /*twist_option*/, + CubitBoolean /*align_direction*/, + CubitBoolean /*perpendicular*/, + CubitBoolean /*simplify_option*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a body by lofting surfaces between bodies. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::loft_surfaces_to_body( Surface * /*face1*/, + const double & /*takeoff1*/, + Surface * /*face2*/, + const double & /*takeoff2*/, + BodySM*& /*new_body*/, + CubitBoolean /*arc_length_option*/, + CubitBoolean /*twist_option*/, + CubitBoolean /*align_direction*/, + CubitBoolean /*perpendicular*/, + CubitBoolean /*simplify_option*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_surface( DLIList<CubitVector*>& /*vec_list*/, + BodySM *& /*new_body*/, + Surface * /*ref_face_ptr*/, + CubitBoolean /*project_points*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +//================================================================================ +// Description: Creates a weld surface. +// Author : Tyronne Lim +// Date : 08/18/03 +//================================================================================ +CubitStatus OCCModifyEngine::create_weld_surface( CubitVector & /*root*/, + Surface * /*ref_face1*/, + double /*leg1*/, + Surface * /*ref_face2*/, + double /*leg2*/, + BodySM *& /*new_body*/ ) const +{ + PRINT_ERROR("Function not implemented in this engine.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_surfaces( + DLIList<BodySM*> &blank_bodies, + DLIList<Surface*> &surfaces, + const CubitVector& sweep_vector, + bool sweep_perp, + bool through_all, + bool outward, + bool up_to_next, + Surface *stop_surf, + Curve *curve_to_sweep_along, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_curves( + DLIList<BodySM*> &blank_bodies, + DLIList<Curve*> &curves, + const CubitVector& sweep_vector, + bool through_all, + Surface *stop_surf, + Curve *curve_to_sweep_along, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_surfaces_rotated( + DLIList<BodySM*> &blank_bodies, + DLIList<Surface*> &surfaces, + const CubitVector &point, + const CubitVector &sweep_axis, + double angle, + Surface *stop_surf, + bool up_to_next, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::webcut_with_sweep_curves_rotated( + DLIList<BodySM*> &blank_bodies, + DLIList<Curve*> &curves, + const CubitVector &point, + const CubitVector &sweep_axis, + double angle, + Surface *stop_surf, + DLIList<BodySM*> &results_list, + CubitBoolean imprint) +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +CubitStatus OCCModifyEngine::scale( BodySM *&body, const CubitVector& factors ) +{ + return OCCQueryEngine::instance()->scale( body, factors ); +} + +CubitStatus OCCModifyEngine::tolerant_imprint( DLIList<BodySM*> &bodies_in, + DLIList<BodySM*> &new_bodies, + DLIList<TopologyBridge*>*, + DLIList<TopologyBridge*>* ) const +{ + PRINT_ERROR("Option not supported for mesh based geometry.\n"); + return CUBIT_FAILURE; +} + +// EOF
participants (1)
-
janehu@mcs.anl.gov