]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
First implementation of Loft Feature
authorlucasjerome <jerome.lucas@cegsenslab.fr>
Wed, 27 Jan 2021 18:38:10 +0000 (19:38 +0100)
committerlucasjerome <jerome.lucas@cegsenslab.fr>
Wed, 27 Jan 2021 18:38:10 +0000 (19:38 +0100)
18 files changed:
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_Loft.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_Loft.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Loft.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Loft.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.h
src/FeaturesPlugin/icons/loft.png [new file with mode: 0644]
src/FeaturesPlugin/loft_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_Loft.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Loft.h [new file with mode: 0644]
src/PythonAPI/model/features/__init__.py

index 0b8e3055ceea2574236c565de5a95816d09e0a8c..3d5dd4d8f23420fe9bff62ae63e58841544e3ca3 100644 (file)
@@ -36,6 +36,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_MultiTranslation.h
   FeaturesAPI_Partition.h
   FeaturesAPI_Pipe.h
+  FeaturesAPI_Loft.h
   FeaturesAPI_Placement.h
   FeaturesAPI_Recover.h
   FeaturesAPI_RemoveResults.h
@@ -69,6 +70,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_MultiTranslation.cpp
   FeaturesAPI_Partition.cpp
   FeaturesAPI_Pipe.cpp
+  FeaturesAPI_Loft.cpp
   FeaturesAPI_Placement.cpp
   FeaturesAPI_Recover.cpp
   FeaturesAPI_RemoveResults.cpp
index b76fd2dc433da48ec55917f838656249d29c963a..20007d352e89baa8a1c0c09a166016fcd87d98e0 100644 (file)
@@ -75,6 +75,7 @@
 %shared_ptr(FeaturesAPI_MultiTranslation)
 %shared_ptr(FeaturesAPI_Partition)
 %shared_ptr(FeaturesAPI_Pipe)
+%shared_ptr(FeaturesAPI_Loft)
 %shared_ptr(FeaturesAPI_Placement)
 %shared_ptr(FeaturesAPI_Recover)
 %shared_ptr(FeaturesAPI_RemoveSubShapes)
 %include "FeaturesAPI_MultiTranslation.h"
 %include "FeaturesAPI_Partition.h"
 %include "FeaturesAPI_Pipe.h"
+%include "FeaturesAPI_Loft.h"
 %include "FeaturesAPI_Placement.h"
 %include "FeaturesAPI_Recover.h"
 %include "FeaturesAPI_RemoveSubShapes.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_Loft.cpp b/src/FeaturesAPI/FeaturesAPI_Loft.cpp
new file mode 100644 (file)
index 0000000..210186c
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2014-2020  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 "FeaturesAPI_Loft.h"
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+FeaturesAPI_Loft::FeaturesAPI_Loft(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+: ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+//==================================================================================================
+FeaturesAPI_Loft::FeaturesAPI_Loft(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                   const ModelHighAPI_Selection& theFirstObject,
+                                   const ModelHighAPI_Selection& theSecondObject)
+: ModelHighAPI_Interface(theFeature)
+{
+  if(initialize()) {
+    fillAttribute(theFirstObject, myfisrstObject);
+    fillAttribute(theSecondObject, mysecondObject);
+    execute();
+  }
+}
+
+//==================================================================================================
+FeaturesAPI_Loft::~FeaturesAPI_Loft()
+{
+
+}
+
+//==================================================================================================
+void FeaturesAPI_Loft::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionPtr anAttrFirstObject =
+                                    aBase->selection(FeaturesPlugin_Loft::FIRST_OBJECT_ID());
+  AttributeSelectionPtr anAttrSecondObject =
+                                    aBase->selection(FeaturesPlugin_Loft::SECOND_OBJECT_ID());
+
+  theDumper << aBase << " = model.addLoft(" << aDocName << ", "
+            << anAttrFirstObject << ", " << anAttrSecondObject;
+
+  theDumper << ")" << std::endl;
+}
+
+//==================================================================================================
+LoftPtr addLoft(const std::shared_ptr<ModelAPI_Document>& thePart,
+                const ModelHighAPI_Selection& theFirstObject,
+                const ModelHighAPI_Selection& theSecondObject)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Loft::ID());
+
+  return LoftPtr(new FeaturesAPI_Loft(aFeature, theFirstObject, theSecondObject));
+}
+
diff --git a/src/FeaturesAPI/FeaturesAPI_Loft.h b/src/FeaturesAPI/FeaturesAPI_Loft.h
new file mode 100644 (file)
index 0000000..0777fba
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2014-2020  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
+//
+
+#ifndef FeaturesAPI_Loft_H_
+#define FeaturesAPI_Loft_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Loft.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Dumper;
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Loft
+/// \ingroup CPPHighAPI
+/// \brief Interface for Loft feature.
+class FeaturesAPI_Loft: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Loft(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Loft(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                            const ModelHighAPI_Selection& theFirstObject,
+                            const ModelHighAPI_Selection& theSecondObject);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_Loft();
+
+  INTERFACE_2(FeaturesPlugin_Loft::ID(),
+              fisrstObject, FeaturesPlugin_Loft::FIRST_OBJECT_ID(),
+              ModelAPI_AttributeSelection, /** First object */,
+              secondObject, FeaturesPlugin_Loft::SECOND_OBJECT_ID(),
+              ModelAPI_AttributeSelection, /** second objexct */)
+
+  /// Dump wrapped feature
+  FEATURESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Loft object.
+typedef std::shared_ptr<FeaturesAPI_Loft> LoftPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Loft feature.
+FEATURESAPI_EXPORT
+LoftPtr addLoft(const std::shared_ptr<ModelAPI_Document>& thePart,
+                const ModelHighAPI_Selection& theFirstObject,
+                const ModelHighAPI_Selection& theSecondObject);
+
+#endif // FeaturesAPI_Loft_H_
index 17ada7187e7c42fda139cd4ebb47fea682fc0974..4dec708b9a6e970f5ce75d323defff25640107a8 100644 (file)
@@ -39,6 +39,7 @@
   #include "FeaturesAPI_MultiTranslation.h"
   #include "FeaturesAPI_Partition.h"
   #include "FeaturesAPI_Pipe.h"
+  #include "FeaturesAPI_Loft.h"
   #include "FeaturesAPI_Placement.h"
   #include "FeaturesAPI_Recover.h"
   #include "FeaturesAPI_RemoveSubShapes.h"
index 1dce791a91c48cc0b07a8e657e6e0f197598d6e1..766fde58fa67b38b4388ba3b499ceee0dc9981ae 100644 (file)
@@ -38,6 +38,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_Intersection.h
     FeaturesPlugin_Partition.h
     FeaturesPlugin_Pipe.h
+    FeaturesPlugin_Loft.h
     FeaturesPlugin_Placement.h
     FeaturesPlugin_CompositeBoolean.h
     FeaturesPlugin_CompositeSketch.h
@@ -85,6 +86,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Intersection.cpp
     FeaturesPlugin_Partition.cpp
     FeaturesPlugin_Pipe.cpp
+    FeaturesPlugin_Loft.cpp
     FeaturesPlugin_Placement.cpp
     FeaturesPlugin_CompositeBoolean.cpp
     FeaturesPlugin_CompositeSketch.cpp
@@ -135,6 +137,7 @@ SET(XML_RESOURCES
   placement_widget.xml
   intersection_widget.xml
   pipe_widget.xml
+  loft_widget.xml
   remove_subshapes_widget.xml
   union_widget.xml
   symmetry_widget.xml
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp b/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp
new file mode 100644 (file)
index 0000000..0c30c01
--- /dev/null
@@ -0,0 +1,380 @@
+// Copyright (C) 2014-2020  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_Loft.h"
+#include "FeaturesPlugin_Tools.h"
+
+
+#include <ModelAPI_AttributeSelection.h>
+
+#include <GeomAlgoAPI_Tools.h>
+#include <GeomAlgoAPI_Copy.h>
+#include <GeomAlgoAPI_Filling.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_Pnt.h>
+
+#include <map>
+#include <sstream>
+#include <cmath>
+
+//==================================================================================================
+FeaturesPlugin_Loft::FeaturesPlugin_Loft()
+{
+}
+
+//==================================================================================================
+void FeaturesPlugin_Loft::initAttributes()
+{
+  data()->addAttribute(FIRST_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(SECOND_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
+}
+
+//==================================================================================================
+void FeaturesPlugin_Loft::execute()
+{
+  AttributeSelectionPtr aFirstSelection = selection(FIRST_OBJECT_ID());
+  AttributeSelectionPtr aSecondelection = selection(SECOND_OBJECT_ID());
+
+  if (aFirstSelection->isInitialized() && aSecondelection->isInitialized()) {
+
+    GeomShapePtr aFirstShape, aSecondShape;
+
+    if (aFirstSelection && aSecondelection) {
+      aFirstShape = aFirstSelection->value();
+      if (!aFirstShape && aFirstSelection->context())
+        aFirstShape = aFirstSelection->context()->shape();
+
+      aSecondShape = aSecondelection->value();
+      if (!aSecondShape && aSecondelection->context())
+        aSecondShape = aSecondelection->context()->shape();
+
+    }
+    // Loft for two edges
+    if(aFirstShape->isEdge()) {
+
+      std::shared_ptr<GeomAlgoAPI_Filling> aFilling(
+                          new GeomAlgoAPI_Filling(2.0, 5.0, 0, 0.0001, 0.0001 ));
+
+      // collect base shapes
+      GeomEdgePtr aFirstEdge = toEdge(aFirstShape);
+      if (!aFirstEdge) {
+        myLastEdgeStartPoint = GeomPointPtr();
+        myLastEdgeEndPoint = GeomPointPtr();
+        return;
+      }
+      aFilling->add(aFirstEdge);
+
+      GeomEdgePtr aSecondEdge = toEdge(aSecondShape);
+      if (!aSecondEdge) {
+        myLastEdgeStartPoint = GeomPointPtr();
+        myLastEdgeEndPoint = GeomPointPtr();
+        return;
+      }
+      aFilling->add(aSecondEdge);
+      myLastEdgeStartPoint = GeomPointPtr();
+      myLastEdgeEndPoint = GeomPointPtr();
+
+      // build result
+      aFilling->build();
+      std::string anError;
+      if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aFilling, getKind(), anError)) {
+        setError(anError);
+        removeResults(0);
+        return;
+      }
+
+      /// store result
+      GeomShapePtr aCreatedFace = aFilling->shape();
+      ResultBodyPtr aResultBody = document()->createBody(data());
+      aResultBody->store(aCreatedFace);
+      // store edges
+      int anEdgeInd = 0;
+      for(GeomAPI_ShapeExplorer anExp(aCreatedFace, GeomAPI_Shape::EDGE);
+                                anExp.more(); anExp.next()) {
+        GeomShapePtr anEdge = anExp.current();
+        aResultBody->generated(anEdge, "Loft_Edge_" + std::to_string((long long)anEdgeInd));
+      }
+      setResult(aResultBody, 0);
+
+    } else {
+
+      std::shared_ptr<GeomAlgoAPI_Loft> aLoftAlgo(new GeomAlgoAPI_Loft(aFirstShape, aSecondShape));
+
+      std::string anError;
+
+      if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aLoftAlgo, getKind(), anError)) {
+        setError(anError);
+        return;
+      }
+      ListOfShape  theBoundaryShapes;
+      theBoundaryShapes.push_back(aFirstShape);
+      theBoundaryShapes.push_back(aSecondShape);
+
+      // Create result body.
+      ResultBodyPtr aResultBody = document()->createBody(data());
+
+      aResultBody->store(aLoftAlgo->shape());
+      // store edges
+      int anEdgeInd = 0;
+      for(GeomAPI_ShapeExplorer anExp(aLoftAlgo->shape(), GeomAPI_Shape::EDGE);
+                                anExp.more(); anExp.next()) {
+        GeomShapePtr anEdge = anExp.current();
+        aResultBody->generated(anEdge, "Loft_Edge_" + std::to_string((long long)anEdgeInd));
+      }
+      int anFaceInd = 0;
+      for(GeomAPI_ShapeExplorer anExp(aLoftAlgo->shape(), GeomAPI_Shape::FACE);
+                                anExp.more(); anExp.next()) {
+        GeomShapePtr anEdge = anExp.current();
+        aResultBody->generated(anEdge, "Loft_Face_" + std::to_string((long long)anFaceInd));
+      }
+      setResult(aResultBody, 0);
+    }
+  }
+}
+/*=================================================================================================
+GeomShapePtr FeaturesPlugin_Loft::getShape(const std::string& anID)
+{
+  AttributeSelectionPtr theSelection = selection(anID);
+  if (!theSelection.get()) {
+      setError("Error: One of the selected base objects is empty.");
+      return;
+  }
+
+  GeomShapePtr aShape = theSelection->value();
+
+  if (aShape.get() && !aShape->isNull()) {
+    std::cout<<"C'est un shape"<<std::endl;  
+    return aShape;
+  } else {
+    // This may be the whole sketch result selected, check and get faces.
+    ResultConstructionPtr aConstruction =
+      std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theSelection->context());
+    if(!aConstruction.get()) {
+      setError("Error: One of selected sketches does not have results.");
+      return;
+    }
+    int aFacesNum = aConstruction->facesNum();
+    if(aFacesNum == 0) {
+      // Probably it can be construction.
+      aShape = aConstruction->shape();
+      if(aShape.get() && !aShape->isNull()) {
+        std::cout<<"C'est un aConstruction"<<std::endl;  
+        return aShape;
+      }
+    } else {
+      setError("Error: One of the selected base objects is not vaidated");
+      return;
+    }
+  }
+}
+*/
+
+//=================================================================================================
+GeomEdgePtr FeaturesPlugin_Loft::toEdge(const GeomShapePtr& theShape)
+{
+  GeomEdgePtr anEdge = GeomEdgePtr(new GeomAPI_Edge(GeomAlgoAPI_Copy(theShape).shape()));
+
+  if (!anEdge || anEdge->empty()) {
+    static const std::string aFeatureError =
+        "Error: incorrect type of input feature (edges are supported only).";
+    setError(aFeatureError);
+    return anEdge;
+  }
+
+  // correct edge orientation according to filling method
+  // check the distance to previous edge boundaries, reverse edge if necessary
+  GeomPointPtr aStartPnt = anEdge->firstPoint();
+  GeomPointPtr aEndPnt = anEdge->lastPoint();
+  if (anEdge->orientation() == GeomAPI_Shape::REVERSED) {
+    aStartPnt = anEdge->lastPoint();
+    aEndPnt = anEdge->firstPoint();
+  }
+  bool isReverse = false;
+  if (myLastEdgeStartPoint) {
+    double d1 = myLastEdgeStartPoint->distance(aStartPnt)
+              + myLastEdgeEndPoint->distance(aEndPnt);
+    double d2 = myLastEdgeStartPoint->distance(aEndPnt)
+              + myLastEdgeEndPoint->distance(aStartPnt);
+    if (fabs(d1 - d2) < 1.e-7) {
+      // undefined case => check distance to start point only
+      d1 = myLastEdgeStartPoint->distance(aStartPnt);
+      d2 = myLastEdgeStartPoint->distance(aEndPnt);
+    }
+    isReverse = d2 < d1;
+  }
+
+  if (isReverse) {
+    anEdge->reverse();
+    myLastEdgeStartPoint = aEndPnt;
+    myLastEdgeEndPoint = aStartPnt;
+  } else {
+    myLastEdgeStartPoint = aStartPnt;
+    myLastEdgeEndPoint = aEndPnt;
+  }
+
+  return anEdge;
+}
+
+/*==================================================================================================
+void FeaturesPlugin_Loft::storeResult(const std::shared_ptr<GeomAPI_Shape> theFirstShape,
+                                      const std::shared_ptr<GeomAPI_Shape> theSecondShape,
+                                      const std::shared_ptr<GeomAlgoAPI_Loft> theLoftAlgo,
+                                      const int theResultIndex)
+{
+  // Create result body.
+  ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
+
+  // Store generated shape.
+  aResultBody->storeGenerated(theFirstShape, theLoftAlgo->shape());
+  aResultBody->storeGenerated(theSecondShape, theLoftAlgo->shape());
+
+  // Store generated edges/faces.
+  GeomAPI_Shape::ShapeType aBaseShapeType = theFirstShape->shapeType();
+  GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE;
+
+  switch(aBaseShapeType) {
+    case GeomAPI_Shape::VERTEX: {
+      aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
+      break;
+    }
+    case GeomAPI_Shape::EDGE:
+    case GeomAPI_Shape::WIRE: {
+      std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
+      GeomAlgoAPI_ShapeTools::findBounds(theFirstShape, aV1, aV2);
+      ListOfShape aV1History, aV2History;
+      theLoftAlgo->generated(aV1, aV1History);
+      theLoftAlgo->generated(aV2, aV2History);
+      if(!aV1History.empty()) {
+        aResultBody->generated(aV1, aV1History.front());
+      }
+      if(!aV2History.empty()) {
+        aResultBody->generated(aV2, aV2History.front());
+      }
+      GeomAlgoAPI_ShapeTools::findBounds(theSecondShape, aV1, aV2);
+      theLoftAlgo->generated(aV1, aV1History);
+      theLoftAlgo->generated(aV2, aV2History);
+      if(!aV1History.empty()) {
+        aResultBody->generated(aV1, aV1History.front());
+      }
+      if(!aV2History.empty()) {
+        aResultBody->generated(aV2, aV2History.front());
+      }
+    }
+    case GeomAPI_Shape::FACE:
+    case GeomAPI_Shape::SHELL: {
+      aShapeTypeToExplode = GeomAPI_Shape::EDGE;
+      break;
+    }
+    case GeomAPI_Shape::COMPOUND: {
+      aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
+      break;
+    }
+    default:
+      return; // unsupported type of shape
+  }
+
+  if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
+      aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+    aResultBody->loadGeneratedShapes(theLoftAlgo, theFirstShape, GeomAPI_Shape::VERTEX);
+    aResultBody->loadGeneratedShapes(theLoftAlgo, theSecondShape, GeomAPI_Shape::VERTEX);
+  }
+  if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
+      aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+    aResultBody->loadGeneratedShapes(theLoftAlgo, theFirstShape, GeomAPI_Shape::EDGE);
+    aResultBody->loadGeneratedShapes(theLoftAlgo, theSecondShape, GeomAPI_Shape::EDGE);
+  }
+
+  // Store from shapes.
+  storeShapes(aResultBody, aBaseShapeType, theLoftAlgo->fromShapes(), "From_");
+
+  // Store to shapes.
+  storeShapes(aResultBody, aBaseShapeType, theLoftAlgo->toShapes(), "To_");
+
+  setResult(aResultBody, theResultIndex);
+}
+
+//==================================================================================================
+void FeaturesPlugin_Loft::storeShapes(ResultBodyPtr theResultBody,
+                                      const GeomAPI_Shape::ShapeType theBaseShapeType,
+                                      const ListOfShape& theShapes,
+                                      const std::string theName)
+{
+  GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
+  std::string aShapeTypeStr = "Face";
+  switch(theBaseShapeType) {
+    case GeomAPI_Shape::VERTEX: {
+      aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
+      aShapeTypeStr = "Vertex";
+      break;
+    }
+    case GeomAPI_Shape::EDGE:
+    case GeomAPI_Shape::WIRE: {
+      aShapeTypeToExplore = GeomAPI_Shape::EDGE;
+      aShapeTypeStr = "Edge";
+      break;
+    }
+    case GeomAPI_Shape::FACE:
+    case GeomAPI_Shape::SHELL: {
+      aShapeTypeToExplore = GeomAPI_Shape::FACE;
+      aShapeTypeStr = "Face";
+      break;
+    }
+    case GeomAPI_Shape::COMPOUND: {
+      aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
+      break;
+    }
+    default:
+      return; // unsupported type of shape
+  }
+
+  // Store shapes.
+  int aShapeIndex = 1;
+  int aFaceIndex = 1;
+  for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
+    GeomShapePtr aShape = *anIt;
+
+    if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
+      std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
+      storeSubShapeTT(theResultBody, aShape,
+                    aShape->shapeType(),
+                    aName,
+                    aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex);
+    } else {
+      std::string aName = theName + aShapeTypeStr;
+      storeSubShapeTT(theResultBody, aShape, aShapeTypeToExplore, aName, aShapeIndex);
+    }
+  }
+}
+
+//==================================================================================================
+void storeSubShapeTT(ResultBodyPtr theResultBody,
+                   const GeomShapePtr theShape,
+                   const GeomAPI_Shape::ShapeType theType,
+                   const std::string theName,
+                   int& theShapeIndex)
+{
+  for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
+    GeomShapePtr aSubShape = anExp.current();
+    std::ostringstream aStr;
+    aStr << theName << "_" << theShapeIndex++;
+    theResultBody->generated(aSubShape, aStr.str());
+  }
+}
+*/
\ No newline at end of file
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.h b/src/FeaturesPlugin/FeaturesPlugin_Loft.h
new file mode 100644 (file)
index 0000000..ef426ff
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright (C) 2014-2020  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
+//
+
+#ifndef FeaturesPlugin_Loft_H_
+#define FeaturesPlugin_Loft_H_
+
+#include "FeaturesPlugin.h"
+
+#include <GeomAlgoAPI_Loft.h>
+
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_ResultBody.h>
+
+class GeomAPI_Pnt;
+
+/// \class FeaturesPlugin_Loft
+/// \ingroup Plugins
+/// \brief Feature for creation of extrusion along a path.
+/// Pipe creates extrusion of objects along a path.
+/// It produces the following results from objects:\n
+/// Vertex -> Edge\n
+/// Edge -> Face\n
+/// Wire -> Shell\n
+/// Face -> Solid
+class FeaturesPlugin_Loft : public ModelAPI_Feature
+{
+public:
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_FEATURE_ID("Loft");
+    return MY_FEATURE_ID;
+  }
+
+  /// Attribute name for first object selected.
+  inline static const std::string& FIRST_OBJECT_ID()
+  {
+    static const std::string MY_FIRST_OBJECT("first_object");
+    return MY_FIRST_OBJECT;
+  }
+
+  /// Attribute name for second object selected.
+  inline static const std::string& SECOND_OBJECT_ID()
+  {
+    static const std::string MY_SECOND_OBJECT("second_object");
+    return MY_SECOND_OBJECT;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_Loft::ID();
+    return MY_KIND;
+  }
+
+  /// Performs the algorithm and stores results it in the data structure.
+  FEATURESPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Use plugin manager for features creation
+  FeaturesPlugin_Loft();
+
+  private:
+
+  void storeResult(const std::shared_ptr<GeomAPI_Shape> theFirstShape,
+                   const std::shared_ptr<GeomAPI_Shape> theSecondShape,
+                   const std::shared_ptr<GeomAlgoAPI_Loft> theLoftAlgo,
+                   const int theResultIndex = 0);
+
+  void storeShapes(ResultBodyPtr theResultBody,
+                   const GeomAPI_Shape::ShapeType theBaseShapeType,
+                   const ListOfShape& theShapes,
+                   const std::string theName);
+  private:
+  /// Convert shape to edge
+  std::shared_ptr<GeomAPI_Edge> toEdge(const std::shared_ptr<GeomAPI_Shape>& theShape);
+
+  private:
+  std::shared_ptr<GeomAPI_Pnt> myLastEdgeStartPoint;
+  std::shared_ptr<GeomAPI_Pnt> myLastEdgeEndPoint;
+};
+
+#endif
index 0d49dfe08d1da9ca019628b9784e630e8b5331f9..a59a083c6ed082a142ef7663480a5165f1f8e4b1 100644 (file)
@@ -37,6 +37,7 @@
 #include <FeaturesPlugin_MultiTranslation.h>
 #include <FeaturesPlugin_Partition.h>
 #include <FeaturesPlugin_Pipe.h>
+#include <FeaturesPlugin_Loft.h>
 #include <FeaturesPlugin_Placement.h>
 #include <FeaturesPlugin_Recover.h>
 #include <FeaturesPlugin_RemoveSubShapes.h>
@@ -79,7 +80,9 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin()
   aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocations",
                               new FeaturesPlugin_ValidatorPipeLocations);
   aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocationsNumber",
-                              new FeaturesPlugin_ValidatorPipeLocationsNumber);
+                              new FeaturesPlugin_ValidatorLoftSameTypeShape);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorLoftSameTypeShape",
+                              new FeaturesPlugin_ValidatorLoftSameTypeShape);
   aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir",
                               new FeaturesPlugin_ValidatorExtrusionDir);
   aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionBoundary",
@@ -155,6 +158,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_Partition);
   } else if (theFeatureID == FeaturesPlugin_Pipe::ID()) {
     return FeaturePtr(new FeaturesPlugin_Pipe);
+  } else if (theFeatureID == FeaturesPlugin_Loft::ID()) {
+    return FeaturePtr(new FeaturesPlugin_Loft);
   } else if (theFeatureID == FeaturesPlugin_Placement::ID()) {
     return FeaturePtr(new FeaturesPlugin_Placement);
   } else if (theFeatureID == FeaturesPlugin_Recover::ID()) {
index 55bad81ce443f6772c579ab99f0760d2f362ac78..89f21dbc112a04ad90c08294fc44896595d7741c 100644 (file)
@@ -228,6 +228,57 @@ bool FeaturesPlugin_ValidatorPipeLocationsNumber::isValid(
 }
 // LCOV_EXCL_STOP
 
+//==================================================================================================
+bool FeaturesPlugin_ValidatorLoftSameTypeShape::isValid(
+                                                const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                                const std::list<std::string>& theArguments,
+                                                Events_InfoMessage& theError) const
+{
+  static const std::string aFirstObjetcID = "first_object";
+  static const std::string aSecondObjetcID = "second_object";
+
+  if (theFeature->getKind() != "Loft") {
+    theError = "Error: Feature \"%1\" does not supported by this validator.";
+    theError.arg(theFeature->getKind());
+    return false;
+  }
+
+  AttributeSelectionPtr aFirstObjectsSelection = theFeature->selection(aFirstObjetcID);
+  if ( !aFirstObjectsSelection->isInitialized()) {
+    theError = "Error: Could not get \"%1\" attribute.";
+    theError.arg(aFirstObjetcID);
+    return false;
+  }
+
+  AttributeSelectionPtr aSecondObjectsSelection = theFeature->selection(aSecondObjetcID);
+  if (!aSecondObjectsSelection->isInitialized()) {
+    theError = "Error: Could not get \"%1\" attribute.";
+    theError.arg(aSecondObjetcID);
+    return false;
+  }
+
+  GeomShapePtr aFirstShape  = aFirstObjectsSelection->value();
+  if (!aFirstShape.get()) {
+    aFirstShape = aFirstObjectsSelection->context()->shape();
+  }
+  GeomShapePtr aSecondShape  = aSecondObjectsSelection->value();
+  if (!aSecondShape.get()) {
+    aSecondShape = aSecondObjectsSelection->context()->shape();
+  }
+
+  if (aFirstShape->isEqual(aSecondShape)) {
+    theError = "Error: the shapes are equal";
+    return false;
+  }
+
+  if (aFirstShape->shapeType()!=aSecondShape->shapeType()) {
+    theError = "Error: the shapes have different type";
+    return false;
+  }
+
+  return true;
+}
+
 //==================================================================================================
 bool FeaturesPlugin_ValidatorBaseForGeneration::isValid(const AttributePtr& theAttribute,
                                                         const std::list<std::string>& theArguments,
index 951d4c52f969eb17ce2924d31fe0b5732e43c242..5be51813238ab7933d8bc0dfcef2ce404d18f6c6 100644 (file)
@@ -68,6 +68,21 @@ class FeaturesPlugin_ValidatorPipeLocationsNumber: public ModelAPI_FeatureValida
                        Events_InfoMessage& theError) const;
 };
 
+/// \class FeaturesPlugin_ValidatorLoftSameTypeShape
+/// \ingroup Validators
+/// \brief Validator for the same type of shape.
+class FeaturesPlugin_ValidatorLoftSameTypeShape: public ModelAPI_FeatureValidator
+{
+ public:
+  //! \return true if the type of selected are the same
+  //! \param theFeature the checked feature
+  //! \param theArguments arguments of the feature (not used)
+  //! \param theError error message
+  virtual bool isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
 /// \class FeaturesPlugin_ValidatorBaseForGeneration
 /// \ingroup Validators
 /// \brief A validator for selection base for generation. Allows to select faces on sketch,
diff --git a/src/FeaturesPlugin/icons/loft.png b/src/FeaturesPlugin/icons/loft.png
new file mode 100644 (file)
index 0000000..892ead9
Binary files /dev/null and b/src/FeaturesPlugin/icons/loft.png differ
diff --git a/src/FeaturesPlugin/loft_widget.xml b/src/FeaturesPlugin/loft_widget.xml
new file mode 100644 (file)
index 0000000..e88c48b
--- /dev/null
@@ -0,0 +1,17 @@
+<source>
+  <shape_selector id="first_object"
+                  label="First object:"
+                  tooltip="Select a object"
+                  shape_types="edge face wire"
+                  default="">
+    <validator id="GeomValidators_ShapeType" parameters="line,edge,wire,face,shell"/>
+  </shape_selector>
+  <shape_selector id="second_object"
+                  label="Second object:"
+                  tooltip="Select a object"
+                  shape_types="edge face wire"
+                  default="">
+    <validator id="GeomValidators_ShapeType" parameters="line,edge,wire,face,shell"/>
+  </shape_selector>
+  <validator id="FeaturesPlugin_ValidatorLoftSameTypeShape"/>
+</source>
index 08c08b775d79c7aaf9fa5ea31cc8103dbe6f65bf..6c2d309c1876a15a8d9fb946ff631324a2b992c1 100644 (file)
                icon="icons/Features/pipe.png" helpfile="pipeFeature.html">
         <source path="pipe_widget.xml"/>
       </feature>
+      <feature id="Loft" title="Loft" tooltip="Generates a shape xwith two elements"
+               icon="icons/Features/loft.png" helpfile="pipeFeature.html">
+        <source path="loft_widget.xml"/>
+      </feature>
     </group>
     <group id="Boolean" toolbar="yes">
       <feature id="Cut" title="Cut" tooltip="Perform boolean cut operation with objects"
index 2d3df2aee8e4b497a927457e359d2df367c950e1..3c7da3c36981d4b5cb04c00cf86f274aefa0a13d 100644 (file)
@@ -56,6 +56,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_PaveFiller.h
     GeomAlgoAPI_Intersection.h
     GeomAlgoAPI_Pipe.h
+    GeomAlgoAPI_Loft.h
     GeomAlgoAPI_WireBuilder.h
     GeomAlgoAPI_Sewing.h
     GeomAlgoAPI_ShapeBuilder.h
@@ -122,6 +123,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_PaveFiller.cpp
     GeomAlgoAPI_Intersection.cpp
     GeomAlgoAPI_Pipe.cpp
+    GeomAlgoAPI_Loft.cpp
     GeomAlgoAPI_WireBuilder.cpp
     GeomAlgoAPI_Sewing.cpp
     GeomAlgoAPI_ShapeBuilder.cpp
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Loft.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.cpp
new file mode 100644 (file)
index 0000000..b2f2f22
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright (C) 2014-2020  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 "GeomAlgoAPI_Loft.h"
+
+#include "GeomAlgoAPI_DFLoader.h"
+
+#include <BRepOffsetAPI_ThruSections.hxx>
+#include <Precision.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+
+//==================================================================================================
+GeomAlgoAPI_Loft::GeomAlgoAPI_Loft(const GeomShapePtr theFirstShape,
+                                   const GeomShapePtr theSecondShape)
+{
+  build(theFirstShape, theSecondShape);
+}
+
+//==================================================================================================
+void GeomAlgoAPI_Loft::build(const GeomShapePtr theFirstShape,
+                             const GeomShapePtr theSecondShape)
+{
+  // Getting base shape.
+  if(!theFirstShape.get() || !theSecondShape.get()) {
+    return;
+  }
+  TopoDS_Shape aFirstShape = theFirstShape->impl<TopoDS_Shape>();
+  if(aFirstShape.IsNull()) {
+    return;
+  }
+  TopoDS_Shape aSecondShape= theSecondShape->impl<TopoDS_Shape>();
+  if(aSecondShape.IsNull()) {
+    return;
+  }
+
+  bool anIsSolid = true;
+
+  TopoDS_Shape aFirstShapeOut;
+  TopoDS_Shape aSecondShapeOut;
+  if (aFirstShape.ShapeType() == TopAbs_FACE) {
+    TopExp_Explorer anExp(aFirstShape, TopAbs_WIRE);
+    aFirstShapeOut = anExp.Current();
+    TopExp_Explorer anExp2(aSecondShape, TopAbs_WIRE);
+    aSecondShapeOut = anExp2.Current();
+  }
+
+  if (aFirstShape.ShapeType() == TopAbs_WIRE) {
+    aFirstShapeOut = aFirstShape;
+    aSecondShapeOut = aSecondShape;
+    anIsSolid = false;
+  }
+
+  // Initialize and build
+  BRepOffsetAPI_ThruSections * ThruSections =
+                              new BRepOffsetAPI_ThruSections(anIsSolid, Standard_False, 1.0e-06);
+  ThruSections->AddWire( TopoDS::Wire( aFirstShapeOut ) );
+  ThruSections->AddWire( TopoDS::Wire( aSecondShapeOut) );
+
+  try
+  {
+    ThruSections->Build();
+  }
+  catch (Standard_Failure& aFail)
+  {
+    //std::cout << "Error: crash in BRepOffsetAPI_ThruSections" << std::endl;
+    delete ThruSections;
+    return;
+  }
+  // Checking result.
+  if(!ThruSections->IsDone() || ThruSections->Shape().IsNull()) {
+    delete ThruSections;
+    return;
+  }
+
+  this->initialize(ThruSections);
+
+  // Setting result.
+  TopoDS_Shape aResult = ThruSections->Shape();
+  aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+  GeomShapePtr aGeomSh(new GeomAPI_Shape());
+  aGeomSh->setImpl(new TopoDS_Shape(aResult));
+  this->setShape(aGeomSh);
+  this->setDone(true);
+}
+
+//==================================================================================================
+void GeomAlgoAPI_Loft::generated(const GeomShapePtr theShape,
+                                 ListOfShape& theHistory)
+{
+    GeomAlgoAPI_MakeShape::generated(theShape, theHistory);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h
new file mode 100644 (file)
index 0000000..7636e03
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2014-2020  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
+//
+
+#ifndef GeomAlgoAPI_Loft_H_
+#define GeomAlgoAPI_Loft__H_
+
+#include "GeomAlgoAPI.h"
+
+#include "GeomAlgoAPI_MakeShape.h"
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_Loft
+/// \ingroup DataAlgo
+/// \brief Allows to create loft of two objects with same type.
+/// It produces the following results from objects:\n
+/// 2 edges -> Face\n
+/// 2 Wire -> Shell\n
+/// 2 Face -> Solid
+class GeomAlgoAPI_Loft : public GeomAlgoAPI_MakeShape
+{
+public:
+  /// \brief Creates loft for two given shape with same type.
+  /// \param[in] theFirstShape  the first shape.
+  /// \param[in] theSecondShape the second shape.
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Loft(const GeomShapePtr theFirstShape,
+                                      const GeomShapePtr theSecondShape);
+
+  /// \return the list of shapes generated from theShape.
+  /// \param[in] theShape base shape.
+  /// \param[out] theHistory generated shapes.
+  GEOMALGOAPI_EXPORT void generated(const GeomShapePtr theShape,
+                                    ListOfShape& theHistory);
+
+private:
+  void build(const GeomShapePtr theFirstShape,
+             const GeomShapePtr theSecondShape);
+
+};
+
+#endif
index 772dc05c219e2fa9c563ea82796013ef67860cca..7377be5f13e7f4c573bb0bb9c6c3dc7ea7c17eff 100644 (file)
@@ -23,7 +23,7 @@ from FeaturesAPI import addPlacement, addRotation, addScale, addSymmetry, addTra
 from FeaturesAPI import addMultiTranslation, addMultiRotation
 from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse
 from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse
-from FeaturesAPI import addPipe
+from FeaturesAPI import addPipe, addLoft
 from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addSplit
 from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
 from FeaturesAPI import addRecover