void ProfileBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Shape& support, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir, const double offset) { if ((method == "UpToLast") || (method == "UpToFirst")) { // Check for valid support object if (support.IsNull()) throw Base::ValueError("SketchBased: Up to face: No support in Sketch and no base feature!"); std::vector<Part::cutFaces> cfaces = Part::findAllFacesCutBy(support, sketchshape, dir); if (cfaces.empty()) throw Base::ValueError("SketchBased: Up to face: No faces found in this direction"); // Find nearest/furthest face std::vector<Part::cutFaces>::const_iterator it, it_near, it_far; it_near = it_far = cfaces.begin(); for (it = cfaces.begin(); it != cfaces.end(); it++) if (it->distsq > it_far->distsq) it_far = it; else if (it->distsq < it_near->distsq) it_near = it; upToFace = (method == "UpToLast" ? it_far->face : it_near->face); } // Check whether the face has limits or not. Unlimited faces have no wire // Note: Datum planes are always unlimited TopExp_Explorer Ex(upToFace,TopAbs_WIRE); if (Ex.More()) { // Remove the limits of the upToFace so that the extrusion works even if sketchshape is larger // than the upToFace bool remove_limits = false; for (Ex.Init(sketchshape,TopAbs_FACE); Ex.More(); Ex.Next()) { // Get outermost wire of sketch face TopoDS_Face sketchface = TopoDS::Face(Ex.Current()); TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(sketchface); if (!checkWireInsideFace(outerWire, upToFace, dir)) { remove_limits = true; break; } } // It must also be checked that all projected inner wires of the upToFace // lie outside the sketch shape. If this is not the case then the sketch // shape is not completely covered by the upToFace. See #0003141 if (!remove_limits) { TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(upToFace); for (Ex.Init(upToFace, TopAbs_WIRE); Ex.More(); Ex.Next()) { if (!outerWire.IsSame(Ex.Current())) { BRepProj_Projection proj(TopoDS::Wire(Ex.Current()), sketchshape, -dir); if (proj.More()) { remove_limits = true; break; } } } } if (remove_limits) { // Note: Using an unlimited face every time gives unnecessary failures for concave faces TopLoc_Location loc = upToFace.Location(); BRepAdaptor_Surface adapt(upToFace, Standard_False); // use the placement of the adapter, not of the upToFace loc = TopLoc_Location(adapt.Trsf()); BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface() #if OCC_VERSION_HEX >= 0x060502 , Precision::Confusion() #endif ); if (!mkFace.IsDone()) throw Base::ValueError("SketchBased: Up To Face: Failed to create unlimited face"); upToFace = TopoDS::Face(mkFace.Shape()); upToFace.Location(loc); } } // Check that the upToFace does not intersect the sketch face and // is not parallel to the extrusion direction (for simplicity, supportface is used instead of sketchshape) BRepAdaptor_Surface adapt1(TopoDS::Face(supportface)); BRepAdaptor_Surface adapt2(TopoDS::Face(upToFace)); if (adapt2.GetType() == GeomAbs_Plane) { if (adapt1.Plane().Axis().IsNormal(adapt2.Plane().Axis(), Precision::Confusion())) throw Base::ValueError("SketchBased: Up to face: Must not be parallel to extrusion direction!"); } // We must measure from sketchshape, not supportface, here BRepExtrema_DistShapeShape distSS(sketchshape, upToFace); if (distSS.Value() < Precision::Confusion()) throw Base::ValueError("SketchBased: Up to face: Must not intersect sketch!"); // Move the face in the extrusion direction // TODO: For non-planar faces, we could consider offsetting the surface if (fabs(offset) > Precision::Confusion()) { if (adapt2.GetType() == GeomAbs_Plane) { gp_Trsf mov; mov.SetTranslation(offset * gp_Vec(dir)); TopLoc_Location loc(mov); upToFace.Move(loc); } else { throw Base::TypeError("SketchBased: Up to Face: Offset not supported yet for non-planar faces"); } } }
//---------------------------------------------------------------- // Function: TopoDS_Shape level function to update the core Surface // for any movement or Boolean operation of the body. // Author: Jane Hu //---------------------------------------------------------------- CubitStatus OCCSurface::update_OCC_entity(TopoDS_Face& old_surface, TopoDS_Shape& new_surface, BRepBuilderAPI_MakeShape *op, TopoDS_Vertex* removed_vertex, LocOpe_SplitShape* sp) { //set the Wires TopTools_IndexedMapOfShape M, M2; TopoDS_Shape shape, shape2, shape_edge, shape_vertex; TopExp::MapShapes(old_surface, TopAbs_WIRE, M); TopTools_ListOfShape shapes; BRepFilletAPI_MakeFillet2d* test_op = NULL; for (int ii=1; ii<=M.Extent(); ii++) { TopoDS_Wire wire = TopoDS::Wire(M(ii)); TopTools_ListOfShape shapes; if(op) { test_op = dynamic_cast<BRepFilletAPI_MakeFillet2d*>(op); if(!test_op) shapes.Assign(op->Modified(wire)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(wire)); if(!new_surface.IsNull()) TopExp::MapShapes(new_surface,TopAbs_WIRE, M2); } else if(sp) shapes.Assign(sp->DescendantShapes(wire)); if (shapes.Extent() == 1) { shape = shapes.First(); if(M2.Extent() == 1) { shape2 = TopoDS::Wire(M2(1)); if(!shape.IsSame(shape2)) shape = shape2; } else if(M2.Extent() > 1) shape.Nullify(); } else if(shapes.Extent() > 1) shape.Nullify(); else if(op->IsDeleted(wire) || shapes.Extent() == 0) { TopTools_IndexedMapOfShape M_new; TopExp::MapShapes(new_surface, TopAbs_WIRE, M_new); if (M_new.Extent()== 1) shape = M_new(1); else shape.Nullify(); } else { shape = wire; continue; } //set curves BRepTools_WireExplorer Ex; for(Ex.Init(wire); Ex.More();Ex.Next()) { TopoDS_Edge edge = Ex.Current(); if(op && !test_op) { shapes.Assign(op->Modified(edge)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(edge)); } else if(sp) shapes.Assign(sp->DescendantShapes(edge)); if (shapes.Extent() == 1) { //in fillet creating mothod, one edge could generated a face, so check //it here. TopAbs_ShapeEnum type = shapes.First().TShape()->ShapeType(); if(type != TopAbs_EDGE) shape_edge.Nullify(); else shape_edge = shapes.First(); } else if (shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape_edge = it.Value(); OCCQueryEngine::instance()->copy_attributes(edge, shape_edge); } shape_edge.Nullify(); } else if (op->IsDeleted(edge)) shape_edge.Nullify(); else if (test_op) { if(!test_op->IsModified(edge)) shape_edge = edge; else shape_edge = (test_op->Modified(edge)).First(); } else shape_edge = edge; //update vertex TopoDS_Vertex vertex = Ex.CurrentVertex(); shapes.Clear(); if(test_op) assert(removed_vertex != NULL); if(op && ! test_op ) shapes.Assign(op->Modified(vertex)); else if(sp) shapes.Assign(sp->DescendantShapes(vertex)); if (shapes.Extent() == 1) shape_vertex = shapes.First(); else if(shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape_vertex = it.Value(); OCCQueryEngine::instance()->copy_attributes(vertex, shape_vertex); } shape_vertex.Nullify() ; } else if(op->IsDeleted(vertex) || (test_op && vertex.IsSame( *removed_vertex))) shape_vertex.Nullify() ; else shape_vertex = vertex; if(!vertex.IsSame(shape_vertex) ) OCCQueryEngine::instance()->update_OCC_map(vertex, shape_vertex); if (!edge.IsSame(shape_edge)) OCCQueryEngine::instance()->update_OCC_map(edge, shape_edge); } if (!wire.IsSame(shape)) OCCQueryEngine::instance()->update_OCC_map(wire, shape); } double dTOL = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); if (!old_surface.IsSame(new_surface)) { TopAbs_ShapeEnum shapetype = TopAbs_SHAPE; if(!new_surface.IsNull()) shapetype = new_surface.TShape()->ShapeType(); if(shapetype == TopAbs_FACE || new_surface.IsNull()) OCCQueryEngine::instance()->update_OCC_map(old_surface, new_surface); else { TopTools_IndexedMapOfShape M; TopExp::MapShapes(new_surface, TopAbs_FACE, M); TopoDS_Shape new_shape; if(M.Extent() == 1) new_shape = M(1); else if(M.Extent() > 1) { for(int i = 1; i <= M.Extent(); i++) { GProp_GProps myProps; BRepGProp::SurfaceProperties(old_surface, myProps); double orig_mass = myProps.Mass(); gp_Pnt orig_pnt = myProps.CentreOfMass(); BRepGProp::SurfaceProperties(M(i), myProps); double after_mass = myProps.Mass(); gp_Pnt after_pnt = myProps.CentreOfMass(); if(fabs(-after_mass + orig_mass) <= dTOL && orig_pnt.IsEqual(after_pnt, dTOL)) { new_shape = M(i); break; } } } OCCQueryEngine::instance()->update_OCC_map(old_surface, new_shape); } } return CUBIT_SUCCESS; }