diff --git a/src/Mod/Surface/App/FeatureBSplineSurf.cpp b/src/Mod/Surface/App/FeatureBSplineSurf.cpp index 8d67c97e62..fe6270ae0c 100644 --- a/src/Mod/Surface/App/FeatureBSplineSurf.cpp +++ b/src/Mod/Surface/App/FeatureBSplineSurf.cpp @@ -107,10 +107,9 @@ App::DocumentObjectExecReturn *BSplineSurf::execute(void) GeomFill_FillingStyle fstyle = getFillingStyle(); GeomFill_BSplineCurves aSurfBuilder; //Create Surface Builder - int ncrv = BoundaryList.getSize(); - if(ncrv==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);} - else if(ncrv==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);} - else if(ncrv==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);} + if(edgeCount==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);} + else if(edgeCount==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);} + else if(edgeCount==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);} createFace(aSurfBuilder.Surface()); diff --git a/src/Mod/Surface/App/FeatureBSurf.cpp b/src/Mod/Surface/App/FeatureBSurf.cpp index bc85b1afbe..4b0adfdaba 100644 --- a/src/Mod/Surface/App/FeatureBSurf.cpp +++ b/src/Mod/Surface/App/FeatureBSurf.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #endif #include @@ -82,43 +83,57 @@ void BSurf::getWire(TopoDS_Wire& aWire) Handle(ShapeExtend_WireData) aWD = new ShapeExtend_WireData; int boundaryListSize = BoundaryList.getSize(); - if(boundaryListSize > 4 || boundaryListSize < 2) + if(boundaryListSize > 4) // if too many not even try { Standard_Failure::Raise("Only 2-4 curves are allowed"); return; } + BRepBuilderAPI_Copy copier; + edgeCount = 0; for(int i = 0; i < boundaryListSize; i++) { - Part::TopoShape ts; //Curve TopoShape - TopoDS_Shape sub; //Curve TopoDS_Shape - TopoDS_Edge etmp; //Curve TopoDS_Edge - - //Get Edge App::PropertyLinkSubList::SubSet set = BoundaryList[i]; if(set.obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { - ts = static_cast(set.obj)->Shape.getShape(); - - //we want only the subshape which is linked - sub = ts.getSubShape(set.sub); - // make a copy of the shape and the underlying geometry to avoid to affect the input shapes - BRepBuilderAPI_Copy copy(sub); - sub = copy.Shape(); - - if(sub.ShapeType() == TopAbs_EDGE) { //Check Shape type and assign edge - etmp = TopoDS::Edge(sub); + const Part::TopoShape &ts = static_cast(set.obj)->Shape.getShape(); + if(ts._Shape.ShapeType() == TopAbs_WIRE) + { + const TopoDS_Wire &wire = TopoDS::Wire(ts._Shape); + // resolve the wire, we need edges from now on + for (TopExp_Explorer wireExplorer (wire, TopAbs_EDGE); wireExplorer.More(); wireExplorer.Next()) + { + // make a copy of the shape and the underlying geometry to avoid to affect the input shapes + copier.Perform(wireExplorer.Current()); + aWD->Add(TopoDS::Edge(copier.Shape())); + edgeCount++; + } } - else { - Standard_Failure::Raise("Curves must be type TopoDS_Edge"); - return; //Raise exception - } - aWD->Add(etmp); + else + { + //we want only the subshape which is linked + const TopoDS_Shape &sub = ts.getSubShape(set.sub); + // make a copy of the shape and the underlying geometry to avoid to affect the input shapes + copier.Perform(sub); + const TopoDS_Shape © = copier.Shape(); + if(copy.ShapeType() == TopAbs_EDGE) { //Check Shape type and assign edge + aWD->Add(TopoDS::Edge(copy)); + edgeCount++; + } + else { + Standard_Failure::Raise("Curves must be of type TopoDS_Edge or TopoDS_Wire"); + return; //Raise exception + } + } } else{Standard_Failure::Raise("Curve not from Part::Feature");return;} - + } + if(edgeCount < 2 || edgeCount > 4) + { + Standard_Failure::Raise("Only 2-4 curves are allowed"); + return; } //Reorder the curves and fix the wire if required diff --git a/src/Mod/Surface/App/FeatureBSurf.h b/src/Mod/Surface/App/FeatureBSurf.h index 287ae206de..af9d81f185 100644 --- a/src/Mod/Surface/App/FeatureBSurf.h +++ b/src/Mod/Surface/App/FeatureBSurf.h @@ -61,6 +61,9 @@ protected: // corrects the initially invalid fill type void correcteInvalidFillType(); + // number of edges is a result of calculating single and wire edges + int edgeCount; + private: static const char* FillTypeEnums[]; }; diff --git a/src/Mod/Surface/App/FeatureBezSurf.cpp b/src/Mod/Surface/App/FeatureBezSurf.cpp index de4dad2ff4..ad90184b82 100644 --- a/src/Mod/Surface/App/FeatureBezSurf.cpp +++ b/src/Mod/Surface/App/FeatureBezSurf.cpp @@ -89,10 +89,9 @@ App::DocumentObjectExecReturn *BezSurf::execute(void) GeomFill_FillingStyle fstyle = getFillingStyle(); GeomFill_BezierCurves aSurfBuilder; //Create Surface Builder - int ncrv = BoundaryList.getSize(); - if(ncrv==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);} - else if(ncrv==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);} - else if(ncrv==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);} + if(edgeCount==2) {aSurfBuilder.Init(crvs[0], crvs[1], fstyle);} + else if(edgeCount==3) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], fstyle);} + else if(edgeCount==4) {aSurfBuilder.Init(crvs[0], crvs[1], crvs[2], crvs[3], fstyle);} createFace(aSurfBuilder.Surface()); diff --git a/src/Mod/Surface/Gui/Command.cpp b/src/Mod/Surface/Gui/Command.cpp index 6794f3a33d..819d0c4630 100644 --- a/src/Mod/Surface/Gui/Command.cpp +++ b/src/Mod/Surface/Gui/Command.cpp @@ -160,6 +160,8 @@ public: protected: bool willBezier; bool willBSpline; + int edgeCount; + bool isEdge(const TopoDS_Shape& shape); virtual bool isActive(void); void createSurface(const char *surfaceNamePrefix, const char *commandName, const char *pythonAddCommand); virtual void activated(int iMsg); @@ -176,13 +178,51 @@ CmdSurfaceBSurf::CmdSurfaceBSurf() : Command("Surface_BSurf") sPixmap = "BSplineSurf"; } +bool CmdSurfaceBSurf::isEdge(const TopoDS_Shape& shape) +{ + if (shape.IsNull() || shape.ShapeType() != TopAbs_EDGE) + { + return false; + } + TopoDS_Edge etmp = TopoDS::Edge(shape); //Curve TopoDS_Edge + TopLoc_Location heloc; // this will be output + Standard_Real u0;// contains output + Standard_Real u1;// contains output + Handle_Geom_Curve c_geom = BRep_Tool::Curve(etmp,heloc,u0,u1); //The geometric curve + Handle_Geom_BezierCurve bez_geom = Handle_Geom_BezierCurve::DownCast(c_geom); //Try to get Bezier curve + if (bez_geom.IsNull()) + { + // this one is not Bezier, we hope it can be converted into b-spline + if(willBezier) { + // already found the other type, fail + return false; + } + // we will create b-spline surface + willBSpline = true; + } + else + { + // this one is Bezier + if(willBSpline) { + // already found the other type, fail + return false; + } + // we will create Bezier surface + willBezier = true; + } + edgeCount++; + return true; +} + bool CmdSurfaceBSurf::isActive(void) { willBezier = willBSpline = false; std::vector Sel = getSelection().getSelection(); - if (Sel.size() < 2 || Sel.size() > 4) { + if (Sel.size() > 4) { return false; } + // we need to count them inside wires, too + edgeCount = 0; for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it) { if(!((*it).pObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) { @@ -191,67 +231,57 @@ bool CmdSurfaceBSurf::isActive(void) Part::TopoShape ts = static_cast((*it).pObject)->Shape.getShape(); try { // make sure the main shape type is edge or wire - TopAbs_ShapeEnum shapeType = ts._Shape.ShapeType(); - if(shapeType != TopAbs_WIRE && shapeType != TopAbs_EDGE) + if(ts._Shape.ShapeType() == TopAbs_WIRE) { - return false; - } - TopoDS_Shape shape = ts.getSubShape("Edge1"); - if (shape.IsNull()) - { - return false; - } - if(shape.ShapeType() != TopAbs_EDGE) { //Check Shape type and assign edge - return false; - } - TopoDS_Edge etmp = TopoDS::Edge(shape); //Curve TopoDS_Edge - TopLoc_Location heloc; // this will be output - Standard_Real u0;// contains output - Standard_Real u1;// contains output - Handle_Geom_Curve c_geom = BRep_Tool::Curve(etmp,heloc,u0,u1); //The geometric curve - Handle_Geom_BezierCurve bez_geom = Handle_Geom_BezierCurve::DownCast(c_geom); //Try to get Bezier curve - if (bez_geom.IsNull()) - { - // this one is not Bezier, we hope it can be converted into b-spline - if(willBezier) { - // already found the other type, fail - return false; + TopoDS_Wire wire = TopoDS::Wire(ts._Shape); + for (TopExp_Explorer wireExplorer (wire, TopAbs_EDGE); wireExplorer.More(); wireExplorer.Next()) + { + if(!isEdge(wireExplorer.Current())) + { + return false; + } } - // we will create b-spline surface - willBSpline = true; } else { - // this one is Bezier - if(willBSpline) { - // already found the other type, fail + TopoDS_Shape shape = ts.getSubShape("Edge1"); + if(!isEdge(shape)) + { return false; } - // we will create Bezier surface - willBezier = true; } } catch(Standard_Failure) { // any OCC exception means an unappropriate shape in the selection return false; } } - return true; + return edgeCount >= 2 && edgeCount <= 4; } void CmdSurfaceBSurf::createSurface(const char *surfaceNamePrefix, const char *commandName, const char *pythonAddCommand) { - // we take the whole selection and require that all of its members are of the required curve - std::vector sel = getSelection().getSelectionEx(0); - if (sel.size() == 2) { + if (edgeCount == 2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Warning"), QObject::tr("Surfaces with two edges may fail for some fill types.")); } std::string FeatName = getUniqueObjectName(surfaceNamePrefix); std::stringstream bspListCmd; + std::vector Sel = getSelection().getSelection(); bspListCmd << "FreeCAD.ActiveDocument.ActiveObject.BoundaryList = ["; - for (std::vector::iterator it = sel.begin(); it != sel.end(); ++it) { - bspListCmd << "(App.activeDocument()." << it->getFeatName() << ", \'Edge1\'),"; + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it) + { + Part::TopoShape ts = static_cast((*it).pObject)->Shape.getShape(); + bspListCmd << "(App.activeDocument()." << it->FeatName; + // if it is wire, add as wire + if(ts._Shape.ShapeType() == TopAbs_WIRE) + { + bspListCmd << ", \'Wire1\'),"; + } + else + { + bspListCmd << ", \'Edge1\'),"; + } } bspListCmd << "]";