Salome HOME
Task #3230: Sketcher: create a curve passing through selected points or vertices...
[modules/shaper.git] / src / ModelHighAPI / ModelHighAPI_Dumper.cpp
index 778b1c94c7c4573a139af74896bc2a929ea577f8..1031cf85498a1868ece8135255c77fa4a94591e7 100644 (file)
 
 #include <Config_PropManager.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_Dir.h>
 #include <GeomAPI_ShapeExplorer.h>
 #include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_Vertex.h>
 #include <GeomAlgoAPI_NExplode.h>
 
 #include <GeomDataAPI_Dir.h>
@@ -311,7 +315,7 @@ void ModelHighAPI_Dumper::DumpStorage::write(const AttributeSelectionPtr& theAtt
 
   if (aShape.get()) {
     myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \""
-                 << theAttrSelect->namingName() << "\"";
+                 << ModelAPI_Tools::toString(theAttrSelect->namingName()) << "\"";
   }
 
   myDumpBuffer << ")";
@@ -328,8 +332,18 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
 
   std::list<FeaturePtr> aFeatures = aDoc1->allFeatures();
   if (aDoc1 != aDoc2) {
+    // Find the position of the part, where its features should be inserted.
+    // It will avoid checking of appropriate elements in partSet after the current part.
+    std::list<FeaturePtr>::iterator aFIt = aFeatures.begin();
+    for (; aFIt != aFeatures.end(); ++aFIt) {
+      ResultPartPtr aPartRes =
+          std::dynamic_pointer_cast<ModelAPI_ResultPart>((*aFIt)->lastResult());
+      if (aPartRes && aPartRes->partDoc() == aDoc2)
+        break;
+    }
+
     std::list<FeaturePtr> anAdditionalFeatures = aDoc2->allFeatures();
-    aFeatures.insert(aFeatures.end(), anAdditionalFeatures.begin(), anAdditionalFeatures.end());
+    aFeatures.insert(aFIt, anAdditionalFeatures.begin(), anAdditionalFeatures.end());
   }
 
   CompositeFeaturePtr aLastCompositeFeature;
@@ -370,8 +384,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
@@ -379,9 +395,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;
@@ -447,7 +496,8 @@ 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 << ")";
+                   << ModelAPI_Tools::toString(theAttrSelect->contextName(aContext))
+                   << "\", " << anIndex << ")";
       aStandardDump = false;
     }
   }
@@ -520,25 +570,30 @@ static int toInt(const std::string& theString)
 
 const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
                                              bool theSaveNotDumped,
-                                             bool theUseEntityName)
-{
-  EntityNameMap::const_iterator aFound = myNames.find(theEntity);
-  if (aFound != myNames.end())
+                                             bool theUseEntityName,
+                                             bool theSetIsDumped)
+{
+  EntityNameMap::iterator aFound = myNames.find(theEntity);
+  if (aFound != myNames.end()) {
+    // Set dumped flag for postponed constraints which are without names
+    if (!aFound->second.myIsDumped)
+      aFound->second.myIsDumped = theSetIsDumped;
     return aFound->second.myCurrentName;
-
+  }
   // entity is not found, store it
-  std::string aName, aKind;
+  std::string aName;
+  std::string aKind;
   bool isDefaultName = false;
   bool isSaveNotDumped = theSaveNotDumped;
   std::ostringstream aDefaultName;
   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
   if (aFeature) {
-    aName = aFeature->name();
+    aName = ModelAPI_Tools::toString(aFeature->name());
     aKind = aFeature->getKind();
   } else {
     FolderPtr aFolder = std::dynamic_pointer_cast<ModelAPI_Folder>(theEntity);
     if (aFolder) {
-      aName = aFolder->data()->name();
+      aName = ModelAPI_Tools::toString(aFolder->data()->name());
       aKind = ModelAPI_Folder::ID();
       isSaveNotDumped = false;
     }
@@ -601,6 +656,8 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
   if (aFeature)
     saveResultNames(aFeature);
 
+  myNames[theEntity].myIsDumped = theSetIsDumped;
+
   return myNames[theEntity].myCurrentName;
 }
 
@@ -629,9 +686,9 @@ void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
   std::list<ResultPtr> allRes;
   ModelAPI_Tools::allResults(theFeature, allRes);
   for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
-    std::pair<std::string, bool> aName = ModelAPI_Tools::getDefaultName(*aRes);
-    std::string aDefaultName = aName.first;
-    std::string aResName = (*aRes)->data()->name();
+    std::pair<std::wstring, bool> aName = ModelAPI_Tools::getDefaultName(*aRes);
+    std::string aDefaultName = ModelAPI_Tools::toString(aName.first);
+    std::string aResName = ModelAPI_Tools::toString((*aRes)->data()->name());
     bool isUserDefined = !(isFeatureDefaultName && aDefaultName == aResName);
     myNames[*aRes] =
       EntityName(aResName, (isUserDefined ? aResName : std::string()), !isUserDefined);
@@ -723,7 +780,7 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeatur
     // dump features in the document
     bool aRes = process(aSubDoc);
     if (isDumpModelDo)
-      *this << "model.do()\n";
+      *this << "\nmodel.do()\n";
     *this << std::endl;
     return aRes;
   }
@@ -815,14 +872,15 @@ void ModelHighAPI_Dumper::dumpSubFeatureNameAndColor(const std::string theSubFea
                                                      const FeaturePtr& theSubFeature)
 {
   name(theSubFeature, false);
-  myNames[theSubFeature] = EntityName(theSubFeatureGet, theSubFeature->name(), false);
+  myNames[theSubFeature] =
+    EntityName(theSubFeatureGet, ModelAPI_Tools::toString(theSubFeature->name()), false);
 
   // store results if they have user-defined names or colors
   std::list<ResultPtr> aResultsWithNameOrColor;
   const std::list<ResultPtr>& aResults = theSubFeature->results();
   std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
   for (; aResIt != aResults.end(); ++aResIt) {
-    std::string aResName = (*aResIt)->data()->name();
+    std::string aResName = ModelAPI_Tools::toString((*aResIt)->data()->name());
     myNames[*aResIt] = EntityName(aResName, aResName, false);
     aResultsWithNameOrColor.push_back(*aResIt);
   }
@@ -1005,6 +1063,16 @@ bool ModelHighAPI_Dumper::isDefaultTransparency(const ResultPtr& theResult) cons
   return fabs(anAttribute->value()) < 1.e-12;
 }
 
+bool ModelHighAPI_Dumper::dumpCommentBeforeFeature(const FeaturePtr& theFeature) const
+{
+  // currently, the comment should not be dumped only before the filters
+  FiltersFeaturePtr aFilters = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(theFeature);
+  if (aFilters)
+    return false;
+  // all other features should be commented before the dump
+  return true;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar)
 {
   *myDumpStorage << theChar;
@@ -1023,6 +1091,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::string& theStrin
   return *this;
 }
 
+ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::wstring& theString)
+{
+  *myDumpStorage << ModelAPI_Tools::toString(theString);
+  return *this;
+}
+
 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const bool theValue)
 {
   *myDumpStorage << (theValue ? "True" : "False");
@@ -1398,10 +1472,10 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     const std::shared_ptr<ModelAPI_AttributeSelectionList>& theAttrSelList)
 {
   static const int aThreshold = 2;
-  static bool aDumpAsIs = false;
+  static int aNbSpaces = 0;
   // if number of elements in the list if greater than a threshold,
   // dump it in a separate line with specific name
-  if (aDumpAsIs || theAttrSelList->size() <= aThreshold) {
+  if (aNbSpaces > 0 || theAttrSelList->size() <= aThreshold) {
     *myDumpStorage << "[";
 
     GeomShapePtr aShape;
@@ -1424,6 +1498,11 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 
       if(isAdded) {
         *myDumpStorage << ", ";
+        // print each attribute on separate line with the appropriate shift
+        if (aNbSpaces > 0) {
+          std::string aSpaces(aNbSpaces + 1, ' ');
+          *myDumpStorage << "\n" << aSpaces;
+        }
       } else {
         isAdded = true;
       }
@@ -1457,9 +1536,9 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     }
     // reserve dumped buffer and store list "as is"
     myDumpStorage->reserveBuffer();
-    aDumpAsIs = true;
+    aNbSpaces = (int)aListName.size() + 3;
     *this << aListName << " = " << theAttrSelList << "\n";
-    aDumpAsIs = false;
+    aNbSpaces = 0;
     // append reserved data to the end of the current buffer
     myDumpStorage->restoreReservedBuffer();
     *myDumpStorage << aListName;
@@ -1484,6 +1563,11 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
   return *this;
 }
 
+void ModelHighAPI_Dumper::newline()
+{
+  *this << std::endl;
+}
+
 /// Dump std::endl
 ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
                                 std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
@@ -1513,6 +1597,7 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
 
   // store all not-dumped entities first
   std::set<EntityPtr> aNotDumped = theDumper.myNotDumpedEntities;
+  theDumper.clearNotDumped();
   theDumper.myDumpStorage->reserveBuffer();
   std::set<EntityPtr>::const_iterator anIt = aNotDumped.begin();
   for (; anIt != aNotDumped.end(); ++anIt) {
@@ -1567,6 +1652,15 @@ void ModelHighAPI_Dumper::exportVariables() const
         anEntryStr<<aPartId<<":"<<aFeatureId;
         std::string anEntry = anEntryStr.str();
         exportVariable(anEntry, aNameIter->second.myCurrentName);
+        size_t aSize = aFeature->results().size();
+        if (aSize > 1) { // additional entries for features with more than one result
+          for(int a = 1; a < aSize; a++) {
+            std::ostringstream aResEntryStr;
+            aResEntryStr<<anEntry<<":"<<a;
+            std::string aResEntry = aResEntryStr.str();
+            exportVariable(aResEntry, aNameIter->second.myCurrentName);
+          }
+        }
       }
     }
   }