From: azv Date: Wed, 15 Jan 2020 11:09:51 +0000 (+0300) Subject: Issue #17347: B-Splines in Sketcher X-Git-Tag: V9_5_0a1~54^2~26 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=52b602cebc1184e09d86608510b0f14aff5d1d4b;p=modules%2Fshaper.git Issue #17347: B-Splines in Sketcher Movement of B-spline curve. --- diff --git a/src/ModuleBase/ModuleBase_IWidgetCreator.cpp b/src/ModuleBase/ModuleBase_IWidgetCreator.cpp index 1e5e8ac33..706533ff2 100644 --- a/src/ModuleBase/ModuleBase_IWidgetCreator.cpp +++ b/src/ModuleBase/ModuleBase_IWidgetCreator.cpp @@ -29,7 +29,8 @@ ModuleBase_IWidgetCreator::~ModuleBase_IWidgetCreator() QWidget* ModuleBase_IWidgetCreator::createPanelByType(const std::string& theType, QWidget* theParent, - const FeaturePtr& theFeature) + const FeaturePtr& theFeature, + Config_WidgetAPI* theWidgetApi) { return 0; } diff --git a/src/ModuleBase/ModuleBase_IWidgetCreator.h b/src/ModuleBase/ModuleBase_IWidgetCreator.h index 85219c27c..8ffc9a0bf 100644 --- a/src/ModuleBase/ModuleBase_IWidgetCreator.h +++ b/src/ModuleBase/ModuleBase_IWidgetCreator.h @@ -68,10 +68,12 @@ public: /// \param theType a panel type /// \param theParent a parent widget /// \param theFeature a feature modified in the panel + /// \param theWidgetApi a low-level API for reading xml definitions of widget /// \return created widget or null virtual QWidget* createPanelByType(const std::string& theType, QWidget* theParent, - const FeaturePtr& theFeature); + const FeaturePtr& theFeature, + Config_WidgetAPI* theWidgetApi = 0); /// Create page by its type /// The default implementation is empty diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index 4060181c0..f2187ee77 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -255,8 +255,8 @@ Q_OBJECT /// \param theFeature a feature object /// \param theToStoreValue a value about necessity to store the widget value to the feature /// \param isUpdateFlushed a flag if update should be flushed on store value - void setFeature(const FeaturePtr& theFeature, const bool theToStoreValue = false, - const bool isUpdateFlushed = true); + virtual void setFeature(const FeaturePtr& theFeature, const bool theToStoreValue = false, + const bool isUpdateFlushed = true); /// Editing mode depends on mode of current operation. This value is defined by it. virtual void setEditingMode(bool isEditing) { myIsEditing = isEditing; } diff --git a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp index 946a282a6..b31226593 100644 --- a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp @@ -99,12 +99,13 @@ bool ModuleBase_WidgetCreatorFactory::hasPanelWidget(const std::string& theType) QWidget* ModuleBase_WidgetCreatorFactory::createPanelByType(const std::string& theType, QWidget* theParent, - const FeaturePtr& theFeature) + const FeaturePtr& theFeature, + Config_WidgetAPI* myWidgetApi) { QWidget* aPanel = 0; if (myPanelToCreator.contains(theType)) { WidgetCreatorPtr aCreator = myPanelToCreator[theType]; - aPanel = aCreator->createPanelByType(theType, theParent, theFeature); + aPanel = aCreator->createPanelByType(theType, theParent, theFeature, myWidgetApi); } return aPanel; } diff --git a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h index 66c229a3b..45cc5b5bb 100644 --- a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h +++ b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h @@ -65,9 +65,12 @@ class MODULEBASE_EXPORT ModuleBase_WidgetCreatorFactory /// \param theType a type /// \param theParent a parent widget /// \param theFeature a feature to fill the panel + /// \param theWidgetApi the widget configuration. + /// The attribute of the model widget is obtained from XML /// \return a created panel or null QWidget* createPanelByType(const std::string& theType, QWidget* theParent, - const FeaturePtr& theFeature); + const FeaturePtr& theFeature, + Config_WidgetAPI* theWidgetApi = 0); /// Returns true if there is a creator, which can make a page by the type /// \param theType a type diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index 7f51a61a7..0467869f9 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -161,8 +161,12 @@ void ModuleBase_WidgetFactory::createPanel(ModuleBase_PageBase* thePage, std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); if (!aPanelName.empty() && ModuleBase_WidgetCreatorFactory::get()->hasPanelWidget(aPanelName)) { QWidget* aPanel = ModuleBase_WidgetCreatorFactory::get()->createPanelByType(aPanelName, - thePage->pageWidget(), theFeature); - thePage->addWidget(aPanel); + thePage->pageWidget(), theFeature, myWidgetApi); + ModuleBase_ModelWidget* aModelWdg = dynamic_cast(aPanel); + if (aModelWdg) + thePage->addModelWidget(aModelWdg); + else + thePage->addWidget(aPanel); thePage->alignToTop(); } } diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index c282d5481..cf6523d41 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -24,6 +24,7 @@ SET(PROJECT_HEADERS SketchPlugin.h SketchPlugin_Arc.h SketchPlugin_BSpline.h + SketchPlugin_BSplineWidget.h SketchPlugin_Circle.h SketchPlugin_Constraint.h SketchPlugin_ConstraintAngle.h @@ -65,17 +66,23 @@ SET(PROJECT_HEADERS SketchPlugin_Point.h SketchPlugin_Projection.h SketchPlugin_Sketch.h + SketchPlugin_SketchDrawer.h SketchPlugin_SketchEntity.h SketchPlugin_Split.h SketchPlugin_Tools.h SketchPlugin_Trim.h SketchPlugin_Validators.h - SketchPlugin_SketchDrawer.h + SketchPlugin_WidgetCreator.h +) + +SET(PROJECT_MOC_HEADERS + SketchPlugin_BSplineWidget.h ) SET(PROJECT_SOURCES SketchPlugin_Arc.cpp SketchPlugin_BSpline.cpp + SketchPlugin_BSplineWidget.cpp SketchPlugin_Circle.cpp SketchPlugin_Constraint.cpp SketchPlugin_ConstraintAngle.cpp @@ -115,12 +122,13 @@ SET(PROJECT_SOURCES SketchPlugin_Point.cpp SketchPlugin_Projection.cpp SketchPlugin_Sketch.cpp + SketchPlugin_SketchDrawer.cpp SketchPlugin_SketchEntity.cpp SketchPlugin_Split.cpp SketchPlugin_Tools.cpp SketchPlugin_Trim.cpp SketchPlugin_Validators.cpp - SketchPlugin_SketchDrawer.cpp + SketchPlugin_WidgetCreator.cpp ) SET(PROJECT_LIBRARIES @@ -129,6 +137,7 @@ SET(PROJECT_LIBRARIES GeomAlgoAPI ModelAPI ModelGeomAlgo + ModuleBase SketcherPrs GeomDataAPI ) @@ -139,14 +148,18 @@ SET(XML_RESOURCES ) SET(TEXT_RESOURCES - SketchPlugin_msg_en.ts - SketchPlugin_msg_fr.ts + SketchPlugin_msg_en.ts + SketchPlugin_msg_fr.ts ) +# sources / moc wrappings +QT_WRAP_MOC(PROJECT_AUTOMOC ${PROJECT_MOC_HEADERS}) + +SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC}) SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES}) ADD_DEFINITIONS(-DSKETCHPLUGIN_EXPORTS) -ADD_LIBRARY(SketchPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES} ${TEXT_RESOURCES}) +ADD_LIBRARY(SketchPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES} ${TEXT_RESOURCES} ${PROJECT_AUTOMOC}) TARGET_LINK_LIBRARIES(SketchPlugin ${PROJECT_LIBRARIES}) INCLUDE_DIRECTORIES( @@ -154,10 +167,12 @@ INCLUDE_DIRECTORIES( ../Events ../ModelAPI ../ModelGeomAlgo + ../ModuleBase ../GeomAPI ../GeomAlgoAPI ../GeomDataAPI ../SketcherPrs + ${OpenCASCADE_INCLUDE_DIR} ) INSTALL(TARGETS SketchPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES}) diff --git a/src/SketchPlugin/SketchPlugin_BSpline.cpp b/src/SketchPlugin/SketchPlugin_BSpline.cpp index 89090e4fe..e8e84177d 100644 --- a/src/SketchPlugin/SketchPlugin_BSpline.cpp +++ b/src/SketchPlugin/SketchPlugin_BSpline.cpp @@ -24,6 +24,7 @@ #include +#include #include #include @@ -41,6 +42,9 @@ SketchPlugin_BSpline::SketchPlugin_BSpline() void SketchPlugin_BSpline::initDerivedClassAttributes() { + data()->addAttribute(START_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(END_ID(), GeomDataAPI_Point2D::typeId()); + data()->addAttribute(POLES_ID(), GeomDataAPI_Point2DArray::typeId()); data()->addAttribute(WEIGHTS_ID(), ModelAPI_AttributeDoubleArray::typeId()); data()->addAttribute(KNOTS_ID(), ModelAPI_AttributeDoubleArray::typeId()); diff --git a/src/SketchPlugin/SketchPlugin_BSpline.h b/src/SketchPlugin/SketchPlugin_BSpline.h index 5a99005f0..a72126c91 100644 --- a/src/SketchPlugin/SketchPlugin_BSpline.h +++ b/src/SketchPlugin/SketchPlugin_BSpline.h @@ -72,6 +72,19 @@ public: return ID; } + /// start point of B-spline curve + inline static const std::string& START_ID() + { + static const std::string ID("start_point"); + return ID; + } + /// end point of B-spline curve + inline static const std::string& END_ID() + { + static const std::string ID("end_point"); + return ID; + } + /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { diff --git a/src/SketchPlugin/SketchPlugin_BSplineWidget.cpp b/src/SketchPlugin/SketchPlugin_BSplineWidget.cpp new file mode 100644 index 000000000..259891a12 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_BSplineWidget.cpp @@ -0,0 +1,177 @@ +// Copyright (C) 2019-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include + +#include + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + + +SketchPlugin_BSplineWidget::SketchPlugin_BSplineWidget( + QWidget* theParent, + const Config_WidgetAPI* theData) + : ModuleBase_ModelWidget(theParent, theData) +{ + QVBoxLayout* aMainLayout = new QVBoxLayout(this); + + // GroupBox to keep widgets for B-spline poles and weights + myPolesGroupBox = new QGroupBox(tr("Poles and weights"), theParent); + aMainLayout->addWidget(myPolesGroupBox); + // layout of GroupBox + QGridLayout* aGroupLayout = new QGridLayout(myPolesGroupBox); + aGroupLayout->setSpacing(4); + aGroupLayout->setColumnStretch(1, 1); + + restoreValueCustom(); +} + +void SketchPlugin_BSplineWidget::setFeature(const FeaturePtr& theFeature, + const bool theToStoreValue, + const bool isUpdateFlushed) +{ + ModuleBase_ModelWidget::setFeature(theFeature, theToStoreValue, isUpdateFlushed); + restoreValueCustom(); +} + +void SketchPlugin_BSplineWidget::deactivate() +{ + ModuleBase_ModelWidget::deactivate(); + storeValueCustom(); +} + + +QList SketchPlugin_BSplineWidget::getControls() const +{ + QList aControls; + std::list::const_iterator anIt = myPoles.begin(); + for (; anIt != myPoles.end(); ++anIt) { + aControls.append(anIt->myX); + aControls.append(anIt->myY); + aControls.append(anIt->myWeight); + } + return aControls; +} + +void SketchPlugin_BSplineWidget::storePolesAndWeights() const +{ + std::shared_ptr aData = myFeature->data(); + AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_BSpline::POLES_ID())); + AttributeDoubleArrayPtr aWeightsArray = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID()); + + aPointArray->setSize((int)myPoles.size()); + aWeightsArray->setSize((int)myPoles.size()); + + std::list::const_iterator anIt = myPoles.begin(); + for (int anIndex = 0; anIt != myPoles.end(); ++anIndex, ++anIt) { + aPointArray->setPnt(anIndex, anIt->myX->value(), anIt->myY->value()); + aWeightsArray->setValue(anIndex, anIt->myWeight->value()); + } +} + +bool SketchPlugin_BSplineWidget::storeValueCustom() +{ + std::shared_ptr aData = myFeature->data(); + if (!aData || !aData->isValid()) // can be on abort of sketcher element + return false; + + AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_BSpline::POLES_ID())); + AttributeDoubleArrayPtr aWeights = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID()); + + bool isBlocked = blockSignals(true); + bool isImmutable = aPoles->setImmutable(true); + + storePolesAndWeights(); + ModuleBase_Tools::flushUpdated(myFeature); + + aPoles->setImmutable(isImmutable); + blockSignals(isBlocked); + + return true; +} + +bool SketchPlugin_BSplineWidget::restoreValueCustom() +{ + if (!myFeature) + return false; + + DataPtr aData = myFeature->data(); + + AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_BSpline::POLES_ID())); + AttributeDoubleArrayPtr aWeights = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID()); + + while (myPoles.size() < aPoles->size()) + addPoleWidget(); + + std::list::iterator anIt = myPoles.begin(); + for (int anIndex = 0; anIt != myPoles.end(); ++anIt, ++anIndex) { + GeomPnt2dPtr aPoint = aPoles->pnt(anIndex); + anIt->myX->setValue(aPoint->x()); + anIt->myY->setValue(aPoint->y()); + anIt->myWeight->setValue(aWeights->value(anIndex)); + } + + return true; +} + +void SketchPlugin_BSplineWidget::addPoleWidget() +{ + QGridLayout* aGroupLay = dynamic_cast(myPolesGroupBox->layout()); + + int aNbPoles = (int)myPoles.size(); + + QString aPoleStr = tr("Pole %1"); + aPoleStr = aPoleStr.arg(aNbPoles + 1); + + QGroupBox* aPoleGroupBox = new QGroupBox(aPoleStr, myPolesGroupBox); + QFormLayout* aPoleLay = new QFormLayout(aPoleGroupBox); + ModuleBase_Tools::adjustMargins(aPoleLay); + aPoleLay->setSpacing(2); + + myPoles.push_back(BSplinePoleWidgets()); + BSplinePoleWidgets& aPoleWidgets = myPoles.back(); + + aPoleWidgets.myX = new ModuleBase_LabelValue(aPoleGroupBox, tr("X")); + aPoleLay->addRow(aPoleWidgets.myX); + aPoleWidgets.myY = new ModuleBase_LabelValue(aPoleGroupBox, tr("Y")); + aPoleLay->addRow(aPoleWidgets.myY); + aPoleWidgets.myWeight = new ModuleBase_ParamSpinBox(aPoleGroupBox); + aPoleWidgets.myWeight->setMinimum(0.0); + aPoleLay->addRow(tr("Weight") + " : ", aPoleWidgets.myWeight); + + aGroupLay->addWidget(aPoleGroupBox, aNbPoles, 1); + + // we should listen textChanged signal as valueChanged do not send when text is modified + connect(aPoleWidgets.myWeight, SIGNAL(textChanged(const QString&)), + this, SIGNAL(valuesModified())); +} diff --git a/src/SketchPlugin/SketchPlugin_BSplineWidget.h b/src/SketchPlugin/SketchPlugin_BSplineWidget.h new file mode 100644 index 000000000..30fa4c6f0 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_BSplineWidget.h @@ -0,0 +1,89 @@ +// Copyright (C) 2019-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef SketchPlugin_BSplineWidget_H +#define SketchPlugin_BSplineWidget_H + + +#include + +#include + +#include +#include +#include + +class QGroupBox; + + +/** \brief Represent a content of the property panel to show/modify parameters of B-spline curve. + * \ingroup GUI + */ +class SketchPlugin_BSplineWidget : public ModuleBase_ModelWidget +{ +Q_OBJECT +public: + /// Constructor + /// \param theParent the parent object + /// \param theData the widget configuation. The attribute of the model widget is obtained from + SketchPlugin_BSplineWidget(QWidget* theParent, + const Config_WidgetAPI* theData); + + virtual ~SketchPlugin_BSplineWidget() {} + + /// The methiod called when widget is deactivated + virtual void deactivate(); + + /// Returns list of widget controls + /// \return a control list + virtual QList getControls() const; + + /// Set feature which is processing by active operation + /// \param theFeature a feature object + /// \param theToStoreValue a value about necessity to store the widget value to the feature + /// \param isUpdateFlushed a flag if update should be flushed on store value + virtual void setFeature(const FeaturePtr& theFeature, const bool theToStoreValue = false, + const bool isUpdateFlushed = true); + +protected: + /// Saves the internal parameters to the given feature + /// \return True in success + virtual bool storeValueCustom(); + + /// Restore value from attribute data to the widget's control + virtual bool restoreValueCustom(); + + /// Create group of widgets related to coordinates of pole and its weight + void addPoleWidget(); + + /// Update attributes of B-spline feature + void storePolesAndWeights() const; + +private: + struct BSplinePoleWidgets { + ModuleBase_LabelValue* myX; + ModuleBase_LabelValue* myY; + ModuleBase_ParamSpinBox* myWeight; + }; + + QGroupBox* myPolesGroupBox; ///< widget to show poles and weights of B-spline curve + std::list myPoles; ///< list of B-spline poles and their weights +}; + +#endif \ No newline at end of file diff --git a/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp b/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp index b1701c1b7..63826c7da 100644 --- a/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroBSpline.cpp @@ -75,6 +75,8 @@ void SketchPlugin_MacroBSpline::initAttributes() data()->addAttribute(REF_POLES_ID(), ModelAPI_AttributeRefAttrList::typeId()); ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), REF_POLES_ID()); + data()->addAttribute(CONTROL_POLYGON_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId()); } @@ -82,16 +84,18 @@ void SketchPlugin_MacroBSpline::execute() { FeaturePtr aBSpline = createBSplineFeature(); - std::list aControlPoles; - createControlPolygon(aBSpline, aControlPoles); - constraintsForPoles(aControlPoles); - - // message to init reentrant operation - static Events_ID anId = ModelAPI_EventReentrantMessage::eventId(); - ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this)); - // set here the last pole to make coincidence with the start point of the next B-spline curve - aMessage->setCreatedFeature(aControlPoles.back()); - Events_Loop::loop()->send(aMessage); + if (boolean(CONTROL_POLYGON_ID())->value()) { + std::list aControlPoles; + createControlPolygon(aBSpline, aControlPoles); + constraintsForPoles(aControlPoles); + + // message to init reentrant operation + static Events_ID anId = ModelAPI_EventReentrantMessage::eventId(); + ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this)); + // set here the last pole to make coincidence with the start point of the next B-spline curve + aMessage->setCreatedFeature(aControlPoles.back()); + Events_Loop::loop()->send(aMessage); + } } // LCOV_EXCL_START @@ -173,6 +177,21 @@ FeaturePtr SketchPlugin_MacroBSpline::createBSplineFeature() for (int index = 0; index < aSize; ++index, ++aMIt) aMults->setValue(index, *aMIt); + SketchPlugin_Sketch* aSketch = + std::dynamic_pointer_cast(aBSpline)->sketch(); + + AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast( + aBSpline->attribute(SketchPlugin_BSpline::START_ID())); + aStartPoint->setValue(aPoles->pnt(0)); + // internal constraint to keep position of the point + createInternalConstraint(aSketch, aStartPoint, aPoles, 0); + + AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast( + aBSpline->attribute(SketchPlugin_BSpline::END_ID())); + aEndPoint->setValue(aPoles->pnt(aPoles->size() - 1)); + // internal constraint to keep position of the point + createInternalConstraint(aSketch, aEndPoint, aPoles, aPoles->size() - 1); + aBSpline->boolean(SketchPlugin_BSpline::AUXILIARY_ID())->setValue( boolean(AUXILIARY_ID())->value()); diff --git a/src/SketchPlugin/SketchPlugin_MacroBSpline.h b/src/SketchPlugin/SketchPlugin_MacroBSpline.h index 7515cadb5..d8a0e5b89 100644 --- a/src/SketchPlugin/SketchPlugin_MacroBSpline.h +++ b/src/SketchPlugin/SketchPlugin_MacroBSpline.h @@ -69,6 +69,13 @@ public: return ID; } + /// flag attribute whether control polygon is need to be created + inline static const std::string& CONTROL_POLYGON_ID() + { + static const std::string ID("need_control_poly"); + return ID; + } + /// Returns the kind of a feature SKETCHPLUGIN_EXPORT virtual const std::string& getKind() { diff --git a/src/SketchPlugin/SketchPlugin_Plugin.cpp b/src/SketchPlugin/SketchPlugin_Plugin.cpp index a6ef2a190..b48e6cfef 100644 --- a/src/SketchPlugin/SketchPlugin_Plugin.cpp +++ b/src/SketchPlugin/SketchPlugin_Plugin.cpp @@ -59,6 +59,7 @@ #include #include #include +#include #include @@ -70,6 +71,8 @@ #include #include +#include + #include #include @@ -92,6 +95,10 @@ static SketchPlugin_Plugin* MY_SKETCH_INSTANCE = new SketchPlugin_Plugin(); SketchPlugin_Plugin::SketchPlugin_Plugin() { + WidgetCreatorFactoryPtr aWidgetCreatorFactory = ModuleBase_WidgetCreatorFactory::get(); + aWidgetCreatorFactory->registerCreator( + std::shared_ptr(new SketchPlugin_WidgetCreator())); + SessionPtr aMgr = ModelAPI_Session::get(); ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); aFactory->registerValidator("SketchPlugin_DistanceAttr", diff --git a/src/SketchPlugin/SketchPlugin_WidgetCreator.cpp b/src/SketchPlugin/SketchPlugin_WidgetCreator.cpp new file mode 100644 index 000000000..37da438b9 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_WidgetCreator.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2019-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include +#include + + +SketchPlugin_WidgetCreator::SketchPlugin_WidgetCreator() + : ModuleBase_IWidgetCreator() +{ + myPanelTypes.insert("bspline-panel"); +} + +void SketchPlugin_WidgetCreator::panelTypes(std::set& theTypes) +{ + theTypes = myPanelTypes; +} + +QWidget* SketchPlugin_WidgetCreator::createPanelByType( + const std::string& theType, + QWidget* theParent, + const FeaturePtr& theFeature, + Config_WidgetAPI* theWidgetApi) +{ + QWidget* aWidget = 0; + if (theType == "bspline-panel") { + SketchPlugin_BSplineWidget* aPanel = new SketchPlugin_BSplineWidget(theParent, theWidgetApi); + aPanel->setFeature(theFeature); + aWidget = aPanel; + } + return aWidget; +} diff --git a/src/SketchPlugin/SketchPlugin_WidgetCreator.h b/src/SketchPlugin/SketchPlugin_WidgetCreator.h new file mode 100644 index 000000000..9b1a9bac1 --- /dev/null +++ b/src/SketchPlugin/SketchPlugin_WidgetCreator.h @@ -0,0 +1,63 @@ +// Copyright (C) 2019-2020 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef SketchPlugin_WidgetCreator_H +#define SketchPlugin_WidgetCreator_H + + +#include +#include + +#include +#include + +class QWidget; + +/** + * \ingroup GUI + * Interface to WidgetCreator which can create specific widgets by type + */ +class SketchPlugin_WidgetCreator : public ModuleBase_IWidgetCreator +{ +public: + /// Default constructor + SketchPlugin_WidgetCreator(); + + /// Virtual destructor + virtual ~SketchPlugin_WidgetCreator() {} + + /// Returns a container of possible page types, which this creator can process + /// \param theTypes a list of type names + virtual void panelTypes(std::set& theTypes); + + /// Create panel control by its type. + /// The default implementation is empty + /// \param theType a panel type + /// \param theParent a parent widget + /// \param theFeature a feature modified in the panel + /// \return created widget or null + virtual QWidget* createPanelByType(const std::string& theType, + QWidget* theParent, + const FeaturePtr& theFeature, + Config_WidgetAPI* theWidgetApi); +private: + std::set myPanelTypes; ///< types of panels +}; + +#endif \ No newline at end of file diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 2f3ee2761..241c30de0 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -602,16 +602,21 @@ - + + + - + + #include #include +#include #include #include @@ -101,33 +102,7 @@ static EntityWrapperPtr createScalar(const AttributePtr& theAttribute, static EntityWrapperPtr createScalarArray(const AttributePtr& theAttribute, PlaneGCSSolver_Storage* theStorage) { - class ArrayAttribute { - public: - ArrayAttribute(AttributePtr theAttribute) - { - myDouble = std::dynamic_pointer_cast(theAttribute); - myInteger = std::dynamic_pointer_cast(theAttribute); - } - - bool isInitialized() const - { - return (myDouble && myDouble->isInitialized()) || (myInteger && myInteger->isInitialized()); - } - - int size() const - { - return myDouble.get() ? myDouble->size() : myInteger->size(); - } - - double value(const int theIndex) const - { - return myDouble.get() ? myDouble->value(theIndex) : myInteger->value(theIndex); - } - - private: - AttributeDoubleArrayPtr myDouble; - AttributeIntArrayPtr myInteger; - } anArray(theAttribute); + PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute); if (!anArray.isInitialized()) return EntityWrapperPtr(); @@ -220,3 +195,59 @@ EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute( aResult->setExternal(true); return aResult; } + +bool PlaneGCSSolver_AttributeBuilder::updateAttribute( + AttributePtr theAttribute, + EntityWrapperPtr theEntity) +{ + bool isUpdated = false; + GCS::SET_pD aParamsToRemove; + // rebuild array if its size is changed + if (theEntity->type() == ENTITY_POINT_ARRAY) { + std::shared_ptr aWrapper = + std::dynamic_pointer_cast(theEntity); + std::shared_ptr anAttribute = + std::dynamic_pointer_cast(theAttribute); + + if (aWrapper->size() != anAttribute->size()) { + std::vector aPointsArray = aWrapper->array(); + while (anAttribute->size() > (int)aPointsArray.size()) { + // add points to the middle of array + aPointsArray.insert(--aPointsArray.end(), createPoint(GeomPnt2dPtr(), myStorage)); + } + + while (anAttribute->size() < (int)aPointsArray.size()) { + // remove middle points + std::vector::iterator anIt = --aPointsArray.end(); + GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(*anIt); + aParamsToRemove.insert(aParams.begin(), aParams.end()); + aPointsArray.erase(anIt); + } + + aWrapper->setArray(aPointsArray); + } + } + else if (theEntity->type() == ENTITY_SCALAR_ARRAY) { + std::shared_ptr aWrapper = + std::dynamic_pointer_cast(theEntity); + if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) { + aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper); + std::shared_ptr aNewArray = + std::dynamic_pointer_cast( + createAttribute(theAttribute)); + aWrapper->setArray(aNewArray->array()); + isUpdated = true; + } + } + + if (!aParamsToRemove.empty()) { + if (myStorage) + myStorage->removeParameters(aParamsToRemove); + else { + std::for_each(aParamsToRemove.begin(), aParamsToRemove.end(), + [](double* theParam) { delete theParam; }); + } + } + + return isUpdated || theEntity->update(theAttribute); +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h index 7d21983b3..adc0e5720 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h @@ -38,6 +38,10 @@ public: /// \return Created wrapper of the attribute applicable for specific solver virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute); + /// \brief Update entity by the attribute values. + /// \return \c true if any value is updated. + virtual bool updateAttribute(AttributePtr theAttribute, EntityWrapperPtr theEntity); + /// \brief Blank. To be defined in derived class. virtual EntityWrapperPtr createFeature(FeaturePtr) { return EntityWrapperPtr(); } diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.cpp index 225c4344f..be2e0bf81 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.cpp @@ -19,7 +19,21 @@ #include +#include + PlaneGCSSolver_BooleanWrapper::PlaneGCSSolver_BooleanWrapper(bool theParam) : myValue(theParam) { } + +bool PlaneGCSSolver_BooleanWrapper::update(AttributePtr theAttribute) +{ + bool isUpdated = false; + AttributeBooleanPtr aBoolean = + std::dynamic_pointer_cast(theAttribute); + if (aBoolean) { + isUpdated = value() != aBoolean->value(); + setValue(aBoolean->value()); + } + return isUpdated; +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.h index 3bd1d8d2e..667eb083d 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.h @@ -42,6 +42,11 @@ public: virtual SketchSolver_EntityType type() const { return ENTITY_BOOLEAN; } +protected: + /// \brief Update entity by the values of theAttribute + /// \return \c true if any value of attribute is not equal to the stored in the entity + virtual bool update(std::shared_ptr theAttribute); + protected: bool myValue; }; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h index b99cc7c3b..ab6ea7894 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h @@ -23,6 +23,8 @@ #include #include +#include + /** * Wrapper providing operations with PlaneGCS constraints. */ diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h index 5eceaf63c..bc86246e5 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h @@ -22,12 +22,11 @@ #include -#include -#include - -#include +#include #include +class ModelAPI_Attribute; + class PlaneGCSSolver_EntityWrapper; typedef std::shared_ptr EntityWrapperPtr; @@ -55,6 +54,14 @@ public: const std::map& additionalAttributes() const { return myAdditionalAttributes; } +protected: + /// \brief Update entity by the values of theAttribute + /// \return \c true if any value of attribute is not equal to the stored in the entity + virtual bool update(std::shared_ptr theAttribute) + { return false; } + + friend class PlaneGCSSolver_AttributeBuilder; + private: bool myExternal; std::map myAdditionalAttributes; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp index de163985d..499dfe1af 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp @@ -40,8 +40,6 @@ #include #include -static bool isAttributeApplicable(const std::string& theAttrName, - const std::string& theOwnerName); static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes); static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes); @@ -69,7 +67,7 @@ EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute( { FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner()); EntityWrapperPtr anAttr; - if (isAttributeApplicable(theAttribute->id(), anOwner->getKind())) + if (PlaneGCSSolver_Tools::isAttributeApplicable(theAttribute->id(), anOwner->getKind())) anAttr = PlaneGCSSolver_AttributeBuilder::createAttribute(theAttribute); if (anAttr) myAttributes[theAttribute] = anAttr; @@ -341,56 +339,3 @@ EntityWrapperPtr createBSpline(const AttributeEntityMap& theAttributes) return EdgeWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewSpline)); } - -bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName) -{ - if (theOwnerName == SketchPlugin_Arc::ID()) { - return theAttrName == SketchPlugin_Arc::CENTER_ID() || - theAttrName == SketchPlugin_Arc::START_ID() || - theAttrName == SketchPlugin_Arc::END_ID() || - theAttrName == SketchPlugin_Arc::REVERSED_ID(); - } - else if (theOwnerName == SketchPlugin_Circle::ID()) { - return theAttrName == SketchPlugin_Circle::CENTER_ID() || - theAttrName == SketchPlugin_Circle::RADIUS_ID(); - } - else if (theOwnerName == SketchPlugin_Line::ID()) { - return theAttrName == SketchPlugin_Line::START_ID() || - theAttrName == SketchPlugin_Line::END_ID(); - } - else if (theOwnerName == SketchPlugin_Ellipse::ID()) { - return theAttrName == SketchPlugin_Ellipse::CENTER_ID() || - theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() || - theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() || - theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() || - theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() || - theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() || - theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() || - theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() || - theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID(); - } - else if (theOwnerName == SketchPlugin_EllipticArc::ID()) { - return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() || - theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() || - theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() || - theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() || - theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() || - theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() || - theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() || - theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() || - theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() || - theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() || - theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() || - theAttrName == SketchPlugin_EllipticArc::REVERSED_ID(); - } - else if (theOwnerName == SketchPlugin_BSpline::ID()) { - return theAttrName == SketchPlugin_BSpline::POLES_ID() || - theAttrName == SketchPlugin_BSpline::WEIGHTS_ID() || - theAttrName == SketchPlugin_BSpline::KNOTS_ID() || - theAttrName == SketchPlugin_BSpline::MULTS_ID() || - theAttrName == SketchPlugin_BSpline::DEGREE_ID(); - } - - // suppose that all remaining features are points - return theAttrName == SketchPlugin_Point::COORD_ID(); -} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.cpp index 33a7954df..a409fb448 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.cpp @@ -18,9 +18,32 @@ // #include +#include + +#include + +#include PlaneGCSSolver_PointArrayWrapper::PlaneGCSSolver_PointArrayWrapper( const std::vector& thePoints) : myPoints(thePoints) { } + +bool PlaneGCSSolver_PointArrayWrapper::update(AttributePtr theAttribute) +{ + bool isUpdated = false; + std::shared_ptr aPointArray = + std::dynamic_pointer_cast(theAttribute); + if (aPointArray && aPointArray->size() == (int)myPoints.size()) { + std::vector::iterator aPIt = myPoints.begin(); + for (int anIndex = 0; aPIt != myPoints.end(); ++aPIt, ++anIndex) { + GeomPnt2dPtr aPnt = aPointArray->pnt(anIndex); + + const GCSPointPtr& aGCSPoint = (*aPIt)->point(); + isUpdated = PlaneGCSSolver_Tools::updateValue(aPnt->x(), *(aGCSPoint->x)) || isUpdated; + isUpdated = PlaneGCSSolver_Tools::updateValue(aPnt->y(), *(aGCSPoint->y)) || isUpdated; + } + } + return isUpdated; +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.h index 8752b79c9..0524be273 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.h @@ -38,10 +38,20 @@ public: /// \breif Size of array int size() const { return (int)myPoints.size(); } + /// \brief Return array of points + const std::vector& array() const { return myPoints; } + /// \breif Set points + void setArray(const std::vector& thePoints) { myPoints = thePoints; } + /// \brief Return type of current entity virtual SketchSolver_EntityType type() const { return ENTITY_POINT_ARRAY; } +protected: + /// \brief Update entity by the values of theAttribute + /// \return \c true if any value of attribute is not equal to the stored in the entity + virtual bool update(std::shared_ptr theAttribute); + private: std::vector myPoints; }; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.cpp index bfb662590..bda73b197 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.cpp @@ -18,8 +18,23 @@ // #include +#include + +#include PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(const GCSPointPtr thePoint) : myPoint(thePoint) { } + +bool PlaneGCSSolver_PointWrapper::update(AttributePtr theAttribute) +{ + bool isUpdated = false; + std::shared_ptr aPoint2D = + std::dynamic_pointer_cast(theAttribute); + if (aPoint2D) { + isUpdated = PlaneGCSSolver_Tools::updateValue(aPoint2D->x(), *(myPoint->x)) || isUpdated; + isUpdated = PlaneGCSSolver_Tools::updateValue(aPoint2D->y(), *(myPoint->y)) || isUpdated; + } + return isUpdated; +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.h index 3cb05e124..a50497523 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.h @@ -42,6 +42,11 @@ public: virtual SketchSolver_EntityType type() const { return ENTITY_POINT; } +protected: + /// \brief Update entity by the values of theAttribute + /// \return \c true if any value of attribute is not equal to the stored in the entity + virtual bool update(std::shared_ptr theAttribute); + private: GCSPointPtr myPoint; }; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.cpp index b599f8fbd..9d5615492 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.cpp @@ -18,8 +18,22 @@ // #include +#include PlaneGCSSolver_ScalarArrayWrapper::PlaneGCSSolver_ScalarArrayWrapper(const GCS::VEC_pD& theParam) : myValue(theParam) { } + +bool PlaneGCSSolver_ScalarArrayWrapper::update(AttributePtr theAttribute) +{ + bool isUpdated = false; + PlaneGCSSolver_Tools::AttributeArray anArray(theAttribute); + if (anArray.isInitialized() && anArray.size() == (int)myValue.size()) { + for (int anIndex = 0; anIndex < anArray.size(); ++anIndex) { + isUpdated = PlaneGCSSolver_Tools::updateValue(anArray.value(anIndex), *(myValue[anIndex])) + || isUpdated; + } + } + return isUpdated; +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.h index 40746cfb4..6b0992ec2 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.h @@ -31,13 +31,23 @@ class PlaneGCSSolver_ScalarArrayWrapper : public PlaneGCSSolver_EntityWrapper public: PlaneGCSSolver_ScalarArrayWrapper(const GCS::VEC_pD& theParam); + /// \breif Size of array + int size() const { return (int)myValue.size(); } + /// \brief Return array of PlaneGCS parameters const GCS::VEC_pD& array() const { return myValue; } + /// \breif Set array of parameters + void setArray(const GCS::VEC_pD& theParams) { myValue = theParams; } /// \brief Return type of current entity virtual SketchSolver_EntityType type() const { return ENTITY_SCALAR_ARRAY; } +protected: + /// \brief Update entity by the values of theAttribute + /// \return \c true if any value of attribute is not equal to the stored in the entity + virtual bool update(std::shared_ptr theAttribute); + protected: GCS::VEC_pD myValue; ///< list of pointers to values provided by the storage }; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.cpp index dc6d72ff3..399b37531 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.cpp @@ -18,6 +18,10 @@ // #include +#include + +#include +#include PlaneGCSSolver_ScalarWrapper::PlaneGCSSolver_ScalarWrapper(double *const theParam) : myValue(theParam) @@ -33,3 +37,29 @@ double PlaneGCSSolver_ScalarWrapper::value() const { return *myValue; } + +bool PlaneGCSSolver_ScalarWrapper::update(AttributePtr theAttribute) +{ + double anAttrValue = 0.0; + AttributeDoublePtr aDouble = + std::dynamic_pointer_cast(theAttribute); + if (aDouble) + anAttrValue = aDouble->value(); + else { + AttributeIntegerPtr anInt = + std::dynamic_pointer_cast(theAttribute); + if (anInt) + anAttrValue = anInt->value(); + else + return false; + } + + // There is possible an angular value, which is converted between degrees and radians. + // So, we use its value instead of using direct pointer to variable. + double aCurrentValue = value(); + + bool isUpdated = PlaneGCSSolver_Tools::updateValue(anAttrValue, aCurrentValue); + if (isUpdated) + setValue(aCurrentValue); + return isUpdated; +} diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.h index 454f5ea01..01238d579 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.h @@ -44,6 +44,11 @@ public: virtual SketchSolver_EntityType type() const { return ENTITY_SCALAR; } +protected: + /// \brief Update entity by the values of theAttribute + /// \return \c true if any value of attribute is not equal to the stored in the entity + virtual bool update(std::shared_ptr theAttribute); + protected: double* myValue; ///< pointer to value provided by the storage }; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index 328b7144c..3c1e8fa43 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -106,55 +106,6 @@ EntityWrapperPtr PlaneGCSSolver_Storage::createAttribute( return aResult; } -/// \brief Update value -static bool updateValue(const double& theSource, double& theDest) -{ - static const double aTol = 1.e4 * tolerance; - bool isUpdated = fabs(theSource - theDest) > aTol; - if (isUpdated) - theDest = theSource; - return isUpdated; -} - -/// \brief Update coordinates of the point or scalar using its base attribute -static bool updateValues(AttributePtr& theAttribute, EntityWrapperPtr& theEntity) -{ - bool isUpdated = false; - - std::shared_ptr aPoint2D = - std::dynamic_pointer_cast(theAttribute); - if (aPoint2D) { - const GCSPointPtr& aGCSPoint = - std::dynamic_pointer_cast(theEntity)->point(); - isUpdated = updateValue(aPoint2D->x(), *(aGCSPoint->x)) || isUpdated; - isUpdated = updateValue(aPoint2D->y(), *(aGCSPoint->y)) || isUpdated; - } else { - AttributeDoublePtr aScalar = - std::dynamic_pointer_cast(theAttribute); - if (aScalar) { - ScalarWrapperPtr aWrapper = - std::dynamic_pointer_cast(theEntity); - // There is possible angular value, which is converted between degrees and radians. - // So, we use its value instead of using direct pointer to value. - double aValue = aWrapper->value(); - isUpdated = updateValue(aScalar->value(), aValue); - if (isUpdated) - aWrapper->setValue(aValue); - } else { - AttributeBooleanPtr aBoolean = - std::dynamic_pointer_cast(theAttribute); - if (aBoolean) { - BooleanWrapperPtr aWrapper = - std::dynamic_pointer_cast(theEntity); - isUpdated = aWrapper->value() != aBoolean->value(); - aWrapper->setValue(aBoolean->value()); - } - } - } - - return isUpdated; -} - static bool hasReference(std::shared_ptr theFeature, const std::string& theFeatureKind) { @@ -207,9 +158,7 @@ bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce) std::list anAttributes = theFeature->data()->attributes(std::string()); std::list::iterator anAttrIt = anAttributes.begin(); for (; anAttrIt != anAttributes.end(); ++anAttrIt) - if ((*anAttrIt)->attributeType() == GeomDataAPI_Point2D::typeId() || - (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId() || - (*anAttrIt)->attributeType() == ModelAPI_AttributeBoolean::typeId()) + if (PlaneGCSSolver_Tools::isAttributeApplicable((*anAttrIt)->id(), theFeature->getKind())) isUpdated = update(*anAttrIt) || isUpdated; // check external attribute is changed @@ -261,7 +210,8 @@ bool PlaneGCSSolver_Storage::update(AttributePtr theAttribute, bool theForce) return aRelated.get() != 0; } - bool isUpdated = updateValues(anAttribute, aRelated); + PlaneGCSSolver_AttributeBuilder aBuilder(aRelated->isExternal() ? 0 : this); + bool isUpdated = aBuilder.updateAttribute(anAttribute, aRelated); if (isUpdated) { setNeedToResolve(true); notify(aFeature); diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index 5fe371915..5224c8443 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include #include @@ -39,6 +41,9 @@ #include #include +#include +#include +#include #include #include #include @@ -52,9 +57,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include @@ -62,6 +70,9 @@ #include #include +#include +#include + #include @@ -129,7 +140,9 @@ static ConstraintWrapperPtr std::shared_ptr theEntity2); static GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar); +static GCS::SET_pD scalarArrayParameters(const EntityWrapperPtr& theArray); static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint); +static GCS::SET_pD pointArrayParameters(const EntityWrapperPtr& theArray); static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine); static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle); static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc); @@ -399,8 +412,12 @@ GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity) case ENTITY_SCALAR: case ENTITY_ANGLE: return scalarParameters(GCS_SCALAR_WRAPPER(theEntity)); + case ENTITY_SCALAR_ARRAY: + return scalarArrayParameters(theEntity); case ENTITY_POINT: return pointParameters(GCS_POINT_WRAPPER(theEntity)); + case ENTITY_POINT_ARRAY: + return pointArrayParameters(theEntity); case ENTITY_LINE: return lineParameters(GCS_EDGE_WRAPPER(theEntity)); case ENTITY_CIRCLE: @@ -418,6 +435,98 @@ GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity) return GCS::SET_pD(); } +bool PlaneGCSSolver_Tools::isAttributeApplicable(const std::string& theAttrName, + const std::string& theOwnerName) +{ + if (theOwnerName == SketchPlugin_Arc::ID()) { + return theAttrName == SketchPlugin_Arc::CENTER_ID() || + theAttrName == SketchPlugin_Arc::START_ID() || + theAttrName == SketchPlugin_Arc::END_ID() || + theAttrName == SketchPlugin_Arc::REVERSED_ID(); + } + else if (theOwnerName == SketchPlugin_Circle::ID()) { + return theAttrName == SketchPlugin_Circle::CENTER_ID() || + theAttrName == SketchPlugin_Circle::RADIUS_ID(); + } + else if (theOwnerName == SketchPlugin_Line::ID()) { + return theAttrName == SketchPlugin_Line::START_ID() || + theAttrName == SketchPlugin_Line::END_ID(); + } + else if (theOwnerName == SketchPlugin_Ellipse::ID()) { + return theAttrName == SketchPlugin_Ellipse::CENTER_ID() || + theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() || + theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() || + theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() || + theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() || + theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() || + theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() || + theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() || + theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID(); + } + else if (theOwnerName == SketchPlugin_EllipticArc::ID()) { + return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() || + theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() || + theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() || + theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() || + theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() || + theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() || + theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() || + theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() || + theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() || + theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() || + theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() || + theAttrName == SketchPlugin_EllipticArc::REVERSED_ID(); + } + else if (theOwnerName == SketchPlugin_BSpline::ID()) { + return theAttrName == SketchPlugin_BSpline::POLES_ID() || + theAttrName == SketchPlugin_BSpline::WEIGHTS_ID() || + theAttrName == SketchPlugin_BSpline::KNOTS_ID() || + theAttrName == SketchPlugin_BSpline::MULTS_ID() || + theAttrName == SketchPlugin_BSpline::DEGREE_ID() || + theAttrName == SketchPlugin_BSpline::START_ID() || + theAttrName == SketchPlugin_BSpline::END_ID(); + } + + // suppose that all remaining features are points + return theAttrName == SketchPlugin_Point::COORD_ID(); +} + +/// \brief Update value +bool PlaneGCSSolver_Tools::updateValue(const double& theSource, double& theDest, + const double theTolerance) +{ + bool isUpdated = fabs(theSource - theDest) > theTolerance; + if (isUpdated) + theDest = theSource; + return isUpdated; +} + + + + + +// ================ AttributeArray methods ========================== +PlaneGCSSolver_Tools::AttributeArray::AttributeArray(AttributePtr theAttribute) +{ + myDouble = std::dynamic_pointer_cast(theAttribute); + myInteger = std::dynamic_pointer_cast(theAttribute); +} + +bool PlaneGCSSolver_Tools::AttributeArray::isInitialized() const +{ + return (myDouble && myDouble->isInitialized()) || (myInteger && myInteger->isInitialized()); +} + +int PlaneGCSSolver_Tools::AttributeArray::size() const +{ + return myDouble.get() ? myDouble->size() : myInteger->size(); +} + +double PlaneGCSSolver_Tools::AttributeArray::value(const int theIndex) const +{ + return myDouble.get() ? myDouble->value(theIndex) : myInteger->value(theIndex); +} + @@ -758,6 +867,13 @@ GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar) return aParams; } +GCS::SET_pD scalarArrayParameters(const EntityWrapperPtr& theArray) +{ + ScalarArrayWrapperPtr anArray = + std::dynamic_pointer_cast(theArray); + return GCS::SET_pD(anArray->array().begin(), anArray->array().end()); +} + GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint) { GCS::SET_pD aParams; @@ -766,6 +882,19 @@ GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint) return aParams; } +GCS::SET_pD pointArrayParameters(const EntityWrapperPtr& theArray) +{ + GCS::SET_pD aParams; + PointArrayWrapperPtr aPoints = + std::dynamic_pointer_cast(theArray); + for (std::vector::const_iterator anIt = aPoints->array().begin(); + anIt != aPoints->array().end(); ++anIt) { + GCS::SET_pD aPointParams = PlaneGCSSolver_Tools::parameters(*anIt); + aParams.insert(aPointParams.begin(), aPointParams.end()); + } + return aParams; +} + GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine) { GCS::SET_pD aParams; diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h index d90fecbe0..b80f254f4 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h @@ -29,6 +29,9 @@ class GeomAPI_Ellipse2d; class GeomAPI_Lin2d; class GeomAPI_Pnt2d; +class ModelAPI_AttributeDoubleArray; +class ModelAPI_AttributeIntArray; + /** \namespace PlaneGCSSolver_Tools * \ingroup Plugins * \brief Converter tools @@ -67,6 +70,12 @@ namespace PlaneGCSSolver_Tools const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(), const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()); + /// \brief Return \c true if the attribute is used in PlaneGCS solver + /// \param[in] theAttrName name of the attribute + /// \param[in] theOwnerName name of the parent feature + bool isAttributeApplicable(const std::string& theAttrName, + const std::string& theOwnerName); + /// \brief Convert entity to point /// \return empty pointer if the entity is not a point std::shared_ptr point(EntityWrapperPtr theEntity); @@ -91,6 +100,28 @@ namespace PlaneGCSSolver_Tools /// brief Return list of parameters for the given entity GCS::SET_pD parameters(const EntityWrapperPtr& theEntity); + + /// \brief Update value in theDest if theSource is differ more than theTolerance + /// \return \c true if the value was updated. + bool updateValue(const double& theSource, double& theDest, + const double theTolerance = 1.e-4 * tolerance); + + /// \brief Provide an interface to access values in attribute which is an array of values + class AttributeArray + { + public: + AttributeArray(AttributePtr theAttribute); + + bool isInitialized() const; + + int size() const; + + double value(const int theIndex) const; + + private: + std::shared_ptr myDouble; + std::shared_ptr myInteger; + }; }; #endif diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index a3e0bf2d0..0099869f5 100644 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -225,8 +225,11 @@ void XGUI_PropertyPanel::createContentPanel(FeaturePtr theFeature) QString aXmlRepr = anOperation->getDescription()->xmlRepresentation(); ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myOperationMgr->workshop()); - aFactory.createPanel(contentWidget(), theFeature); - /// Apply button should be update if the feature was modified by the panel + ModuleBase_PageBase* aPage = contentWidget(); + aFactory.createPanel(aPage, theFeature); + // update model widgets if exist + setModelWidgets(aPage->modelWidgets()); + // Apply button should be update if the feature was modified by the panel myOperationMgr->onValidateOperation(); } ModuleBase_OperationFeature* aFeatureOp =