From c85368bfc02a45d86ec6bc11bed561a42c1f1461 Mon Sep 17 00:00:00 2001 From: balazs-bamer Date: Sun, 4 Jan 2015 11:59:28 +0100 Subject: [PATCH] B-spline surface operation enabled I have converted Nate's b-spline generation to use my superclass FeatureBSurf and added it to the GUI. Other half-ready operations as filling and cut are commented out. Missing: - the fill type must be queried from the user. The data panel lets it modify, but it is not user-friendly. - b-spline surface is generated, but it covers only a fraction of the supporting curves. It may lie on OCC error. --- src/Mod/Surface/App/FeatureBSplineSurf.cpp | 131 ++++++++++++++++++++- src/Mod/Surface/App/FeatureBSplineSurf.h | 19 +-- src/Mod/Surface/App/FeatureBSurf.cpp | 3 +- src/Mod/Surface/App/FillType.h | 34 ------ src/Mod/Surface/Gui/Command.cpp | 85 ++++++++++++- src/Mod/Surface/Gui/Workbench.cpp | 10 +- 6 files changed, 221 insertions(+), 61 deletions(-) delete mode 100644 src/Mod/Surface/App/FillType.h diff --git a/src/Mod/Surface/App/FeatureBSplineSurf.cpp b/src/Mod/Surface/App/FeatureBSplineSurf.cpp index 6d24a860b0..38b5274dbf 100644 --- a/src/Mod/Surface/App/FeatureBSplineSurf.cpp +++ b/src/Mod/Surface/App/FeatureBSplineSurf.cpp @@ -1,6 +1,6 @@ /*************************************************************************** - * Copyright (c) 2014 Nathan Miller * - * Balázs Bámer * + * Copyright (c) 2014-2015 Nathan Miller * + * Balázs Bámer * * * * This file is part of the FreeCAD CAx development system. * * * @@ -21,6 +21,132 @@ * * ***************************************************************************/ +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "FeatureBSplineSurf.h" + + +using namespace Surface; + +PROPERTY_SOURCE(Surface::BSplineSurf, Part::Feature) + +//Initial values + +BSplineSurf::BSplineSurf() +{ + ADD_PROPERTY(aBList,(0,"Geom_BSplineCurve")); + ADD_PROPERTY(filltype,(1)); +} + +//Structures + +struct crvs{ + + Handle_Geom_BSplineCurve C1; + Handle_Geom_BSplineCurve C2; + Handle_Geom_BSplineCurve C3; + Handle_Geom_BSplineCurve C4; + +}; + +//Functions + +App::DocumentObjectExecReturn *BSplineSurf::execute(void) +{ + //Begin Construction + try{ + GeomFill_FillingStyle fstyle = getFillingStyle(); + GeomFill_BSplineCurves aSurfBuilder; //Create Surface Builder + TopoDS_Wire aWire; //Create empty wire + + //Gets the healed wire + getWire(aWire); + + //Create BSpline Surface builder + crvs bcrv; + Standard_Real u0;// contains output + Standard_Real u1;// contains output + TopExp_Explorer anExp (aWire, TopAbs_EDGE); + int it = 0; + for (; anExp.More(); anExp.Next()) { + const TopoDS_Edge hedge = TopoDS::Edge (anExp.Current()); + TopLoc_Location heloc; // this will be output + Handle_Geom_Curve c_geom = BRep_Tool::Curve(hedge,heloc,u0,u1); //The geometric curve + Handle_Geom_BSplineCurve b_geom = Handle_Geom_BSplineCurve::DownCast(c_geom); //Try to get BSpline curve + + if (!b_geom.IsNull()) { + gp_Trsf transf = heloc.Transformation(); + b_geom->Transform(transf); // apply original transformation to control points + //Store Underlying Geometry + if(it==0){bcrv.C1 = b_geom;} + else if(it==1){bcrv.C2 = b_geom;} + else if(it==2){bcrv.C3 = b_geom;} + else if(it==3){bcrv.C4 = b_geom;} + } + else { + Standard_Failure::Raise("Curve not a BSpline Curve"); + } + it++; + } + + int ncrv = aBList.getSize(); + if(ncrv==2){aSurfBuilder.Init(bcrv.C1,bcrv.C2,fstyle);} + else if(ncrv==3){aSurfBuilder.Init(bcrv.C1,bcrv.C2,bcrv.C3,fstyle);} + else if(ncrv==4){aSurfBuilder.Init(bcrv.C1,bcrv.C2,bcrv.C3,bcrv.C4,fstyle);} + + //Create the surface + const Handle_Geom_BSplineSurface aSurface = aSurfBuilder.Surface(); + + BRepBuilderAPI_MakeFace aFaceBuilder;//(aSurface,aWire,Standard_True); //Create Face Builder + u0 = 0.; + u1 = 1.; + Standard_Real v0 = 0.; + Standard_Real v1 = 1.; + aFaceBuilder.Init(aSurface,u0,u1,v0,v1,Precision::Confusion()); + + TopoDS_Face aFace = aFaceBuilder.Face(); //Returned Face + if(!aFaceBuilder.IsDone()){return new App::DocumentObjectExecReturn("Face unable to be constructed");} + + if (aFace.IsNull()){ + return new App::DocumentObjectExecReturn("Resulting Face is null"); + } + this->Shape.setValue(aFace); + + return App::DocumentObject::StdReturn; + + } //End Try + catch(Standard_ConstructionError) { + // message is in a Latin language, show a normal one + return new App::DocumentObjectExecReturn("Curves are disjoint."); + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); + } //End Catch + +} //End execute + + +/* + #include "PreCompiled.h" #ifndef _PreComp_ #include @@ -234,3 +360,4 @@ void getCurves(GeomFill_BSplineCurves& aBuilder,TopoDS_Wire& aWire, const App::P return; } +*/ diff --git a/src/Mod/Surface/App/FeatureBSplineSurf.h b/src/Mod/Surface/App/FeatureBSplineSurf.h index fefcdd8bd5..5e799a3fa0 100644 --- a/src/Mod/Surface/App/FeatureBSplineSurf.h +++ b/src/Mod/Surface/App/FeatureBSplineSurf.h @@ -1,5 +1,6 @@ /*************************************************************************** - * Copyright (c) 2014 Nathan Miller * + * Copyright (c) 2014-2015 Nathan Miller * + * Balázs Bámer * * * * This file is part of the FreeCAD CAx development system. * * * @@ -23,32 +24,20 @@ #ifndef SURFACE_FEATUREBSPLINESURF_H #define SURFACE_FEATUREBSPLINESURF_H -#include -#include -#include -#include "Mod/Part/App/PartFeature.h" +#include "FeatureBSurf.h" namespace Surface { -class SurfaceExport BSplineSurf : public Part::Feature +class SurfaceExport BSplineSurf : public BSurf { PROPERTY_HEADER(Surface::BSplineSurf); public: BSplineSurf(); - App::PropertyLinkSubList aBSplineList; //BSpline curves to be turned into a face (2-4 curves allowed). - App::PropertyInteger filltype; //Fill method (1, 2, or 3 for Stretch, Coons, and Curved) - // recalculate the feature App::DocumentObjectExecReturn *execute(void); - short mustExecute() const; - /// returns the type name of the view provider -// const char* getViewProviderName(void) const { -// return "PartGui::ViewProviderCut"; -// } - }; }//Namespace Surface #endif diff --git a/src/Mod/Surface/App/FeatureBSurf.cpp b/src/Mod/Surface/App/FeatureBSurf.cpp index 3894bf7558..477f58c162 100644 --- a/src/Mod/Surface/App/FeatureBSurf.cpp +++ b/src/Mod/Surface/App/FeatureBSurf.cpp @@ -65,8 +65,7 @@ void BSurf::getWire(TopoDS_Wire& aWire) Handle(ShapeFix_Wire) aShFW = new ShapeFix_Wire; Handle(ShapeExtend_WireData) aWD = new ShapeExtend_WireData; - if(aBList.getSize()>4){Standard_Failure::Raise("Only 2-4 continuous Bezier Curves are allowed");return;} - if(aBList.getSize()<2){Standard_Failure::Raise("Only 2-4 continuous Bezier Curves are allowed");return;} + if(aBList.getSize()>4 || aBList.getSize()<2){Standard_Failure::Raise("Only 2-4 curves are allowed");return;} for(int i=0; i #include #include +#include #include #include #include @@ -59,8 +60,6 @@ #include #include "Mod/Part/App/PartFeature.h" -// Nate's stuff - //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //=========================================================================== @@ -222,10 +221,88 @@ bool CmdSurfaceBezier::isActive(void) return true; } +//=========================================================================== +// Surface_BSpline +//=========================================================================== +DEF_STD_CMD_A(CmdSurfaceBSpline); + +CmdSurfaceBSpline::CmdSurfaceBSpline() + :Command("Surface_BSpline") +{ + sAppModule = "Surface"; + sGroup = QT_TR_NOOP("Surface"); + sMenuText = QT_TR_NOOP("BSpline"); + sToolTipText = QT_TR_NOOP("Creates a surface from 2, 3 or 4 BSpline curves"); + sWhatsThis = "Surface_BSpline"; + sStatusTip = sToolTipText; + sPixmap = "BSplineSurf"; +} + +void CmdSurfaceBSpline::activated(int iMsg) +{ + /*if (!isActive()) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select 2, 3 or 4 curves, please.")); + return; + }*/ + + // we take the whole selection and require that all of its members are of the required curve + std::vector Selo = getSelection().getSelectionEx(0); + std::string FeatName = getUniqueObjectName("BSplineSurface"); + std::stringstream bspListCmd; + bspListCmd << "FreeCAD.ActiveDocument.ActiveObject.aBList = ["; + for (std::vector::iterator it = Selo.begin(); it != Selo.end(); ++it) { + bspListCmd << "(App.activeDocument()." << it->getFeatName() << ", \'Edge1\'),"; + } + bspListCmd << "]"; + + openCommand("Create BSpline surface"); + doCommand(Doc,"FreeCAD.ActiveDocument.addObject(\"Surface::BSplineSurf\",\"%s\")", FeatName.c_str()); + doCommand(Doc, "FreeCAD.ActiveDocument.ActiveObject.filltype=1"); // TODO ask filltype from user and check it + runCommand(Doc, bspListCmd.str().c_str()); + updateActive(); + commitCommand(); +} + +bool CmdSurfaceBSpline::isActive(void) +{ + std::vector Sel = getSelection().getSelection(); + if (Sel.size() < 2 || Sel.size() > 4) { + return false; + } + for (std::vector::iterator it = Sel.begin(); it != Sel.end(); ++it) + { + if(!((*it).pObject->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) { + return false; + } + Part::TopoShape ts = static_cast((*it).pObject)->Shape.getShape(); + 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_BSplineCurve b_geom = Handle_Geom_BSplineCurve::DownCast(c_geom); //Try to get BSpline curve + if (b_geom.IsNull()) { + return false; + } + } + return true; +} + + void CreateSurfaceCommands(void) { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); - rcCmdMgr.addCommand(new CmdSurfaceFilling()); - rcCmdMgr.addCommand(new CmdSurfaceCut()); +/* rcCmdMgr.addCommand(new CmdSurfaceFilling()); + rcCmdMgr.addCommand(new CmdSurfaceCut());*/ rcCmdMgr.addCommand(new CmdSurfaceBezier()); + rcCmdMgr.addCommand(new CmdSurfaceBSpline()); } diff --git a/src/Mod/Surface/Gui/Workbench.cpp b/src/Mod/Surface/Gui/Workbench.cpp index 9170c1df96..af638de373 100644 --- a/src/Mod/Surface/Gui/Workbench.cpp +++ b/src/Mod/Surface/Gui/Workbench.cpp @@ -54,8 +54,9 @@ Gui::MenuItem* Workbench::setupMenuBar() const root->insertItem( item, surface ); surface->setCommand("Surface"); *surface << "Surface_Bezier"; - *surface << "Surface_Filling"; - *surface << "Surface_Cut"; + *surface << "Surface_BSpline"; +/* *surface << "Surface_Filling"; + *surface << "Surface_Cut";*/ return root; } @@ -67,8 +68,9 @@ Gui::ToolBarItem* Workbench::setupToolBars() const Gui::ToolBarItem* surface = new Gui::ToolBarItem(root); surface->setCommand( "Surface" ); *surface << "Surface_Bezier"; - *surface << "Surface_Filling"; - *surface << "Surface_Cut"; + *surface << "Surface_BSpline"; +/* *surface << "Surface_Filling"; + *surface << "Surface_Cut"; */ return root; }