From 37e93cc1670e72f67b467ff80935ff30c57acfa5 Mon Sep 17 00:00:00 2001 From: Ajinkya Dahale Date: Wed, 29 Dec 2021 02:51:55 -0500 Subject: [PATCH] [Sketcher] Add knot insertion command in Sketcher workbench --- .../Sketcher/Gui/CommandSketcherBSpline.cpp | 142 ++++- src/Mod/Sketcher/Gui/Resources/Sketcher.qrc | 1 + .../splines/Sketcher_BSplineInsertKnot.svg | 488 ++++++++++++++++++ src/Mod/Sketcher/Gui/Workbench.cpp | 6 +- 4 files changed, 634 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Sketcher/Gui/Resources/icons/splines/Sketcher_BSplineInsertKnot.svg diff --git a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp index 8bb99a7bf7..6992dbbd48 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherBSpline.cpp @@ -28,7 +28,7 @@ # include # include # include -# include +# include #endif #include @@ -971,6 +971,145 @@ bool CmdSketcherCompModifyKnotMultiplicity::isActive(void) return isSketcherBSplineActive(getActiveGuiDocument(), false); } +DEF_STD_CMD_A(CmdSketcherInsertKnot) + +CmdSketcherInsertKnot::CmdSketcherInsertKnot() + : Command("Sketcher_BSplineInsertKnot") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("Insert knot"); + sToolTipText = QT_TR_NOOP("Inserts knot at given parameter with the given multiplicity. If a knot already exists at that parameter, it's multiplicity is increased by the value."); + sWhatsThis = "Sketcher_BSplineInsertKnot"; + sStatusTip = sToolTipText; + sPixmap = "Sketcher_BSplineInsertKnot"; + sAccel = ""; + eType = ForEdit; +} + +void CmdSketcherInsertKnot::activated(int iMsg) +{ + Q_UNUSED(iMsg); + +#if OCC_VERSION_HEX < 0x060900 + QMessageBox::warning(Gui::getMainWindow(), + QObject::tr("Wrong OCE/OCC version"), + QObject::tr("This version of OCE/OCC " + "does not support knot operation. " + "You need 6.9.0 or higher")); + return; +#endif + + // get the selection + std::vector selection; + selection = getSelection().getSelectionEx(0, Sketcher::SketchObject::getClassTypeId()); + + // TODO: let user click on a curve after pressing command. + // 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(); + if (SubNames.size() == 0) { + // Check that only one object is selected, + // as we need only one object to get the new GeoId after multiplicity change + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Selection is empty"), + QObject::tr("Nothing is selected. Please select a b-spline.")); + return; + } + Sketcher::SketchObject* Obj = static_cast(selection[0].getObject()); + + openCommand(QT_TRANSLATE_NOOP("Command", "Insert knot (incomplete)")); + + bool applied = false; + + // TODO: Ensure GeoId is for the BSpline and not for it's internal geometry + int GeoId = std::atoi(SubNames[0].substr(4,4000).c_str()) - 1; + + boost::uuids::uuid bsplinetag = Obj->getGeometry(GeoId)->getTag(); + + try { + // TODO: Get param from user input by clicking on desired spot + // Get param from user input into a box + bool paramPicked; + // TODO: get min/max values from the BSpline + double param = QInputDialog::getDouble( + Gui::getMainWindow(), QObject::tr("Knot parameter"), + QObject::tr("Please provide the parameter where the knot is to be inserted."), + 0.5, -DBL_MAX, DBL_MAX, 8, ¶mPicked); + if (paramPicked) { + Gui::cmdAppObjectArgs(selection[0].getObject(), + "insertBSplineKnot(%d, %lf, %d) ", + GeoId, param, 1); + applied = true; + + // Warning: GeoId list might have changed + // as the consequence of deleting pole circles and + // particularly B-spline GeoID might have changed. + } + } + catch (const Base::CADKernelError& e) { + e.ReportException(); + if (e.getTranslatable()) { + QMessageBox::warning(Gui::getMainWindow(), + QObject::tr("CAD Kernel Error"), + QObject::tr(e.getMessage().c_str())); + } + getSelection().clearSelection(); + } + catch (const Base::Exception& e) { + e.ReportException(); + if (e.getTranslatable()) { + QMessageBox::warning(Gui::getMainWindow(), + QObject::tr("Input Error"), + QObject::tr(e.getMessage().c_str())); + } + getSelection().clearSelection(); + } + + if (applied) + { + // find new geoid for B-spline as GeoId might have changed + const std::vector< Part::Geometry * > &gvals = Obj->getInternalGeometry(); + + int ngeoid = 0; + bool ngfound = false; + + for (std::vector::const_iterator geo = gvals.begin(); geo != gvals.end(); geo++, ngeoid++) { + if ((*geo) && (*geo)->getTag() == bsplinetag) { + ngfound = true; + break; + } + } + + if (ngfound) { + try { + // add internalalignment for new pole + Gui::cmdAppObjectArgs(selection[0].getObject(), "exposeInternalGeometry(%d)", ngeoid); + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + getSelection().clearSelection(); + } + } + } + + if (applied) + commitCommand(); + else + abortCommand(); + + tryAutoRecomputeIfNotSolve(Obj); + getSelection().clearSelection(); +} + +bool CmdSketcherInsertKnot::isActive(void) +{ + return isSketcherBSplineActive(getActiveGuiDocument(), true); +} + void CreateSketcherCommandsBSpline(void) { Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); @@ -987,4 +1126,5 @@ void CreateSketcherCommandsBSpline(void) rcCmdMgr.addCommand(new CmdSketcherIncreaseKnotMultiplicity()); rcCmdMgr.addCommand(new CmdSketcherDecreaseKnotMultiplicity()); rcCmdMgr.addCommand(new CmdSketcherCompModifyKnotMultiplicity()); + rcCmdMgr.addCommand(new CmdSketcherInsertKnot()); } diff --git a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc index eed7a6cc87..1a6497f360 100644 --- a/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc +++ b/src/Mod/Sketcher/Gui/Resources/Sketcher.qrc @@ -214,6 +214,7 @@ icons/splines/Sketcher_BSplineDegree.svg icons/splines/Sketcher_BSplineIncreaseDegree.svg icons/splines/Sketcher_BSplineIncreaseKnotMultiplicity.svg + icons/splines/Sketcher_BSplineInsertKnot.svg icons/splines/Sketcher_BSplineKnotMultiplicity.svg icons/splines/Sketcher_BSplinePoleWeight.svg icons/splines/Sketcher_BSplinePolygon.svg diff --git a/src/Mod/Sketcher/Gui/Resources/icons/splines/Sketcher_BSplineInsertKnot.svg b/src/Mod/Sketcher/Gui/Resources/icons/splines/Sketcher_BSplineInsertKnot.svg new file mode 100644 index 0000000000..52cfa83e60 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Resources/icons/splines/Sketcher_BSplineInsertKnot.svg @@ -0,0 +1,488 @@ + + + Sketcher_BSplineIncreaseKnotMultiplicity + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Sketcher_BSplineIncreaseKnotMultiplicity + + + [bitacovir] + + + Sketcher_Create_Periodic_BSpline + 22-03-2021 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 9d36c7a920..8069e75b62 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -412,7 +412,8 @@ inline void SketcherAddWorkbenchBSplines(Gui::MenuItem& bspline) << "Sketcher_BSplineIncreaseDegree" << "Sketcher_BSplineDecreaseDegree" << "Sketcher_BSplineIncreaseKnotMultiplicity" - << "Sketcher_BSplineDecreaseKnotMultiplicity"; + << "Sketcher_BSplineDecreaseKnotMultiplicity" + << "Sketcher_BSplineInsertKnot"; } template <> @@ -422,7 +423,8 @@ inline void SketcherAddWorkbenchBSplines(Gui::ToolBarItem& bsp << "Sketcher_BSplineConvertToNURB" << "Sketcher_BSplineIncreaseDegree" << "Sketcher_BSplineDecreaseDegree" - << "Sketcher_CompModifyKnotMultiplicity"; + << "Sketcher_CompModifyKnotMultiplicity" + << "Sketcher_BSplineInsertKnot"; } template