Salome HOME
Avoid crash while placing the presentation of constraint attached to the closed curve...
[modules/shaper.git] / src / ModelHighAPI / ModelHighAPI_Dumper.cpp
index 2bf026285374353fb6ff8f1db825b5ab710f2415..7956062dde22d6a48501f3f005e8fc43cb29412e 100644 (file)
 
 #include <Config_PropManager.h>
 
-#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
 #include <GeomAPI_Dir.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Pnt2d.h>
 #include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_Vertex.h>
 #include <GeomAlgoAPI_NExplode.h>
 
 #include <GeomDataAPI_Dir.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
+#include <GeomDataAPI_Point2DArray.h>
 
 #include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeDoubleArray.h>
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Entity.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_FiltersFeature.h>
 #include <ModelAPI_Folder.h>
 #include <ModelAPI_Result.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_ResultGroup.h>
 #include <ModelAPI_ResultPart.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
@@ -254,8 +263,7 @@ bool ModelHighAPI_Dumper::DumpStorage::exportTo(const std::string& theFilename,
   if (!aFile.is_open())
     return false;
 
-  // standard header (encoding + imported modules)
-  aFile << "# -*- coding: utf-8 -*-" << std::endl << std::endl;
+  // standard header imported modules
   for (ModulesSet::const_iterator aModIt = theUsedModules.begin();
     aModIt != theUsedModules.end(); ++aModIt) {
     aFile << "from " << *aModIt << " import *" << std::endl;
@@ -289,7 +297,8 @@ static void getShapeAndContext(const AttributeSelectionPtr& theAttrSelect,
     if (theAttrSelect->isGeometricalSelection() &&
         theShape.get() && theShape->shapeType() == GeomAPI_Shape::COMPOUND &&
         theContext.get() && !theShape->isEqual(theContext->shape()) &&
-        theContext->groupName() != ModelAPI_ResultPart::group()) {
+        theContext->groupName() != ModelAPI_ResultPart::group() &&
+        theContext->groupName() != ModelAPI_ResultGroup::group()) {
       GeomAPI_ShapeIterator anIt(theShape);
       theShape = anIt.current();
     }
@@ -365,8 +374,10 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
     std::list<ModelGeomAlgo_Shape::SubshapeOfResult> anApproproate;
     if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theShape->shapeType(),
                                                  anApproproate)) {
+      bool isContinue = true;
+      std::list<std::pair<GeomShapePtr, int> > aCenters;
       std::list<ModelGeomAlgo_Shape::SubshapeOfResult>::iterator anApIt = anApproproate.begin();
-      for (; anApIt != anApproproate.end(); ++anApIt) {
+      for (; anApIt != anApproproate.end() && isContinue; ++anApIt) {
         ++aNbPossibleSelections;
 
         // stop if the target shape and result are found
@@ -374,9 +385,42 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
         if (!aCurShape)
           aCurShape = anApIt->myResult->shape();
 
-        if (anApIt->myResult->isSame(theResult) && aCurShape->isSame(theShape))
-          break;
+        if (anApIt->myResult->isSame(theResult)) {
+          if (anApIt->myCenterType == (int)ModelAPI_AttributeSelection::NOT_CENTER)
+            isContinue = !aCurShape->isSame(theShape);
+          else if (theShape->isVertex() && aCurShape->isEdge()) {
+            GeomEdgePtr aCurEdge = aCurShape->edge();
+            GeomVertexPtr aVertex = theShape->vertex();
+            GeomPointPtr aCenter;
+            switch (anApIt->myCenterType) {
+            case (int)ModelAPI_AttributeSelection::CIRCLE_CENTER: {
+                GeomCirclePtr aCirc = aCurEdge->circle();
+                if (aCirc)
+                  aCenter = aCirc->center();
+                break;
+              }
+            case (int)ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS: {
+                GeomEllipsePtr anEllipse = aCurEdge->ellipse();
+                if (anEllipse)
+                  aCenter = anEllipse->firstFocus();
+                break;
+              }
+            case (int)ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS: {
+                GeomEllipsePtr anEllipse = aCurEdge->ellipse();
+                if (anEllipse)
+                  aCenter = anEllipse->secondFocus();
+                break;
+              }
+            }
+            if (aCenter && aCenter->distance(aVertex->point()) < 1.e-7)
+              aCenters.push_back(std::pair<GeomShapePtr, int>(aCurShape, aNbPossibleSelections));
+          }
+        }
       }
+      // passed till the appropriate shape, check the center of circle
+      // or a focus of ellipse is selected
+      if (isContinue && !aCenters.empty())
+        aNbPossibleSelections = aCenters.front().second;
     }
   }
   return aNbPossibleSelections;
@@ -442,7 +486,7 @@ void ModelHighAPI_Dumper::DumpStorageWeak::write(const AttributeSelectionPtr& th
     int anIndex = aNExplode.index(aShape);
     if (anIndex != 0) { // found a week-naming index, so, export it
       myDumpBuffer << "model.selection(\"" << aShape->shapeTypeStr() << "\", \""
-                   << theAttrSelect->contextName(aContext) << "\", " << anIndex;
+                   << theAttrSelect->contextName(aContext) << "\", " << anIndex << ")";
       aStandardDump = false;
     }
   }
@@ -643,7 +687,6 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theD
 
   // dump subfeatures and store result to file
   bool isOk = process(theDoc) && myDumpStorage->exportTo(theFileName, myModules);
-  clearCustomStorage();
   return isOk;
 }
 
@@ -661,8 +704,12 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theD
   // dump all other features
   for (anObjIt = anObjects.begin(); anObjIt != anObjects.end(); ++anObjIt) {
     CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anObjIt);
-    if (aCompFeat) // iteratively process composite features
-      isOk = process(aCompFeat) && isOk;
+    if (aCompFeat) {
+      // iteratively process composite features,
+      // if the composite feature is the last in the document, no need to dump "model.do()" action
+      std::list<ObjectPtr>::const_iterator aNext = anObjIt;
+      isOk = process(aCompFeat, false, ++aNext != anObjects.end()) && isOk;
+    }
     else if (!isDumped(EntityPtr(*anObjIt))) {
       // dump folder
       FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(*anObjIt);
@@ -681,7 +728,7 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theD
 }
 
 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite,
-                                  bool isForce)
+                                  bool isForce, bool isDumpModelDo)
 {
   // increase composite features stack
   ++gCompositeStackDepth;
@@ -714,7 +761,9 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeatur
     *this << aDocName << " = " << aPartName << ".document()" << std::endl;
     // dump features in the document
     bool aRes = process(aSubDoc);
-    *this << "model.do()" << std::endl;
+    if (isDumpModelDo)
+      *this << "model.do()\n";
+    *this << std::endl;
     return aRes;
   }
 
@@ -1074,6 +1123,43 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
+  const std::shared_ptr<GeomDataAPI_Point2DArray>& thePointArray)
+{
+  static const int aThreshold = 4;
+  static bool aDumpAsIs = false;
+  static std::string aSeparator = "";
+  // if number of elements in the list if greater than a threshold,
+  // dump it in a separate line with specific name
+  int aSize = thePointArray->size();
+  if (aDumpAsIs || aSize <= aThreshold) {
+    *myDumpStorage << "[";
+    GeomPnt2dPtr aPoint = thePointArray->pnt(0);
+    *myDumpStorage << "(" << aPoint->x() << ", " << aPoint->y() << ")";
+    for (int anIndex = 1; anIndex < aSize; ++anIndex) {
+      aPoint = thePointArray->pnt(anIndex);
+      *myDumpStorage << "," << aSeparator << " (" << aPoint->x() << ", " << aPoint->y() << ")";
+    }
+    *myDumpStorage << aSeparator << "]";
+  }
+  else {
+    // name of list
+    FeaturePtr anOwner = ModelAPI_Feature::feature(thePointArray->owner());
+    std::string aListName = name(anOwner) + "_" + thePointArray->id();
+    // reserve dumped buffer and store list "as is"
+    myDumpStorage->reserveBuffer();
+    aDumpAsIs = true;
+    aSeparator = std::string("\n") + std::string(aListName.size() + 3, ' ');
+    *this << aListName << " = " << thePointArray << "\n";
+    aDumpAsIs = false;
+    aSeparator = "";
+    // append reserved data to the end of the current buffer
+    myDumpStorage->restoreReservedBuffer();
+    *myDumpStorage << aListName;
+  }
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeBoolean>& theAttrBool)
 {
@@ -1092,6 +1178,20 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
+    const std::shared_ptr<ModelAPI_AttributeIntArray>& theArray)
+{
+  *myDumpStorage << "[";
+  int aSize = theArray->size();
+  if (aSize > 0) {
+    *myDumpStorage << theArray->value(0);
+    for (int anIndex = 1; anIndex < aSize; ++anIndex)
+      *myDumpStorage << ", " << theArray->value(anIndex);
+  }
+  *myDumpStorage << "]";
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeDouble>& theAttrReal)
 {
@@ -1103,6 +1203,20 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
+  const std::shared_ptr<ModelAPI_AttributeDoubleArray>& theArray)
+{
+  *myDumpStorage << "[";
+  int aSize = theArray->size();
+  if (aSize > 0) {
+    *myDumpStorage << theArray->value(0);
+    for (int anIndex = 1; anIndex < aSize; ++anIndex)
+      *myDumpStorage << ", " << theArray->value(anIndex);
+  }
+  *myDumpStorage << "]";
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeString>& theAttrStr)
 {
@@ -1187,6 +1301,19 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ResultPtr& theResult)
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::list<ResultPtr>& theResults)
+{
+  *this << "[";
+  for (std::list<ResultPtr>::const_iterator anIt = theResults.begin();
+       anIt != theResults.end(); ++anIt) {
+    if (anIt != theResults.begin())
+      *this << ", ";
+    *this << *anIt;
+  }
+  *this << "]";
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ObjectPtr& theObject)
 {
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
@@ -1212,7 +1339,8 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const AttributePtr& theAttr
   // Check the attribute belongs to copied (in multi-translation or multi-rotation) feature.
   // In this case we need to cast explicitly feature to appropriate type.
   AttributeBooleanPtr isCopy = anOwner->boolean("Copy");
-  if (isCopy.get() && isCopy->value()) {
+  AttributeReferencePtr hasParent = anOwner->reference("ParentFeature");
+  if ((isCopy.get() && isCopy->value()) || (hasParent && hasParent->value())) {
     aWrapperPrefix = featureWrapper(anOwner) + "(";
     aWrapperSuffix = ")";
     importModule("SketchAPI");
@@ -1341,6 +1469,14 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
       *this << anAttribute;
     }
 
+    // check selection list is obtained by filters
+    FiltersFeaturePtr aFilters = theAttrSelList->filters();
+    if (aFilters) {
+      if (theAttrSelList->size() > 0)
+        *myDumpStorage << ", ";
+      dumpFeature(aFilters, true);
+    }
+
     *myDumpStorage << "]";
   } else {
     // obtain name of list (the feature may contain several selection lists)
@@ -1453,3 +1589,24 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
 
   return theDumper;
 }
+
+
+void ModelHighAPI_Dumper::exportVariables() const
+{
+  DocumentPtr aRoot = ModelAPI_Session::get()->moduleDocument();
+  EntityNameMap::const_iterator aNameIter = myNames.cbegin();
+  for(; aNameIter != myNames.end(); aNameIter++) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aNameIter->first);
+    if (aFeature.get() && aFeature->document() != aRoot) {
+      FeaturePtr aPartFeat = ModelAPI_Tools::findPartFeature(aRoot, aFeature->document());
+      if (aPartFeat.get()) {
+        int aFeatureId = aFeature->data()->featureId();
+        int aPartId = aPartFeat->data()->featureId();
+        std::ostringstream anEntryStr;
+        anEntryStr<<aPartId<<":"<<aFeatureId;
+        std::string anEntry = anEntryStr.str();
+        exportVariable(anEntry, aNameIter->second.myCurrentName);
+      }
+    }
+  }
+}