From fc89f4eb0c2c6295a1bc02a5cd3db0a22547fc22 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 23 Oct 2020 00:36:41 +0200 Subject: [PATCH] Sketcher: implement command to decrease degree of a B-spline --- src/Mod/Sketcher/App/SketchObject.cpp | 42 +++++++++++++++ src/Mod/Sketcher/App/SketchObject.h | 8 +++ src/Mod/Sketcher/App/SketchObjectPy.xml | 5 ++ src/Mod/Sketcher/App/SketchObjectPyImp.cpp | 18 +++++++ .../Sketcher/Gui/CommandSketcherBSpline.cpp | 53 ++++++++++++++++--- src/Mod/Sketcher/Gui/Workbench.cpp | 4 +- 6 files changed, 122 insertions(+), 8 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 4a4fcdd5cb..cab7d3bf4b 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -5198,6 +5198,48 @@ bool SketchObject::increaseBSplineDegree(int GeoId, int degreeincrement /*= 1*/) return true; } +bool SketchObject::decreaseBSplineDegree(int GeoId, int degreedecrement /*= 1*/) +{ + Base::StateLocker lock(managedoperation, true); // no need to check input data validity as this is an sketchobject managed operation. + + if (GeoId < 0 || GeoId > getHighestCurveIndex()) + return false; + + const Part::Geometry *geo = getGeometry(GeoId); + + if (geo->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) + return false; + + const Part::GeomBSplineCurve *bsp = static_cast(geo); + + const Handle(Geom_BSplineCurve) curve = Handle(Geom_BSplineCurve)::DownCast(bsp->handle()); + + std::unique_ptr bspline(new Part::GeomBSplineCurve(curve)); + + try { + int cdegree = bspline->getDegree(); + + bool ok = bspline->approximate(Precision::Confusion(), 20, cdegree-degreedecrement, 0); + if (!ok) + return false; + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + return false; + } + + const std::vector< Part::Geometry * > &vals = getInternalGeometry(); + + std::vector< Part::Geometry * > newVals(vals); + + newVals[GeoId] = bspline.release(); + + // AcceptGeometry called from onChanged + Geometry.setValues(newVals); + + return true; +} + bool SketchObject::modifyBSplineKnotMultiplicity(int GeoId, int knotIndex, int multiplicityincr) { Base::StateLocker lock(managedoperation, true); // no need to check input data validity as this is an sketchobject managed operation. diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 83a95e26ab..6c5535a59c 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -253,6 +253,14 @@ public: */ bool increaseBSplineDegree(int GeoId, int degreeincrement = 1); + /*! + \brief Decreases the degree of a BSpline by degreedecrement, which defaults to 1 + \param GeoId - the geometry of type bspline to increase the degree + \param degreedecrement - the decrement in number of degrees to effect + \retval bool - returns true if the decrease in degree succeeded, or false if it did not succeed. + */ + bool decreaseBSplineDegree(int GeoId, int degreedecrement = 1); + /*! \brief Increases or Decreases the multiplicity of a BSpline knot by the multiplicityincr param, which defaults to 1, if the result is multiplicity zero, the knot is removed \param GeoId - the geometry of type bspline to increase the degree diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml index 0082e13a0d..d7cefa156a 100644 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ b/src/Mod/Sketcher/App/SketchObjectPy.xml @@ -257,6 +257,11 @@ If there is no such constraint an exception is raised. Increases the given BSpline Degree by a number of degrees + + + Decreases the given BSpline Degree by a number of degrees by approximating this curve + + Increases or reduces the given BSpline knot multiplicity diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index 2736fdd9ea..d1dc97a2fd 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -1396,6 +1396,24 @@ PyObject* SketchObjectPy::increaseBSplineDegree(PyObject *args) Py_Return; } +PyObject* SketchObjectPy::decreaseBSplineDegree(PyObject *args) +{ + int GeoId; + int incr = 1; + + if (!PyArg_ParseTuple(args, "i|i", &GeoId, &incr)) + return 0; + + if (this->getSketchObjectPtr()->decreaseBSplineDegree(GeoId, incr)==false) { + std::stringstream str; + str << "Degree decrease failed for: " << GeoId; + PyErr_SetString(PyExc_ValueError, str.str().c_str()); + return 0; + } + + Py_Return; +} + PyObject* SketchObjectPy::modifyBSplineKnotMultiplicity(PyObject *args) { int GeoId; diff --git a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp index c6991d9565..cfd210a4ed 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp @@ -479,8 +479,7 @@ CmdSketcherDecreaseDegree::CmdSketcherDecreaseDegree() sAppModule = "Sketcher"; sGroup = QT_TR_NOOP("Sketcher"); sMenuText = QT_TR_NOOP("Decrease B-spline degree"); - sToolTipText = QT_TR_NOOP("Decreases the degree of the B-spline.\n" - "This command is currently NOT IMPLEMENTED."); + sToolTipText = QT_TR_NOOP("Decreases the degree of the B-spline"); sWhatsThis = "Sketcher_BSplineDecreaseDegree"; sStatusTip = sToolTipText; sPixmap = "Sketcher_BSplineDecreaseDegree"; @@ -488,12 +487,54 @@ CmdSketcherDecreaseDegree::CmdSketcherDecreaseDegree() eType = ForEdit; } -// TODO: fully implement this function to complement Sketcher_BSplineIncreaseDegree void CmdSketcherDecreaseDegree::activated(int iMsg) { Q_UNUSED(iMsg); - Base::Console().Message("Decrease degree of spline. " - "This command is currently NOT IMPLEMENTED.\n"); + + // get the selection + std::vector selection; + selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); + + // only one sketch with its subelements are allowed to be selected + if (selection.size() != 1) { + return; + } + + // get the needed lists and objects + const std::vector &SubNames = selection[0].getSubNames(); + Sketcher::SketchObject* Obj = static_cast(selection[0].getObject()); + + openCommand("Decrease spline degree"); + + bool ignored = false; + + for (size_t i=0; i < SubNames.size(); i++) { + // only handle edges + if (SubNames[i].size() > 4 && SubNames[i].substr(0,4) == "Edge") { + int GeoId = std::atoi(SubNames[i].substr(4,4000).c_str()) - 1; + const Part::Geometry * geo = Obj->getGeometry(GeoId); + + if (geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { + Gui::cmdAppObjectArgs(selection[0].getObject(), "decreaseBSplineDegree(%d) ", GeoId); + // add new control points + //Gui::cmdAppObjectArgs(selection[0].getObject(), "exposeInternalGeometry(%d)", GeoId); + } + else { + ignored = true; + } + } + } + + if (ignored) { + QMessageBox::warning(Gui::getMainWindow(), + QObject::tr("Wrong selection"), + QObject::tr("At least one of the selected " + "objects was not a B-Spline and was ignored.")); + } + + commitCommand(); + tryAutoRecomputeIfNotSolve(Obj); + getSelection().clearSelection(); } bool CmdSketcherDecreaseDegree::isActive(void) @@ -902,7 +943,7 @@ void CreateSketcherCommandsBSpline(void) rcCmdMgr.addCommand(new CmdSketcherCompBSplineShowHideGeometryInformation()); rcCmdMgr.addCommand(new CmdSketcherConvertToNURB()); rcCmdMgr.addCommand(new CmdSketcherIncreaseDegree()); - rcCmdMgr.addCommand(new CmdSketcherDecreaseDegree()); // TODO: implement this function + rcCmdMgr.addCommand(new CmdSketcherDecreaseDegree()); rcCmdMgr.addCommand(new CmdSketcherIncreaseKnotMultiplicity()); rcCmdMgr.addCommand(new CmdSketcherDecreaseKnotMultiplicity()); rcCmdMgr.addCommand(new CmdSketcherCompModifyKnotMultiplicity()); diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 4357172ebf..ab9a42b35a 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -373,7 +373,7 @@ inline void SketcherAddWorkbenchBSplines(Gui::MenuItem& bspline) << "Sketcher_BSplineKnotMultiplicity" << "Sketcher_BSplineConvertToNURB" << "Sketcher_BSplineIncreaseDegree" - << "Sketcher_BSplineDecreaseDegree" // TODO: implement this command + << "Sketcher_BSplineDecreaseDegree" << "Sketcher_BSplineIncreaseKnotMultiplicity" << "Sketcher_BSplineDecreaseKnotMultiplicity"; } @@ -384,7 +384,7 @@ inline void SketcherAddWorkbenchBSplines(Gui::ToolBarItem& bsp bspline << "Sketcher_CompBSplineShowHideGeometryInformation" << "Sketcher_BSplineConvertToNURB" << "Sketcher_BSplineIncreaseDegree" - << "Sketcher_BSplineDecreaseDegree" // TODO: implement this command + << "Sketcher_BSplineDecreaseDegree" << "Sketcher_CompModifyKnotMultiplicity"; }