| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
| #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()); |
| } |
|
|