]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #17347: B-Splines in Sketcher
authorazv <azv@opencascade.com>
Wed, 15 Jan 2020 11:09:51 +0000 (14:09 +0300)
committerazv <azv@opencascade.com>
Wed, 15 Jan 2020 11:09:51 +0000 (14:09 +0300)
Movement of B-spline curve.

36 files changed:
src/ModuleBase/ModuleBase_IWidgetCreator.cpp
src/ModuleBase/ModuleBase_IWidgetCreator.h
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp
src/ModuleBase/ModuleBase_WidgetCreatorFactory.h
src/ModuleBase/ModuleBase_WidgetFactory.cpp
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_BSpline.cpp
src/SketchPlugin/SketchPlugin_BSpline.h
src/SketchPlugin/SketchPlugin_BSplineWidget.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_BSplineWidget.h [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_MacroBSpline.cpp
src/SketchPlugin/SketchPlugin_MacroBSpline.h
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_WidgetCreator.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_WidgetCreator.h [new file with mode: 0644]
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_AttributeBuilder.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_BooleanWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_EntityWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_FeatureBuilder.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointArrayWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_PointWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarArrayWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ScalarWrapper.h
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp
src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.h
src/XGUI/XGUI_PropertyPanel.cpp

index 1e5e8ac33d104300d2501f491ce88acc3f1303fc..706533ff23c87c1159879e60d545200a7a7f48d0 100644 (file)
@@ -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;
 }
index 85219c27cb044e9132d2a9a6b1d75f9ac20796e0..8ffc9a0bfa135038f10ad277478d18e57387d7a8 100644 (file)
@@ -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
index 4060181c0d412c27e0e812e9dc8393c2b1168ec4..f2187ee771d36e8815cd013247b3f9c90d067794 100644 (file)
@@ -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; }
index 946a282a68eb28d825bc9542b1f58ca392f94fbf..b3122659346d5d5ca98be1d0400a1d07b67d51d9 100644 (file)
@@ -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;
 }
index 66c229a3b459466fb479f5391dc35f20bea06a4a..45cc5b5bb19fb5d6192c1b600400303fbdf987c0 100644 (file)
@@ -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
index 7f51a61a7cebe597e8b0cb4c1b41f1636c814238..0467869f9b0e40256c5d006b77c42056c8999925 100644 (file)
@@ -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<ModuleBase_ModelWidget*>(aPanel);
+    if (aModelWdg)
+      thePage->addModelWidget(aModelWdg);
+    else
+      thePage->addWidget(aPanel);
     thePage->alignToTop();
   }
 }
index c282d548131921be6031d9192a9cf72f87277d52..cf6523d41558a395882e1294e0826b202eca678b 100644 (file)
@@ -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})
index 89090e4fe4051488042d261229ef5a001ac1ee6f..e8e84177d5480547fde7db0e3f2003408c9331d7 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <GeomAPI_Pnt2d.h>
 
+#include <GeomDataAPI_Point2D.h>
 #include <GeomDataAPI_Point2DArray.h>
 
 #include <ModelAPI_AttributeDoubleArray.h>
@@ -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());
index 5a99005f00e353b81f9e51110777ac98cfa1e62d..a72126c91f87218a72ad6a6158a1520e9cd5b30d 100644 (file)
@@ -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 (file)
index 0000000..259891a
--- /dev/null
@@ -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 <SketchPlugin_BSplineWidget.h>
+
+#include <SketchPlugin_BSpline.h>
+
+#include <ModuleBase_Tools.h>
+
+#include <ModelAPI_AttributeDoubleArray.h>
+
+#include <GeomDataAPI_Point2DArray.h>
+
+#include <GeomAPI_Pnt2d.h>
+
+#include <QFormLayout>
+#include <QGroupBox>
+#include <QLabel>
+#include <QVBoxLayout>
+
+
+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<QWidget*> SketchPlugin_BSplineWidget::getControls() const
+{
+  QList<QWidget*> aControls;
+  std::list<BSplinePoleWidgets>::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<ModelAPI_Data> aData = myFeature->data();
+  AttributePoint2DArrayPtr aPointArray = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
+      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<BSplinePoleWidgets>::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<ModelAPI_Data> aData = myFeature->data();
+  if (!aData || !aData->isValid()) // can be on abort of sketcher element
+    return false;
+
+  AttributePoint2DArrayPtr aPoles = std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(
+      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<GeomDataAPI_Point2DArray>(
+      aData->attribute(SketchPlugin_BSpline::POLES_ID()));
+  AttributeDoubleArrayPtr aWeights = aData->realArray(SketchPlugin_BSpline::WEIGHTS_ID());
+
+  while (myPoles.size() < aPoles->size())
+    addPoleWidget();
+
+  std::list<BSplinePoleWidgets>::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<QGridLayout*>(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 (file)
index 0000000..30fa4c6
--- /dev/null
@@ -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 <SketchPlugin.h>
+
+#include <ModelAPI_Feature.h>
+
+#include <ModuleBase_LabelValue.h>
+#include <ModuleBase_ModelWidget.h>
+#include <ModuleBase_ParamSpinBox.h>
+
+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<QWidget*> 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<BSplinePoleWidgets> myPoles; ///< list of B-spline poles and their weights
+};
+
+#endif
\ No newline at end of file
index b1701c1b723dc6af1982b025950a40830672ad46..63826c7da4d92ab455a5ce310b738a696b62c6d7 100644 (file)
@@ -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<FeaturePtr> 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<FeaturePtr> 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<SketchPlugin_Feature>(aBSpline)->sketch();
+
+  AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+      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<GeomDataAPI_Point2D>(
+      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());
 
index 7515cadb5f4f0f7154719c436d126b6e1b0c7546..d8a0e5b89d5cdc20282c099485ed3f7794f8745d 100644 (file)
@@ -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()
   {
index a6ef2a190e47f0960eb2964d3baeba18325a8b2c..b48e6cfef86fe702f08c1812e451e50374b2d75f 100644 (file)
@@ -59,6 +59,7 @@
 #include <SketchPlugin_EllipticArc.h>
 #include <SketchPlugin_MacroEllipticArc.h>
 #include <SketchPlugin_SketchDrawer.h>
+#include <SketchPlugin_WidgetCreator.h>
 
 #include <SketcherPrs_Tools.h>
 
@@ -70,6 +71,8 @@
 #include <ModelAPI_Validator.h>
 #include <ModelAPI_Data.h>
 
+#include <ModuleBase_WidgetCreatorFactory.h>
+
 #include <Config_PropManager.h>
 
 #include <memory>
@@ -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<SketchPlugin_WidgetCreator>(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 (file)
index 0000000..37da438
--- /dev/null
@@ -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 <SketchPlugin_WidgetCreator.h>
+#include <SketchPlugin_BSplineWidget.h>
+
+
+SketchPlugin_WidgetCreator::SketchPlugin_WidgetCreator()
+  : ModuleBase_IWidgetCreator()
+{
+  myPanelTypes.insert("bspline-panel");
+}
+
+void SketchPlugin_WidgetCreator::panelTypes(std::set<std::string>& 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 (file)
index 0000000..9b1a9ba
--- /dev/null
@@ -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 <SketchPlugin.h>
+#include <ModuleBase_IWidgetCreator.h>
+
+#include <string>
+#include <set>
+
+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<std::string>& 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<std::string> myPanelTypes; ///< types of panels
+};
+
+#endif
\ No newline at end of file
index 2f3ee27615c0e378f89f6132dea3956c481f2a16..241c30de0c6c75be1a9323687fb3e963f682962c 100644 (file)
       <feature id="SketchBSpline"
                title="B-spline"
                tooltip="Create B-spline curve"
+               property_panel_id="bspline-panel"
                icon="icons/Sketch/bspline.png"
                helpfile="bsplineFeature.html"
                internal="1">
-        <sketch-bspline_selector id="poles"
-                                 weights="weights"
-                                 title="Poles and weights"
-                                 tooltip="B-spline poles and weights"
-                                 enable_value="enable_by_preferences">
+        <sketch-2dpoint_selector id="start_point" accept_expressions="0" title="Start point" tooltip="Start point coordinates"
+                                 enable_value="enable_by_preferences"/>
+        <sketch-2dpoint_selector id="end_point" accept_expressions="0" title="End point" tooltip="End point coordinates"
+                                 enable_value="enable_by_preferences"/>
+        <bspline-panel id="poles"
+                       weights="weights"
+                       title="Poles and weights"
+                       tooltip="B-spline poles and weights"
+                       enable_value="enable_by_preferences">
           <validator id="SketchPlugin_BSplineValidator"/>
-        </sketch-bspline_selector>
+        </bspline-panel>
         <boolvalue id="Auxiliary"
                    label="Auxiliary"
                    default="false"
                                  enable_value="enable_by_preferences">
           <validator id="SketchPlugin_BSplineValidator"/>
         </sketch-bspline_selector>
+        <boolvalue id="need_control_poly"
+                   label="Create control polygon"
+                   default="true"
+                   tooltip="Specify if the control polygon should be created"/>
         <boolvalue id="Auxiliary"
                    label="Auxiliary"
                    default="false"
index bce4d90d627523ce8debaf1e6a26df40cbd58d2a..24659d40681c0a562ca0c1616bfb3ed6898d1e47 100644 (file)
@@ -24,6 +24,7 @@
 #include <PlaneGCSSolver_ScalarWrapper.h>
 #include <PlaneGCSSolver_ScalarArrayWrapper.h>
 #include <PlaneGCSSolver_BooleanWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
 
 #include <GeomAPI_Pnt2d.h>
 #include <GeomDataAPI_Point2D.h>
@@ -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<ModelAPI_AttributeDoubleArray>(theAttribute);
-      myInteger = std::dynamic_pointer_cast<ModelAPI_AttributeIntArray>(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<PlaneGCSSolver_PointArrayWrapper> aWrapper =
+        std::dynamic_pointer_cast<PlaneGCSSolver_PointArrayWrapper>(theEntity);
+    std::shared_ptr<GeomDataAPI_Point2DArray> anAttribute =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
+
+    if (aWrapper->size() != anAttribute->size()) {
+      std::vector<PointWrapperPtr> 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<PointWrapperPtr>::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<PlaneGCSSolver_ScalarArrayWrapper> aWrapper =
+        std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(theEntity);
+    if (aWrapper->size() != PlaneGCSSolver_Tools::AttributeArray(theAttribute).size()) {
+      aParamsToRemove = PlaneGCSSolver_Tools::parameters(aWrapper);
+      std::shared_ptr<PlaneGCSSolver_ScalarArrayWrapper> aNewArray =
+          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarArrayWrapper>(
+          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);
+}
index 7d21983b30337becddb0b02252bacd8b35bce714..adc0e5720212174335716a65abd90254b7ff250e 100644 (file)
@@ -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(); }
index 225c4344f73e98ce386bafce57f52bed100774a6..be2e0bf81113065e1e394a0bb7f910db40fe7402 100644 (file)
 
 #include <PlaneGCSSolver_BooleanWrapper.h>
 
+#include <ModelAPI_AttributeBoolean.h>
+
 PlaneGCSSolver_BooleanWrapper::PlaneGCSSolver_BooleanWrapper(bool theParam)
   : myValue(theParam)
 {
 }
+
+bool PlaneGCSSolver_BooleanWrapper::update(AttributePtr theAttribute)
+{
+  bool isUpdated = false;
+  AttributeBooleanPtr aBoolean =
+      std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
+  if (aBoolean) {
+    isUpdated = value() != aBoolean->value();
+    setValue(aBoolean->value());
+  }
+  return isUpdated;
+}
index 3bd1d8d2ed7ed5455b909cbda6b7bee6e9692db2..667eb083dea0ae0385daa6272d71fbe12cf68a0a 100644 (file)
@@ -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<ModelAPI_Attribute> theAttribute);
+
 protected:
   bool myValue;
 };
index b99cc7c3b1bd00160a3d9cb2ea782555d15ca295..ab6ea78943dbf91d7076c0f795a2577e7744eef1 100644 (file)
@@ -23,6 +23,8 @@
 #include <PlaneGCSSolver_Defs.h>
 #include <PlaneGCSSolver_ScalarWrapper.h>
 
+#include <list>
+
 /**
  *  Wrapper providing operations with PlaneGCS constraints.
  */
index 5eceaf63c5c20f1d63906b4584d4ee401b24eabc..bc86246e588e66eb2e1137236427ac7648c670ee 100644 (file)
 
 #include <PlaneGCSSolver_Defs.h>
 
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_Feature.h>
-
-#include <list>
+#include <map>
 #include <memory>
 
+class ModelAPI_Attribute;
+
 class PlaneGCSSolver_EntityWrapper;
 typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
 
@@ -55,6 +54,14 @@ public:
   const std::map<std::string, EntityWrapperPtr>& 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<ModelAPI_Attribute> theAttribute)
+  { return false; }
+
+  friend class PlaneGCSSolver_AttributeBuilder;
+
 private:
   bool myExternal;
   std::map<std::string, EntityWrapperPtr> myAdditionalAttributes;
index de163985da3173df1ecbe8f7ffa8c9d69d9eab32..499dfe1af8467f27ac7da03c7ea4b27fc73872a9 100644 (file)
@@ -40,8 +40,6 @@
 #include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_XY.h>
 
-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();
-}
index 33a7954df83249bc9c9d5aa35925cb8c9f700231..a409fb448b77aff9b7480e44c026c03c9d9fe1c3 100644 (file)
 //
 
 #include <PlaneGCSSolver_PointArrayWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
+
+#include <GeomDataAPI_Point2DArray.h>
+
+#include <GeomAPI_Pnt2d.h>
 
 PlaneGCSSolver_PointArrayWrapper::PlaneGCSSolver_PointArrayWrapper(
     const std::vector<PointWrapperPtr>& thePoints)
   : myPoints(thePoints)
 {
 }
+
+bool PlaneGCSSolver_PointArrayWrapper::update(AttributePtr theAttribute)
+{
+  bool isUpdated = false;
+  std::shared_ptr<GeomDataAPI_Point2DArray> aPointArray =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2DArray>(theAttribute);
+  if (aPointArray && aPointArray->size() == (int)myPoints.size()) {
+    std::vector<PointWrapperPtr>::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;
+}
index 8752b79c9c575156dd7d394af999e50db07463fc..0524be273904dcb16faca532af82a46686603773 100644 (file)
@@ -38,10 +38,20 @@ public:
   /// \breif Size of array
   int size() const { return (int)myPoints.size(); }
 
+  /// \brief Return array of points
+  const std::vector<PointWrapperPtr>& array() const { return myPoints; }
+  /// \breif Set points
+  void setArray(const std::vector<PointWrapperPtr>& 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<ModelAPI_Attribute> theAttribute);
+
 private:
   std::vector<PointWrapperPtr> myPoints;
 };
index bfb662590ad96dd2bdfe647a1404b7518b5ff179..bda73b1977ef5ac62285794385701f4461ac83b6 100644 (file)
 //
 
 #include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
+
+#include <GeomDataAPI_Point2D.h>
 
 PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(const GCSPointPtr thePoint)
   : myPoint(thePoint)
 {
 }
+
+bool PlaneGCSSolver_PointWrapper::update(AttributePtr theAttribute)
+{
+  bool isUpdated = false;
+  std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
+  if (aPoint2D) {
+    isUpdated = PlaneGCSSolver_Tools::updateValue(aPoint2D->x(), *(myPoint->x)) || isUpdated;
+    isUpdated = PlaneGCSSolver_Tools::updateValue(aPoint2D->y(), *(myPoint->y)) || isUpdated;
+  }
+  return isUpdated;
+}
index 3cb05e124f04505181e834b2cbbf6fc29bd1716d..a50497523bc04a1f38aeff314fc0bfde437e4b08 100644 (file)
@@ -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<ModelAPI_Attribute> theAttribute);
+
 private:
   GCSPointPtr myPoint;
 };
index b599f8fbda2986e0f801e7ba8d0d9e4ee301bfc3..9d5615492060b0acc1c0afe3e4846dabfe146f9e 100644 (file)
 //
 
 #include <PlaneGCSSolver_ScalarArrayWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
 
 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;
+}
index 40746cfb4e5380624ab97e20768a608055588eb9..6b0992ec2f6870516e13cb0ab6fbec5d887aa5c9 100644 (file)
@@ -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<ModelAPI_Attribute> theAttribute);
+
 protected:
   GCS::VEC_pD myValue; ///< list of pointers to values provided by the storage
 };
index dc6d72ff391897d05cf5a1b7046995baf0cc2101..399b37531a88487e34ab413c6c40c13a80a23952 100644 (file)
 //
 
 #include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeInteger.h>
 
 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<ModelAPI_AttributeDouble>(theAttribute);
+  if (aDouble)
+    anAttrValue = aDouble->value();
+  else {
+    AttributeIntegerPtr anInt =
+        std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(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;
+}
index 454f5ea01159642431862ca71c6022d090ed7fa3..01238d579d2ed795920d6f5886de1f3a294fba85 100644 (file)
@@ -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<ModelAPI_Attribute> theAttribute);
+
 protected:
   double* myValue; ///< pointer to value provided by the storage
 };
index 328b7144c03e363e4a934e4e7af27d5bcfd70418..3c1e8fa4313d3212d029567458b5ac52b72defae 100644 (file)
@@ -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<GeomDataAPI_Point2D> aPoint2D =
-      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
-  if (aPoint2D) {
-    const GCSPointPtr& aGCSPoint =
-        std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity)->point();
-    isUpdated = updateValue(aPoint2D->x(), *(aGCSPoint->x)) || isUpdated;
-    isUpdated = updateValue(aPoint2D->y(), *(aGCSPoint->y)) || isUpdated;
-  } else {
-    AttributeDoublePtr aScalar =
-        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
-    if (aScalar) {
-      ScalarWrapperPtr aWrapper =
-          std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(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<ModelAPI_AttributeBoolean>(theAttribute);
-      if (aBoolean) {
-        BooleanWrapperPtr aWrapper =
-            std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(theEntity);
-        isUpdated = aWrapper->value() != aBoolean->value();
-        aWrapper->setValue(aBoolean->value());
-      }
-    }
-  }
-
-  return isUpdated;
-}
-
 static bool hasReference(std::shared_ptr<SketchPlugin_Feature> theFeature,
                          const std::string& theFeatureKind)
 {
@@ -207,9 +158,7 @@ bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
   std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
   std::list<AttributePtr>::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);
index 5fe371915581cac21ca251761c48e73475332353..5224c8443ef0e02f1922bb716bea77423e2f186e 100644 (file)
@@ -19,7 +19,9 @@
 
 #include <PlaneGCSSolver_Tools.h>
 #include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_PointArrayWrapper.h>
 #include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarArrayWrapper.h>
 #include <PlaneGCSSolver_ScalarWrapper.h>
 #include <PlaneGCSSolver_ConstraintWrapper.h>
 
@@ -39,6 +41,9 @@
 #include <SketchSolver_ConstraintMultiRotation.h>
 #include <SketchSolver_ConstraintMultiTranslation.h>
 
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_BSpline.h>
+#include <SketchPlugin_Circle.h>
 #include <SketchPlugin_ConstraintAngle.h>
 #include <SketchPlugin_ConstraintCoincidence.h>
 #include <SketchPlugin_ConstraintCollinear.h>
 #include <SketchPlugin_ConstraintRigid.h>
 #include <SketchPlugin_ConstraintPerpendicular.h>
 #include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
 #include <SketchPlugin_Line.h>
 #include <SketchPlugin_MultiRotation.h>
 #include <SketchPlugin_MultiTranslation.h>
+#include <SketchPlugin_Point.h>
 
 #include <GeomAPI_Circ2d.h>
 #include <GeomAPI_Dir2d.h>
@@ -62,6 +70,9 @@
 #include <GeomAPI_Lin2d.h>
 #include <GeomAPI_Pnt2d.h>
 
+#include <ModelAPI_AttributeDoubleArray.h>
+#include <ModelAPI_AttributeIntArray.h>
+
 #include <cmath>
 
 
@@ -129,7 +140,9 @@ static ConstraintWrapperPtr
                                      std::shared_ptr<PlaneGCSSolver_EdgeWrapper> 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<ModelAPI_AttributeDoubleArray>(theAttribute);
+  myInteger = std::dynamic_pointer_cast<ModelAPI_AttributeIntArray>(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<PlaneGCSSolver_ScalarArrayWrapper>(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<PlaneGCSSolver_PointArrayWrapper>(theArray);
+  for (std::vector<PointWrapperPtr>::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;
index d90fecbe0c67f320e9dbfd41c5e2481b15157519..b80f254f4adca180223f809877e70a138ad52609 100644 (file)
@@ -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<GeomAPI_Pnt2d> 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<ModelAPI_AttributeDoubleArray> myDouble;
+    std::shared_ptr<ModelAPI_AttributeIntArray> myInteger;
+  };
 };
 
 #endif
index a3e0bf2d004f512ec1a7ebf30f67fe1839ca04c9..0099869f50e86fd6cc92f88e407822eabf49d33e 100644 (file)
@@ -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 =