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"); } } }
void SketchBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Shape& support, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, const gp_Dir& dir) { if ((method == "UpToLast") || (method == "UpToFirst")) { // Check for valid support object if (support.IsNull()) throw Base::Exception("SketchBased: Up to face: No support in Sketch!"); std::vector<Part::cutFaces> cfaces = Part::findAllFacesCutBy(support, sketchshape, dir); if (cfaces.empty()) throw Base::Exception("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); } // Remove the limits of the upToFace so that the extrusion works even if sketchshape is larger // than the upToFace bool remove_limits = false; TopExp_Explorer Ex; 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; } } 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); BRepBuilderAPI_MakeFace mkFace(adapt.Surface().Surface() #if OCC_VERSION_HEX >= 0x060502 , Precision::Confusion() #endif ); if (!mkFace.IsDone()) throw Base::Exception("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::Exception("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::Exception("SketchBased: Up to face: Must not intersect sketch!"); }