Salome HOME
bos #26449: SHAPER: save imported images
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_MultiTranslation.cpp
index d92efbab6ff1037f07ace428479227b9bf12d2b4..5fafcb11a144315bba93ec574b948a943422252c 100644 (file)
@@ -1,25 +1,48 @@
-// Copyright (C) 2014-201x CEA/DEN, EDF R&D
-
-// File:        FeaturesPlugin_MultiTranslation.cpp
-// Created:     30 Jan 2017
-// Author:      Clarisse Genrault (CEA)
+// 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
+// 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 <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 <GeomAPI_Lin.h>
+#include <GeomAPI_ShapeIterator.h>
+#include <GeomAPI_Trsf.h>
 
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_AttributeSelectionList.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()
 {
@@ -39,7 +62,7 @@ void FeaturesPlugin_MultiTranslation::initAttributes()
                        ModelAPI_AttributeDouble::typeId());
   data()->addAttribute(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID(),
                        ModelAPI_AttributeInteger::typeId());
-  
+
   data()->addAttribute(FeaturesPlugin_MultiTranslation::USE_SECOND_DIR_ID(),
                        ModelAPI_AttributeString::typeId());
   data()->addAttribute(FeaturesPlugin_MultiTranslation::AXIS_SECOND_DIR_ID(),
@@ -48,243 +71,110 @@ 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
-      eraseResults();
-      return;
-    }
-    anObjects.push_back(anObject);
-    aContextes.push_back(anObjectAttr->context());
-  }
 
-  //Getting axis.
-  std::shared_ptr<GeomAPI_Ax1> anAxis;
-  std::shared_ptr<GeomAPI_Edge> anEdge;
-  std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
-    selection(FeaturesPlugin_MultiTranslation::AXIS_FIRST_DIR_ID());
-  if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
-  } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
-             anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
+  GeomAPI_ShapeHierarchy anObjects;
+  std::list<ResultPtr> aParts;
+  ResultPtr aTextureSource;
+  if (!FeaturesPlugin_Tools::shapesFromSelectionList
+      (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource))
+    return;
+
+  std::shared_ptr<GeomAPI_Dir> aFirstDir, aSecondDir;
+  double aFirstStep, aSecondStep;
+  int aFirstNbCopies, aSecondNbCopies;
+  if (!paramsAlongDirection(0, aFirstDir, aFirstStep, aFirstNbCopies))
+    return;
+
+  bool useSecondDir = !string(USE_SECOND_DIR_ID())->value().empty();
+  if (useSecondDir) {
+    if (!paramsAlongDirection(1, aSecondDir, aSecondStep, aSecondNbCopies))
+      return;
   }
-  if(anEdge) {
-    anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
-                                                          anEdge->line()->direction()));
+  else {
+    aSecondDir = aFirstDir; // direction does not matter
+    aSecondStep = 0.0;
+    aSecondNbCopies = 1;
   }
 
-  // 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();
-  // 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;
-    
-    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;
-      }
-      
-      aTranslationAlgo->build();
-      
-      // Checking that the algorithm worked properly.
-      if (!aTranslationAlgo->isDone()) {
-        static const std::string aFeatureError = "Error : Multitranslation algorithm failed.";
-        setError(aFeatureError);
-        break;
-      }
-      if (aTranslationAlgo->shape()->isNull()) {
-        static const std::string aShapeError = "Error : Resulting shape is null.";
-        setError(aShapeError);
-        break;
-      }
-      if (!aTranslationAlgo->isValid()) {
-        static const std::string aFeatureError = "Error : Resulting shape in not valid.";
-        setError(aFeatureError);
-        break;
+  // 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);
+
+        ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
+        aResultPart->setTrsf(anOrigin, aTrsf);
+        setResult(aResultPart, aResultIndex);
+        aResultIndex++;
       }
-      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::performTwoDirection()
-{ 
-  // 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
-      eraseResults();
-      return;
     }
-    anObjects.push_back(anObject);
-    aContextes.push_back(anObjectAttr->context());
   }
 
-  //Getting axis.
-  std::shared_ptr<GeomAPI_Ax1> aFirstAxis;
-  std::shared_ptr<GeomAPI_Edge> anEdge;
-  std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
-    selection(FeaturesPlugin_MultiTranslation::AXIS_FIRST_DIR_ID());
-  if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
-  } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
-             anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
-  }
-  if(anEdge) {
-    aFirstAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
-                                                              anEdge->line()->direction()));
-  }
-  std::shared_ptr<GeomAPI_Ax1> aSecondAxis;
-  anObjRef = selection(FeaturesPlugin_MultiTranslation::AXIS_SECOND_DIR_ID());
-  if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
-  } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
-             anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
-    anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
-  }
-  if(anEdge) {
-    aSecondAxis = std::shared_ptr<GeomAPI_Ax1>(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();
-    
-  // 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++) {
+  // 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;
-    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;
+
+    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));
-      
-        if (!aTranslationAlgo->check()) {
-          setError(aTranslationAlgo->getError());
-          break;
-        }
-      
-        aTranslationAlgo->build();
-      
+            new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
+
         // Checking that the algorithm worked properly.
-        if (!aTranslationAlgo->isDone()) {
-          static const std::string aFeatureError = "Error : Multitranslation algorithm failed.";
-          setError(aFeatureError);
-          break;
-        }
-        if (aTranslationAlgo->shape()->isNull()) {
-          static const std::string aShapeError = "Error : Resulting shape is null.";
-          setError(aShapeError);
-          break;
-        }
-        if (!aTranslationAlgo->isValid()) {
-          static const std::string aFeatureError = "Error : Resulting shape in not valid.";
-          setError(aFeatureError);
+        if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(
+            aTranslationAlgo, getKind(), anError)) {
+          setError(anError);
           break;
         }
         aListOfShape.push_back(aTranslationAlgo->shape());
-        aListOfTranslationAlgo.push_back(aTranslationAlgo);
+        aMakeShapeList->appendAlgo(aTranslationAlgo);
       }
     }
-    std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
+    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);
-    aResultBody->storeModified(aBaseShape, aCompound);
-    loadNamingDS(aListOfTranslationAlgo, aResultBody, aBaseShape);
-    setResult(aResultBody, aResultIndex);
-    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.
@@ -292,37 +182,48 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection()
 }
 
 //=================================================================================================
-void FeaturesPlugin_MultiTranslation::loadNamingDS(
-    std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
-    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
-    std::shared_ptr<GeomAPI_Shape> theBaseShape)
+bool FeaturesPlugin_MultiTranslation::paramsAlongDirection(const int theIndex,
+                                                           std::shared_ptr<GeomAPI_Dir>& theDir,
+                                                           double& theDistance,
+                                                           int& theQuantity)
 {
-  int aTag = 1;
-  int anIndex = 1;
-  std::string aTranslatedName;
-  
-  for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
-    theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
-    std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = (*anIt)->mapOfSubShapes();
+  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" };
 
-    // naming of faces
-    aTranslatedName = "Translated_Face_" + std::to_string((long long) anIndex);
-    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::FACE,
-                                               aTag++, aTranslatedName, *aSubShapes.get(),
-                                               false, true);
+  //Getting axis.
+  static const std::string aSelectionError = "Error: The axis shape selection is bad.";
+  AttributeSelectionPtr anObjRef = selection(THE_AXIS_DIR[theIndex]);
+  GeomShapePtr aShape = anObjRef->value();
+  if (!aShape.get() && anObjRef->context().get())
+    aShape = anObjRef->context()->shape();
+  if (!aShape.get()) {
+    setError(aSelectionError);
+    return false;
+  }
 
-    // naming of edges
-    aTranslatedName = "Translated_Edge_" + std::to_string((long long) anIndex);
-    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::EDGE,
-                                               aTag++, aTranslatedName, *aSubShapes.get(),
-                                               false, true);
+  GeomEdgePtr anEdge;
+  if (aShape->isEdge())
+    anEdge = aShape->edge();
+  else if (aShape->isCompound()) {
+    GeomAPI_ShapeIterator anIt(aShape);
+    anEdge = anIt.current()->edge();
+  }
 
-    // naming of vertex
-    aTranslatedName = "Translated_Vertex_" + std::to_string((long long) anIndex);
-    theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::VERTEX,
-                                               aTag++, aTranslatedName, *aSubShapes.get(),
-                                               false, true);
-    
-    ++anIndex;
+  if (!anEdge.get()) {
+    setError(aSelectionError);
+    return false;
   }
-}
\ No newline at end of file
+
+  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 false;
+  }
+  return true;
+}