Salome HOME
bos #26449: SHAPER: save imported images
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_MultiTranslation.cpp
index d0e5360c4cb84c4b62ce5dae05770b381afd0fb2..5fafcb11a144315bba93ec574b948a943422252c 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2021  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
 //
 // 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
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include <FeaturesPlugin_MultiTranslation.h>
+#include <FeaturesPlugin_Tools.h>
 
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
 #include <GeomAlgoAPI_Tools.h>
+#include <GeomAlgoAPI_Translation.h>
 
 #include <GeomAPI_Ax1.h>
 #include <GeomAPI_Edge.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Tools.h>
 
 #include <math.h>
 
+static const std::string MULTITRANSLATION_VERSION_1("v9.5");
+
 //=================================================================================================
 FeaturesPlugin_MultiTranslation::FeaturesPlugin_MultiTranslation()
 {
@@ -66,128 +71,84 @@ void FeaturesPlugin_MultiTranslation::initAttributes()
                        ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(FeaturesPlugin_MultiTranslation::NB_COPIES_SECOND_DIR_ID(),
                        ModelAPI_AttributeInteger::typeId());
-}
 
-//=================================================================================================
-void FeaturesPlugin_MultiTranslation::execute()
-{
-  std::string useSecondDir = string(FeaturesPlugin_MultiTranslation::USE_SECOND_DIR_ID())->value();
-  if(!useSecondDir.empty()) {
-    performTwoDirection();
-  } else {
-    performOneDirection();
+  if (!aSelection->isInitialized()) {
+    // new feature, not read from file
+    data()->setVersion(MULTITRANSLATION_VERSION_1);
   }
 }
 
 //=================================================================================================
-void FeaturesPlugin_MultiTranslation::performOneDirection()
+void FeaturesPlugin_MultiTranslation::execute()
 {
+  bool isKeepSubShapes = data()->version() == MULTITRANSLATION_VERSION_1;
+
   // Getting objects.
-  ListOfShape anObjects;
-  std::list<ResultPtr> aContextes;
-  AttributeSelectionListPtr anObjectsSelList =
-    selectionList(FeaturesPlugin_MultiTranslation::OBJECTS_LIST_ID());
+  AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECTS_LIST_ID());
   if (anObjectsSelList->size() == 0) {
+    setError("Error: empty selection list");
     return;
   }
-  for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
-    std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
-      anObjectsSelList->value(anObjectsIndex);
-    std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
-    if(!anObject.get()) { // may be for not-activated parts
-      return;
-    }
-    anObjects.push_back(anObject);
-    aContextes.push_back(anObjectAttr->context());
-  }
 
-  //Getting axis.
-  static const std::string aSelectionError = "Error: The axis shape selection is bad.";
-  AttributeSelectionPtr anObjRef = selection(AXIS_FIRST_DIR_ID());
-  GeomShapePtr aShape = anObjRef->value();
-  if (!aShape.get()) {
-    if (anObjRef->context().get()) {
-      aShape = anObjRef->context()->shape();
-    }
-  }
-  if (!aShape.get()) {
-    setError(aSelectionError);
+  GeomAPI_ShapeHierarchy anObjects;
+  std::list<ResultPtr> aParts;
+  ResultPtr aTextureSource;
+  if (!FeaturesPlugin_Tools::shapesFromSelectionList
+      (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource))
     return;
-  }
 
-  GeomEdgePtr anEdge;
-  if (aShape->isEdge())
-  {
-    anEdge = aShape->edge();
-  }
-  else if (aShape->isCompound())
-  {
-    GeomAPI_ShapeIterator anIt(aShape);
-    anEdge = anIt.current()->edge();
-  }
-  else
-  {
-    setError(aSelectionError);
+  std::shared_ptr<GeomAPI_Dir> aFirstDir, aSecondDir;
+  double aFirstStep, aSecondStep;
+  int aFirstNbCopies, aSecondNbCopies;
+  if (!paramsAlongDirection(0, aFirstDir, aFirstStep, aFirstNbCopies))
     return;
-  }
 
-  if (!anEdge.get())
-  {
-    setError(aSelectionError);
-    return;
+  bool useSecondDir = !string(USE_SECOND_DIR_ID())->value().empty();
+  if (useSecondDir) {
+    if (!paramsAlongDirection(1, aSecondDir, aSecondStep, aSecondNbCopies))
+      return;
   }
-
-  std::shared_ptr<GeomAPI_Ax1> anAxis (new GeomAPI_Ax1(anEdge->line()->location(),
-                                                       anEdge->line()->direction()));
-
-  // Getting step.
-  double aStep = real(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID())->value();
-
-  // Getting number of copies.
-  int nbCopies =
-    integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value();
-
-  if (nbCopies <=0) {
-    std::string aFeatureError = "Multitranslation builder ";
-    aFeatureError+=":: the number of copies for the first direction is null or negative.";
-    setError(aFeatureError);
-    return;
+  else {
+    aSecondDir = aFirstDir; // direction does not matter
+    aSecondStep = 0.0;
+    aSecondNbCopies = 1;
   }
 
-  // Moving each object.
+  std::string anError;
   int aResultIndex = 0;
-  std::list<ResultPtr>::iterator aContext = aContextes.begin();
-  for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
-        anObjectsIt++, aContext++) {
-    std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
-    bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
+  // Moving each part.
+  for (std::list<ResultPtr>::iterator aPRes = aParts.begin(); aPRes != aParts.end(); ++aPRes) {
+    ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPRes);
+    std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
+    for (int j = 0; j < aSecondNbCopies; j++) {
+      for (int i = 0; i < aFirstNbCopies; i++) {
+        double dx = i * aFirstStep * aFirstDir->x() + j * aSecondStep * aSecondDir->x();
+        double dy = i * aFirstStep * aFirstDir->y() + j * aSecondStep * aSecondDir->y();
+        double dz = i * aFirstStep * aFirstDir->z() + j * aSecondStep * aSecondDir->z();
+        aTrsf->setTranslation(dx, dy, dz);
 
-    // Setting result.
-    if (isPart) {
-      ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
-      std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
-      for (int i=0; i<nbCopies; i++) {
-        aTrsf->setTranslation(anAxis, i*aStep);
         ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
-        aResultPart->setTrsf(*aContext, aTrsf);
+        aResultPart->setTrsf(anOrigin, aTrsf);
         setResult(aResultPart, aResultIndex);
         aResultIndex++;
       }
-    } else {
-      std::string anError;
-      ListOfShape aListOfShape;
-      std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
-
-      for (int i=0; i<nbCopies; i++) {
-        std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
-          new GeomAlgoAPI_Translation(aBaseShape, anAxis, i*aStep));
+    }
+  }
 
-        if (!aTranslationAlgo->check()) {
-          setError(aTranslationAlgo->getError());
-          break;
-        }
+  // Collect transformations for each object in a part.
+  std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
+  for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
+       anObjectsIt != anObjects.end(); anObjectsIt++) {
+    std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
+    ListOfShape aListOfShape;
 
-        aTranslationAlgo->build();
+    for (int j = 0; j < aSecondNbCopies; j++) {
+      for (int i = 0; i < aFirstNbCopies; i++) {
+        double dx = i * aFirstStep * aFirstDir->x() + j * aSecondStep * aSecondDir->x();
+        double dy = i * aFirstStep * aFirstDir->y() + j * aSecondStep * aSecondDir->y();
+        double dz = i * aFirstStep * aFirstDir->z() + j * aSecondStep * aSecondDir->z();
+        std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
+            new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
 
         // Checking that the algorithm worked properly.
         if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(
@@ -196,17 +157,24 @@ void FeaturesPlugin_MultiTranslation::performOneDirection()
           break;
         }
         aListOfShape.push_back(aTranslationAlgo->shape());
-        aListOfTranslationAlgo.push_back(aTranslationAlgo);
+        aMakeShapeList->appendAlgo(aTranslationAlgo);
       }
-      std::shared_ptr<GeomAPI_Shape> aCompound =
-        GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
-      ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aCompound);
-      loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
-
-      setResult(aResultBody, aResultIndex);
     }
-    aResultIndex++;
+    GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
+    anObjects.markModified(aBaseShape, aCompound);
+  }
+
+  // Build results of the operation.
+  const ListOfShape& anOriginalShapes = anObjects.objects();
+  ListOfShape aTopLevel;
+  anObjects.topLevelObjects(aTopLevel);
+  for (ListOfShape::iterator anIt = aTopLevel.begin(); anIt != aTopLevel.end(); ++anIt) {
+    ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+    FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(),
+                                             aMakeShapeList, *anIt, "Translated");
+    // Copy image data, if any
+    ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody);
+    setResult(aResultBody, aResultIndex++);
   }
 
   // Remove the rest results if there were produced in the previous pass.
@@ -214,231 +182,48 @@ void FeaturesPlugin_MultiTranslation::performOneDirection()
 }
 
 //=================================================================================================
-void FeaturesPlugin_MultiTranslation::performTwoDirection()
+bool FeaturesPlugin_MultiTranslation::paramsAlongDirection(const int theIndex,
+                                                           std::shared_ptr<GeomAPI_Dir>& theDir,
+                                                           double& theDistance,
+                                                           int& theQuantity)
 {
-  // Getting objects.
-  ListOfShape anObjects;
-  std::list<ResultPtr> aContextes;
-  AttributeSelectionListPtr anObjectsSelList =
-    selectionList(FeaturesPlugin_MultiTranslation::OBJECTS_LIST_ID());
-  if (anObjectsSelList->size() == 0) {
-    return;
-  }
-  for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
-    std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
-      anObjectsSelList->value(anObjectsIndex);
-    std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
-    if(!anObject.get()) { // may be for not-activated parts
-      return;
-    }
-    anObjects.push_back(anObject);
-    aContextes.push_back(anObjectAttr->context());
-  }
+  static std::string THE_AXIS_DIR[2] = { AXIS_FIRST_DIR_ID(), AXIS_SECOND_DIR_ID() };
+  static std::string THE_STEP[2] = { STEP_FIRST_DIR_ID(), STEP_SECOND_DIR_ID() };
+  static std::string THE_COPIES[2] = { NB_COPIES_FIRST_DIR_ID(), NB_COPIES_SECOND_DIR_ID() };
+  static std::string THE_INDEX_ID[2] = { "first", "second" };
 
   //Getting axis.
   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
-  AttributeSelectionPtr anObjRef = selection(AXIS_FIRST_DIR_ID());
+  AttributeSelectionPtr anObjRef = selection(THE_AXIS_DIR[theIndex]);
   GeomShapePtr aShape = anObjRef->value();
-  if (!aShape.get()) {
-    if (anObjRef->context().get()) {
-      aShape = anObjRef->context()->shape();
-    }
-  }
+  if (!aShape.get() && anObjRef->context().get())
+    aShape = anObjRef->context()->shape();
   if (!aShape.get()) {
     setError(aSelectionError);
-    return;
+    return false;
   }
 
   GeomEdgePtr anEdge;
   if (aShape->isEdge())
-  {
     anEdge = aShape->edge();
-  }
-  else if (aShape->isCompound())
-  {
+  else if (aShape->isCompound()) {
     GeomAPI_ShapeIterator anIt(aShape);
     anEdge = anIt.current()->edge();
   }
-  else
-  {
-    setError(aSelectionError);
-    return;
-  }
-
-  if (!anEdge.get())
-  {
-    setError(aSelectionError);
-    return;
-  }
 
-  std::shared_ptr<GeomAPI_Ax1> aFirstAxis(new GeomAPI_Ax1(anEdge->line()->location(),
-                                                          anEdge->line()->direction()));
-
-  //Getting axis.
-  anObjRef = selection(AXIS_SECOND_DIR_ID());
-  aShape = anObjRef->value();
-  if (!aShape.get()) {
-    if (anObjRef->context().get()) {
-      aShape = anObjRef->context()->shape();
-    }
-  }
-  if (!aShape.get()) {
+  if (!anEdge.get()) {
     setError(aSelectionError);
-    return;
-  }
-
-  if (aShape->isEdge())
-  {
-    anEdge = aShape->edge();
-  }
-  else if (aShape->isCompound())
-  {
-    GeomAPI_ShapeIterator anIt(aShape);
-    anEdge = anIt.current()->edge();
-  }
-  else
-  {
-    setError(aSelectionError);
-    return;
-  }
-
-  if (!anEdge.get())
-  {
-    setError(aSelectionError);
-    return;
-  }
-
-  std::shared_ptr<GeomAPI_Ax1> aSecondAxis(new GeomAPI_Ax1(anEdge->line()->location(),
-                                                           anEdge->line()->direction()));
-
-  // Getting step.
-  double aFirstStep = real(FeaturesPlugin_MultiTranslation::STEP_FIRST_DIR_ID())->value();
-  double aSecondStep = real(FeaturesPlugin_MultiTranslation::STEP_SECOND_DIR_ID())->value();
-
-  // Getting number of copies.
-  int aFirstNbCopies =
-    integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value();
-  int aSecondNbCopies =
-    integer(FeaturesPlugin_MultiTranslation::NB_COPIES_SECOND_DIR_ID())->value();
-
-  if (aFirstNbCopies <=0) {
-    std::string aFeatureError = "Multitranslation builder ";
-    aFeatureError+=":: the number of copies for the first direction is null or negative.";
-    setError(aFeatureError);
-    return;
+    return false;
   }
 
-  if (aSecondNbCopies <=0) {
-    std::string aFeatureError = "Multitranslation builder ";
-    aFeatureError+=":: the number of copies for the second direction is null or negative.";
+  theDir = anEdge->line()->direction();
+  theDistance = real(THE_STEP[theIndex])->value();
+  theQuantity = integer(THE_COPIES[theIndex])->value();
+  if (theQuantity <= 0) {
+    std::string aFeatureError = "Multitranslation builder :: the number of copies for the ";
+    aFeatureError += THE_INDEX_ID[theIndex] + " direction is null or negative.";
     setError(aFeatureError);
-    return;
-  }
-
-  // Coord aFirstAxis
-  double x1 = aFirstAxis->dir()->x();
-  double y1 = aFirstAxis->dir()->y();
-  double z1 = aFirstAxis->dir()->z();
-  double norm1 = sqrt(x1*x1 + y1*y1 + z1*z1);
-
-  // Coord aSecondAxis
-  double x2 = aSecondAxis->dir()->x();
-  double y2 = aSecondAxis->dir()->y();
-  double z2 = aSecondAxis->dir()->z();
-  double norm2 = sqrt(x2*x2 + y2*y2 + z2*z2);
-
-  // Moving each object.
-  int aResultIndex = 0;
-  std::list<ResultPtr>::iterator aContext = aContextes.begin();
-  for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
-        anObjectsIt++, aContext++) {
-    std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
-    bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
-
-    // Setting result.
-    if (isPart) {
-      ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
-      std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
-      for (int j=0; j<aSecondNbCopies; j++) {
-        for (int i=0; i<aFirstNbCopies; i++) {
-          double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
-          double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
-          double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
-          aTrsf->setTranslation(dx, dy, dz);
-          ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
-          aResultPart->setTrsf(*aContext, aTrsf);
-          setResult(aResultPart, aResultIndex);
-          aResultIndex++;
-        }
-      }
-    } else {
-      std::string anError;
-      ListOfShape aListOfShape;
-      std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
-
-      for (int j=0; j<aSecondNbCopies; j++) {
-        for (int i=0; i<aFirstNbCopies; i++) {
-          double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
-          double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
-          double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
-          std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
-            new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
-
-          if (!aTranslationAlgo->check()) {
-            setError(aTranslationAlgo->getError());
-            break;
-          }
-
-          aTranslationAlgo->build();
-
-          // Checking that the algorithm worked properly.
-          if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(
-              aTranslationAlgo, getKind(), anError)) {
-            setError(anError);
-            break;
-          }
-          aListOfShape.push_back(aTranslationAlgo->shape());
-          aListOfTranslationAlgo.push_back(aTranslationAlgo);
-        }
-      }
-      std::shared_ptr<GeomAPI_Shape> aCompound =
-        GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
-      ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
-      aResultBody->storeModified(aBaseShape, aCompound);
-      loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
-      setResult(aResultBody, aResultIndex);
-    }
-    aResultIndex++;
-  }
-
-  // Remove the rest results if there were produced in the previous pass.
-  removeResults(aResultIndex);
-}
-
-//=================================================================================================
-void FeaturesPlugin_MultiTranslation::loadNamingDS(
-    std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
-    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-    std::shared_ptr<GeomAPI_Shape> theBaseShape)
-{
-  for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
-    theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
-    // naming of faces
-    theResultBody->loadModifiedShapes(*anIt,
-                                      theBaseShape,
-                                      GeomAPI_Shape::FACE,
-                                      "Translated_Face");
-
-    // naming of edges
-    theResultBody->loadModifiedShapes(*anIt,
-                                      theBaseShape,
-                                      GeomAPI_Shape::EDGE,
-                                      "Translated_Edge");
-
-    // naming of vertex
-    theResultBody->loadModifiedShapes(*anIt,
-                                      theBaseShape,
-                                      GeomAPI_Shape::VERTEX,
-                                      "Translated_Vertex");
+    return false;
   }
+  return true;
 }