| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include <BRepBuilderAPI_Copy.hxx> |
| | #include <BRepBuilderAPI_MakeFace.hxx> |
| | #include <BRep_Tool.hxx> |
| | #include <GeomConvert.hxx> |
| | #include <GeomFill.hxx> |
| | #include <GeomFill_BSplineCurves.hxx> |
| | #include <GeomFill_BezierCurves.hxx> |
| | #include <Geom_BSplineCurve.hxx> |
| | #include <Geom_BSplineSurface.hxx> |
| | #include <Geom_BezierCurve.hxx> |
| | #include <Geom_BezierSurface.hxx> |
| | #include <Geom_TrimmedCurve.hxx> |
| | #include <ShapeConstruct_Curve.hxx> |
| | #include <ShapeExtend_WireData.hxx> |
| | #include <ShapeFix_Wire.hxx> |
| | #include <Standard_ConstructionError.hxx> |
| | #include <StdFail_NotDone.hxx> |
| | #include <TopExp_Explorer.hxx> |
| | #include <TopoDS.hxx> |
| | #include <TopoDS_Edge.hxx> |
| | #include <TopoDS_Face.hxx> |
| | #include <TopoDS_Wire.hxx> |
| | #include <gp_Trsf.hxx> |
| |
|
| |
|
| | #include "FeatureGeomFillSurface.h" |
| |
|
| |
|
| | using namespace Surface; |
| |
|
| | ShapeValidator::ShapeValidator() |
| | { |
| | initValidator(); |
| | } |
| |
|
| | void ShapeValidator::initValidator() |
| | { |
| | willBezier = true; |
| | edgeCount = 0; |
| | } |
| |
|
| | |
| | void ShapeValidator::checkEdge(const TopoDS_Shape& shape) |
| | { |
| | if (shape.IsNull() || shape.ShapeType() != TopAbs_EDGE) { |
| | Standard_Failure::Raise("Shape is not an edge.\n"); |
| | } |
| |
|
| | TopoDS_Edge etmp = TopoDS::Edge(shape); |
| | TopLoc_Location heloc; |
| | Standard_Real u0; |
| | Standard_Real u1; |
| | Handle(Geom_Curve) c_geom = BRep_Tool::Curve(etmp, heloc, u0, u1); |
| | Handle(Geom_BezierCurve) bez_geom = Handle(Geom_BezierCurve)::DownCast(c_geom); |
| | |
| |
|
| | |
| | if (bez_geom.IsNull()) { |
| | willBezier = false; |
| | } |
| |
|
| | edgeCount++; |
| | } |
| |
|
| | void ShapeValidator::checkAndAdd(const TopoDS_Shape& shape, Handle(ShapeExtend_WireData) * aWD) |
| | { |
| | checkEdge(shape); |
| | if (aWD) { |
| | BRepBuilderAPI_Copy copier(shape); |
| | |
| | (*aWD)->Add(TopoDS::Edge(copier.Shape())); |
| | } |
| | } |
| |
|
| | void ShapeValidator::checkAndAdd( |
| | const Part::TopoShape& ts, |
| | const char* subName, |
| | Handle(ShapeExtend_WireData) * aWD |
| | ) |
| | { |
| | try { |
| | if (subName && *subName != '\0') { |
| | |
| | checkAndAdd(ts.getSubShape(subName), aWD); |
| | } |
| | else if (!ts.getShape().IsNull() && ts.getShape().ShapeType() == TopAbs_WIRE) { |
| | TopoDS_Wire wire = TopoDS::Wire(ts.getShape()); |
| | for (TopExp_Explorer xp(wire, TopAbs_EDGE); xp.More(); xp.Next()) { |
| | checkAndAdd(xp.Current(), aWD); |
| | } |
| | } |
| | else { |
| | checkAndAdd(ts.getShape(), aWD); |
| | } |
| | } |
| | catch (Standard_Failure&) { |
| | Standard_Failure::Raise("Wrong shape type.\n"); |
| | } |
| | } |
| |
|
| |
|
| | PROPERTY_SOURCE(Surface::GeomFillSurface, Part::Spline) |
| |
|
| | const char* GeomFillSurface::FillTypeEnums[] = {"Stretched", "Coons", "Curved", nullptr}; |
| |
|
| | GeomFillSurface::GeomFillSurface() |
| | : Spline() |
| | { |
| | ADD_PROPERTY(FillType, ((long)0)); |
| | ADD_PROPERTY(BoundaryList, (nullptr, "Dummy")); |
| | ADD_PROPERTY(ReversedList, (false)); |
| | FillType.setEnums(FillTypeEnums); |
| | BoundaryList.setScope(App::LinkScope::Global); |
| | } |
| |
|
| |
|
| | |
| | short GeomFillSurface::mustExecute() const |
| | { |
| | if (BoundaryList.isTouched() || ReversedList.isTouched() || FillType.isTouched()) { |
| | return 1; |
| | } |
| | return Spline::mustExecute(); |
| | } |
| |
|
| | void GeomFillSurface::onChanged(const App::Property* prop) |
| | { |
| | if (isRestoring()) { |
| | if (prop == &BoundaryList) { |
| | |
| | if (BoundaryList.getSize() != ReversedList.getSize()) { |
| | ReversedList.setSize(BoundaryList.getSize()); |
| | } |
| | } |
| | } |
| | Part::Spline::onChanged(prop); |
| | } |
| |
|
| | App::DocumentObjectExecReturn* GeomFillSurface::execute() |
| | { |
| | try { |
| | TopoDS_Wire aWire; |
| |
|
| | |
| | if (getWire(aWire)) { |
| | createBezierSurface(aWire); |
| | } |
| | else { |
| | createBSplineSurface(aWire); |
| | } |
| |
|
| | return App::DocumentObject::StdReturn; |
| | } |
| | catch (Standard_ConstructionError&) { |
| | |
| | return new App::DocumentObjectExecReturn("Curves are disjoint."); |
| | } |
| | catch (StdFail_NotDone&) { |
| | return new App::DocumentObjectExecReturn( |
| | "A curve was not a B-spline and could not be converted into one." |
| | ); |
| | } |
| | catch (Standard_Failure& e) { |
| | return new App::DocumentObjectExecReturn(e.GetMessageString()); |
| | } |
| | } |
| |
|
| | GeomFill_FillingStyle GeomFillSurface::getFillingStyle() |
| | { |
| | |
| | switch (FillType.getValue()) { |
| | case GeomFill_StretchStyle: |
| | case GeomFill_CoonsStyle: |
| | case GeomFill_CurvedStyle: |
| | return static_cast<GeomFill_FillingStyle>(FillType.getValue()); |
| | default: |
| | Standard_Failure::Raise("Filling style must be 0 (Stretch), 1 (Coons), or 2 (Curved).\n"); |
| | return GeomFill_StretchStyle; |
| | } |
| | } |
| |
|
| | bool GeomFillSurface::getWire(TopoDS_Wire& aWire) |
| | { |
| | Handle(ShapeFix_Wire) aShFW = new ShapeFix_Wire; |
| | Handle(ShapeExtend_WireData) aWD = new ShapeExtend_WireData; |
| |
|
| | std::vector<App::PropertyLinkSubList::SubSet> boundary = BoundaryList.getSubListValues(); |
| | if (boundary.size() > 4) { |
| | Standard_Failure::Raise("Only 2-4 curves are allowed\n"); |
| | } |
| |
|
| | ShapeValidator validator; |
| | for (const auto& set : boundary) { |
| | if (set.first->isDerivedFrom<Part::Feature>()) { |
| | for (const auto& jt : set.second) { |
| | const Part::TopoShape& ts = static_cast<Part::Feature*>(set.first)->Shape.getShape(); |
| | validator.checkAndAdd(ts, jt.c_str(), &aWD); |
| | } |
| | } |
| | else { |
| | Standard_Failure::Raise("Curve not from Part::Feature\n"); |
| | } |
| | } |
| |
|
| | if (validator.numEdges() < 2 || validator.numEdges() > 4) { |
| | Standard_Failure::Raise("Only 2-4 curves are allowed\n"); |
| | } |
| |
|
| | |
| |
|
| | aShFW->Load(aWD); |
| | aShFW->FixReorder(); |
| | aShFW->ClosedWireMode() = Standard_True; |
| | aShFW->FixConnected(); |
| | aShFW->FixSelfIntersection(); |
| | aShFW->Perform(); |
| |
|
| | aWire = aShFW->Wire(); |
| |
|
| | if (aWire.IsNull()) { |
| | Standard_Failure::Raise("Wire unable to be constructed\n"); |
| | } |
| |
|
| | return validator.isBezier(); |
| | } |
| |
|
| | void GeomFillSurface::createFace(const Handle(Geom_BoundedSurface) & aSurface) |
| | { |
| | BRepBuilderAPI_MakeFace aFaceBuilder; |
| | Standard_Real u1, u2, v1, v2; |
| | |
| | aSurface->Bounds(u1, u2, v1, v2); |
| | aFaceBuilder.Init(aSurface, u1, u2, v1, v2, Precision::Confusion()); |
| |
|
| | TopoDS_Face aFace = aFaceBuilder.Face(); |
| |
|
| | if (!aFaceBuilder.IsDone()) { |
| | Standard_Failure::Raise("Face unable to be constructed\n"); |
| | } |
| | if (aFace.IsNull()) { |
| | Standard_Failure::Raise("Resulting Face is null\n"); |
| | } |
| | this->Shape.setValue(aFace); |
| | } |
| |
|
| | void GeomFillSurface::createBezierSurface(TopoDS_Wire& aWire) |
| | { |
| | std::vector<Handle(Geom_BezierCurve)> curves; |
| | curves.reserve(4); |
| |
|
| | Standard_Real u1, u2; |
| | TopExp_Explorer anExp(aWire, TopAbs_EDGE); |
| | for (; anExp.More(); anExp.Next()) { |
| | const TopoDS_Edge hedge = TopoDS::Edge(anExp.Current()); |
| | TopLoc_Location heloc; |
| | Handle(Geom_Curve) c_geom = BRep_Tool::Curve(hedge, heloc, u1, u2); |
| | Handle(Geom_BezierCurve) bezier = Handle(Geom_BezierCurve)::DownCast(c_geom); |
| | |
| |
|
| | if (!bezier.IsNull()) { |
| | bezier->Segment(u1, u2); |
| | gp_Trsf transf = heloc.Transformation(); |
| | bezier->Transform(transf); |
| | |
| | curves.push_back(bezier); |
| | } |
| | else { |
| | Standard_Failure::Raise("Curve not a Bezier Curve"); |
| | } |
| | } |
| |
|
| | GeomFill_FillingStyle fstyle = getFillingStyle(); |
| | GeomFill_BezierCurves aSurfBuilder; |
| |
|
| | std::size_t edgeCount = curves.size(); |
| | const boost::dynamic_bitset<>& booleans = ReversedList.getValues(); |
| | if (edgeCount == booleans.size()) { |
| | for (std::size_t i = 0; i < edgeCount; i++) { |
| | if (booleans[i]) { |
| | curves[i]->Reverse(); |
| | } |
| | } |
| | } |
| |
|
| | if (edgeCount == 2) { |
| | aSurfBuilder.Init(curves[0], curves[1], fstyle); |
| | } |
| | else if (edgeCount == 3) { |
| | aSurfBuilder.Init(curves[0], curves[1], curves[2], fstyle); |
| | } |
| | else if (edgeCount == 4) { |
| | aSurfBuilder.Init(curves[0], curves[1], curves[2], curves[3], fstyle); |
| | } |
| |
|
| | createFace(aSurfBuilder.Surface()); |
| | } |
| |
|
| | void GeomFillSurface::createBSplineSurface(TopoDS_Wire& aWire) |
| | { |
| | std::vector<Handle(Geom_BSplineCurve)> curves; |
| | curves.reserve(4); |
| | Standard_Real u1, u2; |
| | TopExp_Explorer anExp(aWire, TopAbs_EDGE); |
| | for (; anExp.More(); anExp.Next()) { |
| | const TopoDS_Edge& edge = TopoDS::Edge(anExp.Current()); |
| | TopLoc_Location heloc; |
| | Handle(Geom_Curve) c_geom = BRep_Tool::Curve(edge, heloc, u1, u2); |
| | Handle(Geom_BSplineCurve) bspline = Handle(Geom_BSplineCurve)::DownCast( |
| | c_geom |
| | ); |
| |
|
| | gp_Trsf transf = heloc.Transformation(); |
| | if (!bspline.IsNull()) { |
| | bspline->Segment(u1, u2); |
| | bspline->Transform(transf); |
| | |
| | curves.push_back(bspline); |
| | } |
| | else { |
| | |
| | Handle(Geom_TrimmedCurve) trim = new Geom_TrimmedCurve(c_geom, u1, u2); |
| | |
| | |
| | GeomConvert conv; |
| | Convert_ParameterisationType paratype = Convert_Polynomial; |
| | Handle(Geom_BSplineCurve) bspline2 = conv.CurveToBSplineCurve(trim, paratype); |
| | if (!bspline2.IsNull()) { |
| | bspline2->Transform(transf); |
| | curves.push_back(bspline2); |
| | } |
| | else { |
| | |
| | ShapeConstruct_Curve scc; |
| | Handle(Geom_BSplineCurve) spline |
| | = scc.ConvertToBSpline(c_geom, u1, u2, Precision::Confusion()); |
| | if (spline.IsNull()) { |
| | Standard_Failure::Raise( |
| | "A curve was not a B-spline and could not be converted into one." |
| | ); |
| | } |
| | spline->Transform(transf); |
| | curves.push_back(spline); |
| | } |
| | } |
| | } |
| |
|
| | GeomFill_FillingStyle fstyle = getFillingStyle(); |
| | GeomFill_BSplineCurves aSurfBuilder; |
| |
|
| | std::size_t edgeCount = curves.size(); |
| | const boost::dynamic_bitset<>& booleans = ReversedList.getValues(); |
| | if (edgeCount == booleans.size()) { |
| | for (std::size_t i = 0; i < edgeCount; i++) { |
| | if (booleans[i]) { |
| | curves[i]->Reverse(); |
| | } |
| | } |
| | } |
| | if (edgeCount == 2) { |
| | aSurfBuilder.Init(curves[0], curves[1], fstyle); |
| | } |
| | else if (edgeCount == 3) { |
| | aSurfBuilder.Init(curves[0], curves[1], curves[2], fstyle); |
| | } |
| | else if (edgeCount == 4) { |
| | aSurfBuilder.Init(curves[0], curves[1], curves[2], curves[3], fstyle); |
| | } |
| |
|
| | createFace(aSurfBuilder.Surface()); |
| | } |
| |
|