]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Implementation of interpolation analytical (Work in progress)
authorJérôme <jerome.lucas@cesgenslab.fr>
Tue, 6 Oct 2020 07:33:14 +0000 (09:33 +0200)
committerJérôme <jerome.lucas@cesgenslab.fr>
Thu, 3 Dec 2020 13:49:55 +0000 (14:49 +0100)
src/BuildPlugin/BuildPlugin_Interpolation.cpp
src/BuildPlugin/BuildPlugin_Interpolation.h
src/BuildPlugin/BuildPlugin_Plugin.cpp
src/BuildPlugin/BuildPlugin_Validators.cpp
src/BuildPlugin/BuildPlugin_Validators.h
src/BuildPlugin/CMakeLists.txt
src/BuildPlugin/interpolation_widget.xml

index b8422517b0cedbddfdcad816322e34d5ffc015fc..c2d1d3f9772a9f68df1d5277f09931eebdb9dc45 100644 (file)
 
 #include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_ResultParameter.h>
 
 #include <Events_InfoMessage.h>
 
+#include <Locale_Convert.h>
+
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <GeomAlgoAPI_CurveBuilder.h>
 #include <GeomAlgoAPI_PointBuilder.h>
 #include <GeomAPI_Edge.h>
 #include <GeomAPI_Lin.h>
 #include <GeomAPI_ShapeExplorer.h>
+#include <ModelAPI_Tools.h>
 
 #include <algorithm>
 
+#include <iostream>
+
 //=================================================================================================
 BuildPlugin_Interpolation::BuildPlugin_Interpolation()
 {
@@ -51,6 +63,30 @@ void BuildPlugin_Interpolation::initAttributes()
   data()->addAttribute(USE_TANGENTS_ID(), ModelAPI_AttributeString::typeId());
   data()->addAttribute(TANGENT_START_ID(), ModelAPI_AttributeSelection::typeId());
   data()->addAttribute(TANGENT_END_ID(), ModelAPI_AttributeSelection::typeId());
+
+  data()->addAttribute(CREATION_METHODE_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(CREATION_METHODE_BY_SELECTION_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(CREATION_METHODE_ANALYTICAL_ID(), ModelAPI_AttributeString::typeId());
+
+  data()->addAttribute(EXPRESSION_ERROR_ID(), ModelAPI_AttributeString::typeId());
+  data()->string(EXPRESSION_ERROR_ID())->setIsArgument(false);
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXPRESSION_ERROR_ID());
+
+    data()->addAttribute(XT_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(YT_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ZT_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(MINT_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(MAXT_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(NUMSTEP_ID(), ModelAPI_AttributeInteger::typeId());
+  
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHODE_ANALYTICAL_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CREATION_METHODE_BY_SELECTION_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), YT_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ZT_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINT_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAXT_ID());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), NUMSTEP_ID()); 
+
 }
 
 //=================================================================================================
@@ -78,62 +114,177 @@ static GeomDirPtr selectionToDir(const AttributeSelectionPtr& theSelection)
 //=================================================================================================
 void BuildPlugin_Interpolation::execute()
 {
-  // Get closed flag value
-  bool isClosed = boolean(CLOSED_ID())->value();
+  if( string(CREATION_METHODE_ID())->value() == CREATION_METHODE_BY_SELECTION_ID() )
+  {
+    // Get closed flag value
+    bool isClosed = boolean(CLOSED_ID())->value();
 
-  // Get reorder flag value
-  bool isToReorder = boolean(REORDER_ID())->value();
+    // Get reorder flag value
+    bool isToReorder = boolean(REORDER_ID())->value();
 
-  // Get use tangents flag value
-  bool isToUseTangents = isClosed? false : (!string(USE_TANGENTS_ID())->value().empty());
+    // Get use tangents flag value
+    bool isToUseTangents = isClosed? false : (!string(USE_TANGENTS_ID())->value().empty());
 
-  // Get tangent for start and end points
-  GeomDirPtr aDirStart, aDirEnd;
-  if (isToUseTangents) {
-    aDirStart = selectionToDir(selection(TANGENT_START_ID()));
-    aDirEnd = selectionToDir(selection(TANGENT_END_ID()));
-  }
+    // Get tangent for start and end points
+    GeomDirPtr aDirStart, aDirEnd;
+    if (isToUseTangents) {
+      aDirStart = selectionToDir(selection(TANGENT_START_ID()));
+      aDirEnd = selectionToDir(selection(TANGENT_END_ID()));
+    }
 
-  // Get base objects list.
-  AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
-
-  // Collect points.
-  std::list<GeomPointPtr> aPoints;
-  std::set<GeomShapePtr> aContexts;
-  for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
-    AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
-
-    GeomShapePtr aContextShape = aSelection->context()->shape();
-    aContexts.insert(aContextShape);
-
-               GeomShapePtr aShape = aSelection->value();
-    if (!aShape.get()) {
-      aShape = aContextShape;
-               }
-
-    GeomPointPtr aPoint = GeomAlgoAPI_PointBuilder::point(aShape);
-    aPoints.push_back(aPoint);
-       }
-
-  // Create curve from points
-  GeomEdgePtr anEdge =
-    GeomAlgoAPI_CurveBuilder::edge(aPoints, isClosed, isToReorder, aDirStart, aDirEnd);
-  if (!anEdge.get()) {
-    setError("Error: Result curve is empty.");
-    return;
-  }
+    // Get base objects list.
+    AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+
+    // Collect points.
+    std::list<GeomPointPtr> aPoints;
+    std::set<GeomShapePtr> aContexts;
+    for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+      AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+
+      GeomShapePtr aContextShape = aSelection->context()->shape();
+      aContexts.insert(aContextShape);
+
+      GeomShapePtr aShape = aSelection->value();
+      if (!aShape.get()) {
+        aShape = aContextShape;
+      }
 
-  // Store result.
-  ResultBodyPtr aResultBody = document()->createBody(data());
-  std::set<GeomShapePtr>::const_iterator aContextIt = aContexts.begin();
-  for (; aContextIt != aContexts.end(); aContextIt++) {
-    aResultBody->storeModified(*aContextIt, anEdge, aContextIt == aContexts.begin());
+      GeomPointPtr aPoint = GeomAlgoAPI_PointBuilder::point(aShape);
+      aPoints.push_back(aPoint);
+    }
+
+    // Create curve from points
+    GeomEdgePtr anEdge =
+      GeomAlgoAPI_CurveBuilder::edge(aPoints, isClosed, isToReorder, aDirStart, aDirEnd);
+    if (!anEdge.get()) {
+      setError("Error: Result curve is empty.");
+      return;
+    }
+
+    // Store result.
+    ResultBodyPtr aResultBody = document()->createBody(data());
+    std::set<GeomShapePtr>::const_iterator aContextIt = aContexts.begin();
+    for (; aContextIt != aContexts.end(); aContextIt++) {
+      aResultBody->storeModified(*aContextIt, anEdge, aContextIt == aContexts.begin());
+    }
+    int aVertexIndex = 1;
+    for (GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+      std::string aVertexName = "Vertex_" + std::to_string((long long)aVertexIndex);
+      aResultBody->generated(anExp.current(), aVertexName);
+    }
+
+    setResult(aResultBody);
+  }else
+  {
+      string(EXPRESSION_ERROR_ID())->setValue("rien");
+      string(EXPRESSION_ID())->setValue(string( XT_ID())->value());
+      string(VARIABLE_ID())->setValue("t");
+      updateName();
+      double res;
+      if (!updateExpression(res))
+        setError("Expression error.", false);
+      std::cout << "res = " << res << std::endl;
   }
-  int aVertexIndex = 1;
-  for (GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
-    std::string aVertexName = "Vertex_" + std::to_string((long long)aVertexIndex);
-    aResultBody->generated(anExp.current(), aVertexName);
+
+}
+
+double BuildPlugin_Interpolation::evaluate(const std::wstring& /*theExpression*/,
+                                            std::string& theError)
+{
+  FeaturePtr aMyPtr = std::dynamic_pointer_cast<ModelAPI_Feature>(data()->owner());
+  std::shared_ptr<ModelAPI_ParameterEvalMessage> aProcessMessage =
+    ModelAPI_ParameterEvalMessage::send(aMyPtr, this);
+
+  double aResult = 0;
+  if (aProcessMessage->isProcessed()) {
+    const std::list<ResultParameterPtr>& aParamsList = aProcessMessage->params();
+    aResult = aProcessMessage->result();
+    theError = aProcessMessage->error();
+    /* compare the list of parameters to store if changed
+    AttributeRefListPtr aParams = reflist(ARGUMENTS_ID());
+    bool aDifferent = aParams->size() != (int)aParamsList.size();
+    if (!aDifferent) {
+      std::list<ResultParameterPtr>::const_iterator aNewIter = aParamsList.begin();
+      std::list<ObjectPtr> anOldList = aParams->list();
+      std::list<ObjectPtr>::const_iterator anOldIter = anOldList.begin();
+      for(; !aDifferent && aNewIter != aParamsList.end(); aNewIter++, anOldIter++) {
+        if (*aNewIter != *anOldIter)
+          aDifferent = true;
+      }
+    }
+    if (aDifferent) {
+      aParams->clear();
+      std::list<ResultParameterPtr>::const_iterator aNewIter = aParamsList.begin();
+      for(; aNewIter != aParamsList.end(); aNewIter++) {
+        aParams->append(*aNewIter);
+      }
+    }*/
+  } else { // error: python interpreter is not active
+    theError = "Python interpreter is not available";
   }
+  return aResult;
+}
+
+
+bool BuildPlugin_Interpolation::updateExpression(double& aValue)
+{
+  std::wstring anExpression = string(EXPRESSION_ID())->isUValue() ?
+      Locale::Convert::toWString(string(EXPRESSION_ID())->valueU()) :
+      Locale::Convert::toWString(string(EXPRESSION_ID())->value());
 
-  setResult(aResultBody);
+  std::string outErrorMessage;
+  aValue = evaluate(anExpression, outErrorMessage);
+
+  data()->string(EXPRESSION_ERROR_ID())->setValue(outErrorMessage);
+  if (!outErrorMessage.empty())
+    return false;
+
+  /*ResultParameterPtr aParam = document()->createParameter(data());
+  AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+  aValueAttribute->setValue(aValue);
+  setResult(aParam);*/
+  
+  return true;
 }
+
+void BuildPlugin_Interpolation::updateName()
+{
+  std::wstring aName = string(VARIABLE_ID())->isUValue() ?
+      Locale::Convert::toWString(string(VARIABLE_ID())->valueU()) :
+      Locale::Convert::toWString(string(VARIABLE_ID())->value());
+  data()->setName(aName);
+
+  ResultParameterPtr aParam = document()->createParameter(data());
+  std::wstring anOldName = aParam->data()->name();
+  aParam->data()->setName(aName);
+  setResult(aParam);
+
+
+  // #2474 : if parameter name now hides/shows the higher level parameter name,
+  // update the depended expressions
+  DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+  if (aParam->document() != aRootDoc) {
+    std::list<std::wstring> aNames; // collect names in the root document that must be checked
+    aNames.push_back(aName);
+    if (anOldName != aName) {
+      aNames.push_back(anOldName);
+    }
+    std::list<std::wstring>::iterator aNIter = aNames.begin();
+    for (; aNIter != aNames.end(); aNIter++) {
+      double aValue;
+      ResultParameterPtr aRootParam;
+      FeaturePtr aThis =
+        std::dynamic_pointer_cast<ModelAPI_Feature>(string(VARIABLE_ID())->owner());
+      if (ModelAPI_Tools::findVariable(aThis, *aNIter, aValue, aRootParam, aRootDoc)) {
+        std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes =
+          aRootParam->data()->refsToMe();
+        std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator anAttributeIt =
+          anAttributes.cbegin();
+        for (; anAttributeIt != anAttributes.cend(); ++anAttributeIt) {
+          const AttributePtr& anAttribute = *anAttributeIt;
+          ModelAPI_AttributeEvalMessage::send(anAttribute, NULL);
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
index 912cc126ff14ef4c90ee1a96e2fd38aa0a54db5d..fac6d69463df6a043c498e84ef149934743c2a25 100644 (file)
@@ -39,6 +39,25 @@ public:
     static const std::string MY_ID("Interpolation");
     return MY_ID;
   }
+  /// Attribute name of creation method.
+  inline static const std::string& CREATION_METHODE_ID()
+  {
+    static const std::string MY_CREATION_METHODE_ID("interpolation_method");
+    return MY_CREATION_METHODE_ID;
+  }
+  /// Attribute name of creation method by selection
+  inline static const std::string& CREATION_METHODE_BY_SELECTION_ID()
+  {
+    static const std::string MY_CREATION_METHODE_BY_SELECTION_ID("by_selection");
+    return MY_CREATION_METHODE_BY_SELECTION_ID;
+  }
+
+  /// Attribute name of creation method analytical
+  inline static const std::string& CREATION_METHODE_ANALYTICAL_ID()
+  {
+    static const std::string MY_CREATION_METHODE_ANALYTICAL_ID("analytical");
+    return MY_CREATION_METHODE_ANALYTICAL_ID;
+  }
 
   /// Attribute name of base objects.
   inline static const std::string& BASE_OBJECTS_ID()
@@ -81,6 +100,68 @@ public:
     static const std::string MY_TANGENT_END_ID("tangent_end");
     return MY_TANGENT_END_ID;
   }
+  /// Attribute name of x(t) equation.
+  inline static const std::string& XT_ID()
+  {
+    static const std::string MY_XT_ID("xt");
+    return MY_XT_ID;
+  }
+
+  /// Attribute name of y(t) equation.
+  inline static const std::string& YT_ID()
+  {
+    static const std::string MY_YT_ID("yt");
+    return MY_YT_ID;
+  }
+
+  /// Attribute name of z(t) equation.
+  inline static const std::string& ZT_ID()
+  {
+    static const std::string MY_ZT_ID("zt");
+    return MY_ZT_ID;
+  }
+
+  /// Attribute name of min t.
+  inline static const std::string& MINT_ID()
+  {
+    static const std::string MY_MINT_ID("mint");
+    return MY_MINT_ID;
+  }
+
+  /// Attribute name of max t.
+  inline static const std::string& MAXT_ID()
+  {
+    static const std::string MY_MAXT_ID("maxt");
+    return MY_MAXT_ID;
+  }
+
+  /// attribute of parameter name
+  inline static const std::string& VARIABLE_ID()
+  {
+    static const std::string MY_VARIABLE_ID("variable");
+    return MY_VARIABLE_ID;
+  }
+
+  /// attribute of parameter expression
+  inline static const std::string& EXPRESSION_ID()
+  {
+    static const std::string MY_EXPRESSION_ID("expression");
+    return MY_EXPRESSION_ID;
+  }
+
+  /// attribute of parameter expression error
+  inline static const std::string& EXPRESSION_ERROR_ID()
+  {
+    static const std::string MY_EXPRESSION_ERROR_ID("ExpressionError");
+    return MY_EXPRESSION_ERROR_ID;
+  }
+
+  /// Attribute name of max t.
+  inline static const std::string& NUMSTEP_ID()
+  {
+    static const std::string MY_NUMSTEP_ID("numstep");
+    return MY_NUMSTEP_ID;
+  }
 
   /// Default value of the closed attribute
   inline static bool CLOSED_DEFAULT() { return false; }
@@ -97,6 +178,14 @@ public:
 
   /// Creates a new part document if needed.
   BUILDPLUGIN_EXPORT virtual void execute();
+
+  protected:
+  /// Evaluates theExpression and returns its value.
+  double evaluate(const std::wstring& theExpression, std::string& theError);
+
+  bool updateExpression(double& aValue);
+  void updateName();
+
 };
 
 #endif
index e18d092cfea452708bc289417e237747a1fdb062..54ac6c7d0e5acde742d0fabcc346c63af0edfaa7 100644 (file)
@@ -59,6 +59,9 @@ BuildPlugin_Plugin::BuildPlugin_Plugin()
                               new BuildPlugin_ValidatorFillingSelection());
   aFactory->registerValidator("BuildPlugin_ValidatorBaseForVertex",
                               new BuildPlugin_ValidatorBaseForVertex());
+  aFactory->registerValidator("BuildPlugin_ValidatorExpressionInterpolation",
+                              new BuildPlugin_ValidatorExpressionInterpolation());
+  
 
   // Register this plugin.
   ModelAPI_Session::get()->registerPlugin(this);
index ac454e620fd03348cf9162e682171fb8320e2fda..be26b119646cedc161b890f9dd7c17fdaa66a7fd 100644 (file)
@@ -20,6 +20,7 @@
 #include "BuildPlugin_Validators.h"
 
 #include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultConstruction.h>
 
 #include <GeomAPI_PlanarEdges.h>
@@ -39,6 +40,8 @@
 #include <GeomValidators_FeatureKind.h>
 #include <GeomValidators_ShapeType.h>
 
+#include <BuildPlugin_Interpolation.h>
+
 #include <SketchPlugin_Sketch.h>
 
 #include <Events_InfoMessage.h>
@@ -569,3 +572,28 @@ bool BuildPlugin_ValidatorBaseForVertex::isValid(const AttributePtr& theAttribut
 
   return true;
 }
+
+
+bool BuildPlugin_ValidatorExpressionInterpolation::isValid(const AttributePtr& theAttribute,
+                                                   const std::list<std::string>& /*theArguments*/,
+                                                   Events_InfoMessage& theError) const
+{
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+
+  AttributeStringPtr aStrAttr =
+      std::dynamic_pointer_cast<ModelAPI_AttributeString>(theAttribute);
+  if (!aStrAttr->isInitialized()) {
+    theError = "Attribute \"%1\" is not initialized.";
+    theError.arg(aStrAttr->id());
+    return false;
+  }
+  bool isEmptyExpr = aStrAttr->value().empty();
+  if (isEmptyExpr) {
+    theError = "Expression is empty.";
+    return false;
+  }
+
+  theError = aFeature->string(BuildPlugin_Interpolation::EXPRESSION_ERROR_ID())->value();
+  return theError.empty();
+}
+
index 9d4670ef041019657e8be6178d521ad7bff71813..ffb8b0fbb7bbc37427726f7e1704e4b76ddbdd95 100644 (file)
@@ -133,4 +133,26 @@ public:
                         Events_InfoMessage& theError) const;
 };
 
+/**
+ * \class BuildPlugin_ValidatorExpression
+ * \ingroup Validators
+ * \brief Validator for the expression of parameter.
+ */
+class BuildPlugin_ValidatorExpressionInterpolation
+: public ModelAPI_AttributeValidator
+{
+ public:
+
+  /**
+   * \brief Returns true if attribute has a valid parameter expression.
+   * \param theAttribute the checked attribute
+   * \param theArguments arguments of the attribute
+   * \param theError the error string message if validation fails
+   */
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
+
 #endif
index ca262f1fb0da664c5f8033404c17d2096c71e09b..e13730bea5594dec5310d0da0d812d1aa34baff8 100644 (file)
@@ -23,6 +23,7 @@ INCLUDE(UnitTest)
 INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
                     ${PROJECT_SOURCE_DIR}/src/Config
                     ${PROJECT_SOURCE_DIR}/src/ModelAPI
+                    ${PROJECT_SOURCE_DIR}/src/Locale
                     ${PROJECT_SOURCE_DIR}/src/GeomAPI
                     ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
                     ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
index 5a0acee2fed3d086753912d7314983c60f264d3d..10efe19e76510b9f2aaf0abbc83e54b8fe0aca6b 100644 (file)
@@ -1,32 +1,70 @@
 <source>
-  <multi_selector id="base_objects"
-                  label="Points and vertices:"
-                  tooltip="Select points or vertices objects."
-                  shape_types="vertices"
-                  concealment="true">
-    <validator id="GeomValidators_DifferentShapes"/>
-  </multi_selector>
-  <boolvalue id="reorder" label="Reorder" tooltip="Changes the order of points to construct the shortest curve." default="false"/>
-  <optionalbox id="closed" title="Closed" tooltip="Makes the curve closed or not." default="false"
-               has_frame="false" enable_on_check="false">
-    <optionalbox id="use_tangents" title="Tangents" default="false">
-      <shape_selector id="tangent_start"
-                      icon="icons/Features/axis.png"
-                      label="Start"
-                      tooltip="Select vector tangent to the start of curve"
-                      shape_types="edge"
-                      default="&lt;start&gt;">
-        <validator id="GeomValidators_ShapeType" parameters="empty,line"/>
-      </shape_selector>
-      <shape_selector id="tangent_end"
-                      icon="icons/Features/axis.png"
-                      label="End"
-                      tooltip="Select vector tangent to the end of curve"
-                      shape_types="edge"
-                      default="&lt;end&gt;">
-        <validator id="GeomValidators_ShapeType" parameters="empty,line"/>
-      </shape_selector>
-    </optionalbox>
-  </optionalbox>
-  <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
+  <toolbox id="interpolation_method">
+    <box id="by_selection" 
+         icon="icons/BuildPlugin/edge_by_points_32x32.png">
+      <multi_selector id="base_objects"
+                      label="Points and vertices:"
+                      tooltip="Select points or vertices objects."
+                      shape_types="vertices"
+                      concealment="true">
+        <validator id="GeomValidators_DifferentShapes"/>
+      </multi_selector>
+      <boolvalue id="reorder" label="Reorder" tooltip="Changes the order of points to construct the shortest curve." default="false"/>
+      <optionalbox id="closed" title="Closed" tooltip="Makes the curve closed or not." default="false"
+                  has_frame="false" enable_on_check="false">
+        <optionalbox id="use_tangents" title="Tangents" default="false">
+          <shape_selector id="tangent_start"
+                          icon="icons/Features/axis.png"
+                          label="Start"
+                          tooltip="Select vector tangent to the start of curve"
+                          shape_types="edge"
+                          default="&lt;start&gt;">
+            <validator id="GeomValidators_ShapeType" parameters="empty,line"/>
+          </shape_selector>
+          <shape_selector id="tangent_end"
+                          icon="icons/Features/axis.png"
+                          label="End"
+                          tooltip="Select vector tangent to the end of curve"
+                          shape_types="edge"
+                          default="&lt;end&gt;">
+            <validator id="GeomValidators_ShapeType" parameters="empty,line"/>
+          </shape_selector>
+        </optionalbox>
+      </optionalbox>
+      <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
+    </box>
+    <box id="analytical"
+         title="Curve parameters"
+         tooltip="???"
+         icon="icons/BuildPlugin/feature_edge.png">
+      <stringvalue id="xt" label="X(t) equation" >
+          <validator id="BuildPlugin_ValidatorExpressionInterpolation"/>
+        </stringvalue>
+      <stringvalue id="yt" label="Y(t) equation" >
+        <validator id="BuildPlugin_ValidatorExpressionInterpolation"/>
+      </stringvalue>
+      <stringvalue id="zt" label="Z(t) equation" >
+        <validator id="BuildPlugin_ValidatorExpressionInterpolation"/>
+      </stringvalue>
+      <doublevalue id="mint"
+                   label="Min t"
+                   min="0"
+                   default="0">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+       <doublevalue id="maxt"
+                   label="Max t"
+                   min="0"
+                   default="100">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+       <integervalue id="numstep"
+                   label="Number of steps"
+                   tooltip="Fillet radius."
+                   min="0"
+                   default="10">
+        <validator id="GeomValidators_Positive"/>
+      </integervalue>
+    </box>
+  </toolbox>
 </source>