]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
CEA - Lot3 : Add LOFT Feature CEA/FeaturesPlugin/LOFT
authorlucasjerome <jerome.lucas@cegsenslab.fr>
Wed, 27 Jan 2021 18:38:10 +0000 (19:38 +0100)
committerNicolas RECHATIN <nicolas.rechatin@cea.fr>
Thu, 15 Sep 2022 13:45:58 +0000 (15:45 +0200)
28 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/FeaturesPlugin_msg_fr.ts
src/FeaturesPlugin/Test/TestLoft.py [new file with mode: 0644]
src/FeaturesPlugin/doc/FeaturesPlugin.rst
src/FeaturesPlugin/doc/TUI_loftFeature.rst [new file with mode: 0644]
src/FeaturesPlugin/doc/examples/loft.py [new file with mode: 0644]
src/FeaturesPlugin/doc/images/loft.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/loftPropertyPanel.png [new file with mode: 0644]
src/FeaturesPlugin/doc/images/resultLoft.png [new file with mode: 0644]
src/FeaturesPlugin/doc/loftFeature.rst [new file with mode: 0644]
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/FeaturesPlugin/tests.set
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 5ced6f8c9026a309412f4a4d295a4a8ab9f90e80..554d5ddaa44df1fbbd6953c961df67c612d60eef 100644 (file)
@@ -37,6 +37,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_MultiTranslation.h
   FeaturesAPI_Partition.h
   FeaturesAPI_Pipe.h
+  FeaturesAPI_Loft.h
   FeaturesAPI_Placement.h
   FeaturesAPI_PointCloudOnFace.h
   FeaturesAPI_Recover.h
@@ -75,6 +76,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_MultiTranslation.cpp
   FeaturesAPI_Partition.cpp
   FeaturesAPI_Pipe.cpp
+  FeaturesAPI_Loft.cpp
   FeaturesAPI_Placement.cpp
   FeaturesAPI_PointCloudOnFace.cpp
   FeaturesAPI_Recover.cpp
index d9d5367b828a425f3b17219d37a0e5cb5368aabc..2cc08c164e24296392f064da13953eb95e2f89ba 100644 (file)
@@ -76,6 +76,7 @@
 %shared_ptr(FeaturesAPI_MultiTranslation)
 %shared_ptr(FeaturesAPI_Partition)
 %shared_ptr(FeaturesAPI_Pipe)
+%shared_ptr(FeaturesAPI_Loft)
 %shared_ptr(FeaturesAPI_Placement)
 %shared_ptr(FeaturesAPI_PointCloudOnFace)
 %shared_ptr(FeaturesAPI_Recover)
 %include "FeaturesAPI_MultiTranslation.h"
 %include "FeaturesAPI_Partition.h"
 %include "FeaturesAPI_Pipe.h"
+%include "FeaturesAPI_Loft.h"
 %include "FeaturesAPI_Placement.h"
 %include "FeaturesAPI_PointCloudOnFace.h"
 %include "FeaturesAPI_Recover.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_Loft.cpp b/src/FeaturesAPI/FeaturesAPI_Loft.cpp
new file mode 100644 (file)
index 0000000..ad21aa5
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2014-2022  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..aabe0dc
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2014-2022  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 a761ff93a27367c2f95329d8b5f0be88a6d84c95..f03aad755c7c49bf7f09f49f1037893f70dd540a 100644 (file)
@@ -40,6 +40,7 @@
   #include "FeaturesAPI_MultiTranslation.h"
   #include "FeaturesAPI_Partition.h"
   #include "FeaturesAPI_Pipe.h"
+  #include "FeaturesAPI_Loft.h"
   #include "FeaturesAPI_Placement.h"
   #include "FeaturesAPI_PointCloudOnFace.h"
   #include "FeaturesAPI_Recover.h"
index 4f2148191992e867617c6114a21e83e577929bb7..9cc7503140a3a06a1b139d8a3f16dd61102c4d92 100644 (file)
@@ -39,6 +39,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_Intersection.h
     FeaturesPlugin_Partition.h
     FeaturesPlugin_Pipe.h
+    FeaturesPlugin_Loft.h
     FeaturesPlugin_Placement.h
     FeaturesPlugin_PointCloudOnFace.h
     FeaturesPlugin_CompositeBoolean.h
@@ -94,6 +95,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Intersection.cpp
     FeaturesPlugin_Partition.cpp
     FeaturesPlugin_Pipe.cpp
+    FeaturesPlugin_Loft.cpp
     FeaturesPlugin_Placement.cpp
     FeaturesPlugin_PointCloudOnFace.cpp
     FeaturesPlugin_CompositeBoolean.cpp
@@ -152,6 +154,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
@@ -223,16 +226,16 @@ ADD_UNIT_TESTS(
 IF(${HAVE_SALOME})
   enable_testing()
   set(TEST_INSTALL_DIRECTORY "${SALOME_SHAPER_INSTALL_TESTS}/FeaturesPlugin")
-  
+
   install(FILES CTestTestfileInstall.cmake
   DESTINATION ${TEST_INSTALL_DIRECTORY}
   RENAME CTestTestfile.cmake)
   install(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY})
-  
+
   set(TMP_TESTS_NAMES)
   foreach(tfile ${TEST_NAMES})
     list(APPEND TMP_TESTS_NAMES "Test/${tfile}")
   endforeach(tfile ${TEST_NAMES})
-  
+
   install(FILES ${TMP_TESTS_NAMES} DESTINATION ${TEST_INSTALL_DIRECTORY})
 ENDIF(${HAVE_SALOME})
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp b/src/FeaturesPlugin/FeaturesPlugin_Loft.cpp
new file mode 100644 (file)
index 0000000..223e41e
--- /dev/null
@@ -0,0 +1,89 @@
+// Copyright (C) 2014-2022  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_Copy.h>
+#include <GeomAlgoAPI_Filling.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_Tools.h>
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeExplorer.h>
+
+#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();
+    }
+
+    std::string anError;
+    std::shared_ptr<GeomAlgoAPI_Loft> aLoftAlgo(new GeomAlgoAPI_Loft(aFirstShape, aSecondShape));
+
+    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 Faces
+    for(GeomAPI_ShapeExplorer anExp(aLoftAlgo->shape(), GeomAPI_Shape::FACE);
+                              anExp.more(); anExp.next()) {
+      GeomShapePtr anEdge = anExp.current();
+      aResultBody->generated(anEdge, "Loft_Face");
+    }
+    setResult(aResultBody, 0);
+  }
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Loft.h b/src/FeaturesPlugin/FeaturesPlugin_Loft.h
new file mode 100644 (file)
index 0000000..aa83785
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2014-2022  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:
+/// Vertex -> Edge
+/// Edge -> Face
+/// Wire -> Shell
+/// 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();
+};
+
+#endif
index 24442767f66da642bec549d0bf1fb07ba176e65d..ca33e7adcbb5cc1408bcbc6d338a836cd3976581 100644 (file)
@@ -43,6 +43,7 @@
 #include <FeaturesPlugin_NormalToFace.h>
 #include <FeaturesPlugin_Partition.h>
 #include <FeaturesPlugin_Pipe.h>
+#include <FeaturesPlugin_Loft.h>
 #include <FeaturesPlugin_Placement.h>
 #include <FeaturesPlugin_PointCloudOnFace.h>
 #include <FeaturesPlugin_Recover.h>
@@ -87,6 +88,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin()
                               new FeaturesPlugin_ValidatorPipeLocations);
   aFactory->registerValidator("FeaturesPlugin_ValidatorPipeLocationsNumber",
                               new FeaturesPlugin_ValidatorPipeLocationsNumber);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorLoftSameTypeShape",
+                              new FeaturesPlugin_ValidatorLoftSameTypeShape);
   aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionDir",
                               new FeaturesPlugin_ValidatorExtrusionDir);
   aFactory->registerValidator("FeaturesPlugin_ValidatorExtrusionBoundary",
@@ -162,6 +165,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 3181fc925bead505efef23cf7f526ba214ab234d..68fcb043fca7975f05b3aed6c61625b67b7f010e 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 b868e23b8210b57edbc7144d678d00321688c9c3..adfb0cd3f6d9d58a75a8ccafdd42dbbf32621293 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,
index 878c1f4d5b97b1bad9fdab6ec1d76f3155b3364f..653d085b8e3e5f43680376a611b7936bc0d28863 100644 (file)
       <source>Pipe</source>
       <translation>Tuyau</translation>
     </message>
+    <message>
+      <source>Loft</source>
+      <translation>Lissage</translation>
+    </message>
     <message>
       <source>Recover</source>
       <translation>Récupérer</translation>
     </message>
   </context>
 
+  <!-- Loft -->
+  <context>
+    <name>Loft</name>
+    <message>
+      <source>Loft</source>
+      <translation>Lissage</translation>
+    </message>
+  </context>
+  <context>
+    <name>Loft:first_object</name>
+    <message>
+      <source>First object:</source>
+      <translation>Premier objet:</translation>
+    </message>
+  </context>
+    <context>
+      <name>Loft:second_object</name>
+    <message>
+      <source>Second object:</source>
+      <translation>Deuxième objet:</translation>
+    </message>
+  </context>
   <!-- Recover -->
   <context>
     <name>Recover</name>
diff --git a/src/FeaturesPlugin/Test/TestLoft.py b/src/FeaturesPlugin/Test/TestLoft.py
new file mode 100644 (file)
index 0000000..2744522
--- /dev/null
@@ -0,0 +1,198 @@
+# Copyright (C) 2018-2022  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Sketch
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+
+### Create SketchLine
+SketchLine_1 = Sketch_1.addLine(65.56914119359536, 34.84279475982533, -62.33478893740904, 34.84279475982533)
+
+### Create SketchLine
+SketchLine_2 = Sketch_1.addLine(-62.33478893740904, 34.84279475982533, -62.33478893740904, -28.08005822416302)
+
+### Create SketchLine
+SketchLine_3 = Sketch_1.addLine(-62.33478893740904, -28.08005822416302, 65.56914119359536, -28.08005822416302)
+
+### Create SketchLine
+SketchLine_4 = Sketch_1.addLine(65.56914119359536, -28.08005822416302, 65.56914119359536, 34.84279475982533)
+Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+Sketch_1.setHorizontal(SketchLine_1.result())
+Sketch_1.setVertical(SketchLine_2.result())
+Sketch_1.setHorizontal(SketchLine_3.result())
+Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+
+### Create Plane
+Plane_4 = model.addPlane(Part_1_doc, model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("VERTEX", "Sketch_1/SketchLine_3_StartVertex"), False)
+
+### Create Plane
+Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f"), 100, False)
+
+### Create Sketch
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("YOZ"))
+
+### Create SketchCircle
+SketchCircle_1 = Sketch_2.addCircle(60.9581866489876, 39.76685108527785, 26.86156014153439)
+model.do()
+
+### Create Plane
+Plane_6 = model.addPlane(Part_1_doc, model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2r"), 100, False)
+
+### Create Box
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+
+### Create Box
+Box_2 = model.addBox(Part_1_doc, 10, 10, 10)
+
+### Create Translation
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "all-in-Box_2")], axis = model.selection("EDGE", "PartSet/OY"), distance = 100, keepSubResults = True)
+
+### Create Wire
+Wire_1_objects = [model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Right]"),
+                  model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Top]"),
+                  model.selection("EDGE", "[Box_1_1/Back][Box_1_1/Right]"),
+                  model.selection("EDGE", "[Box_1_1/Right][Box_1_1/Bottom]")]
+Wire_1 = model.addWire(Part_1_doc, Wire_1_objects, False)
+
+### Create Wire
+Wire_2_objects = [model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Left][Translation_1_1_1/MF:Translated&Box_2_1/Top]"),
+                  model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Front][Translation_1_1_1/MF:Translated&Box_2_1/Left]"),
+                  model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Left][Translation_1_1_1/MF:Translated&Box_2_1/Bottom]"),
+                  model.selection("EDGE", "[Translation_1_1_1/MF:Translated&Box_2_1/Back][Translation_1_1_1/MF:Translated&Box_2_1/Left]")]
+Wire_2 = model.addWire(Part_1_doc, Wire_2_objects, False)
+
+### Create Box
+Box_3 = model.addBox(Part_1_doc, 10, 10, 10)
+
+### Create Wire
+Wire_3 = model.addWire(Part_1_doc, [model.selection("EDGE", "[Box_3_1/Left][Box_3_1/Top]"), model.selection("EDGE", "[Box_3_1/Front][Box_3_1/Left]")], False)
+
+### Create Box
+Box_4 = model.addBox(Part_1_doc, 10, 10, 10)
+
+### Create Translation
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("COMPOUND", "all-in-Box_4")], axis = model.selection("EDGE", "PartSet/OY"), distance = 40, keepSubResults = True)
+
+### Create Wire
+Wire_4 = model.addWire(Part_1_doc, [model.selection("EDGE", "[Translation_2_1_1/MF:Translated&Box_4_1/Left][Translation_2_1_1/MF:Translated&Box_4_1/Top]"), model.selection("EDGE", "[Translation_2_1_1/MF:Translated&Box_4_1/Front][Translation_2_1_1/MF:Translated&Box_4_1/Left]")], False)
+
+### Create Loft
+Loft_1 = model.addLoft(Part_1_doc, model.selection("FACE", "Plane_2"), model.selection("FACE", "Plane_1"))
+
+### Create Loft
+Loft_2 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_2_1"), model.selection("WIRE", "Wire_1_1"))
+
+### Create Loft
+Loft_3 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_3_1"), model.selection("WIRE", "Wire_4_1"))
+
+### Create Loft
+Loft_4 = model.addLoft(Part_1_doc, model.selection("EDGE", "Sketch_1/SketchLine_2"), model.selection("EDGE", "Sketch_1/SketchLine_4"))
+
+# # Errors tests
+# Wire and Edge
+Box_5 = model.addBox(Part_1_doc, 10, 10, 10)
+Wire_5_objects = [model.selection("EDGE", "[Box_5_1/Back][Box_5_1/Left]"),
+                  model.selection("EDGE", "[Box_5_1/Left][Box_5_1/Top]"),
+                  model.selection("EDGE", "[Box_5_1/Front][Box_5_1/Left]"),
+                  model.selection("EDGE", "[Box_5_1/Left][Box_5_1/Bottom]")]
+Wire_5 = model.addWire(Part_1_doc, Wire_5_objects, False)
+Box_6 = model.addBox(Part_1_doc, 10, 10, 10)
+Loft_5 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_5_1"), model.selection("EDGE", "[Box_6_1/Right][Box_6_1/Top]"))
+assert(Loft_5.feature().error() == "Error: the shapes have different type")
+
+# Wire and Face
+Wire_6_objects = [model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_5]"),
+                  model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_4]"),
+                  model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_2]"),
+                  model.selection("EDGE", "[Loft_1_1/Loft_Face_1][Loft_1_1/Loft_Face_6]")]
+Wire_6 = model.addWire(Part_1_doc, Wire_6_objects, False)
+Loft_6 = model.addLoft(Part_1_doc, model.selection("WIRE", "Wire_6_1"), model.selection("EDGE", "Plane_3"))
+assert(Loft_6.feature().error() == "Error: the shapes have different type")
+
+# Only one element
+Box_7 = model.addBox(Part_1_doc, 10, 10, 10)
+Loft_7 = model.addLoft(Part_1_doc, model.selection("SOLID", "Box_7_1"), model.selection())
+assert(Loft_7.feature().error() == 'Error: Could not get "second_object" attribute.')
+
+# Two faces with different number of edges
+Cone_1 = model.addCone(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 10, 5, 10)
+Loft_8 = model.addLoft(Part_1_doc, model.selection("FACE", "Cone_1_1/Face_2"), model.selection("EDGE", "Plane_3"))
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+#test loft with two face
+model.testNbResults(Loft_1, 1)
+model.testNbSubResults(Loft_1, [0])
+model.testNbSubShapes(Loft_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Loft_1, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Loft_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Loft_1, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Loft_1, [996988.58940])
+
+#test loft with two wire
+model.testNbResults(Loft_2, 1)
+model.testNbSubResults(Loft_2, [0])
+model.testNbSubShapes(Loft_2, GeomAPI_Shape.SHELL, [1])
+model.testNbSubShapes(Loft_2, GeomAPI_Shape.FACE, [4])
+model.testNbSubShapes(Loft_2, GeomAPI_Shape.EDGE, [16])
+model.testNbSubShapes(Loft_2, GeomAPI_Shape.VERTEX, [32])
+model.testResultsVolumes(Loft_2, [0.0])
+
+#test loft with two wire
+model.testNbResults(Loft_3, 1)
+model.testNbSubResults(Loft_3, [0])
+model.testNbSubShapes(Loft_3, GeomAPI_Shape.SHELL, [1])
+model.testNbSubShapes(Loft_3, GeomAPI_Shape.FACE, [2])
+model.testNbSubShapes(Loft_3, GeomAPI_Shape.EDGE, [8])
+model.testNbSubShapes(Loft_3, GeomAPI_Shape.VERTEX, [16])
+model.testResultsVolumes(Loft_3, [0.0])
+
+#test loft with two edge
+model.testNbResults(Loft_4, 1)
+model.testNbSubResults(Loft_4, [0])
+model.testNbSubShapes(Loft_4, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Loft_4, GeomAPI_Shape.EDGE, [4])
+model.testNbSubShapes(Loft_4, GeomAPI_Shape.VERTEX, [8])
+model.testResultsVolumes(Loft_4, [0.0])
+
+#test loft with faces with different number of edges
+model.testNbResults(Loft_8, 1)
+model.testNbSubResults(Loft_8, [0])
+model.testNbSubShapes(Loft_8, GeomAPI_Shape.FACE, [7])
+model.testNbSubShapes(Loft_8, GeomAPI_Shape.EDGE, [30])
+model.testNbSubShapes(Loft_8, GeomAPI_Shape.VERTEX, [60])
+model.testResultsVolumes(Loft_8, [151868.70541])
+
+
+
+
index 6fc8177bd946e0f6bdf8758681daf93320daf32c..ac4a0fd5b8fd11876b0c2e4f815e19cebcea055a 100644 (file)
@@ -25,6 +25,7 @@ Features plug-in provides a set of common topological operations. It implements
    geometryCalculationFeature.rst
    importResultFeature.rst
    linearCopyFeature.rst
+   loftFeature.rst
    measurementFeature.rst
    normalToFaceFeature.rst
    pipeFeature.rst
diff --git a/src/FeaturesPlugin/doc/TUI_loftFeature.rst b/src/FeaturesPlugin/doc/TUI_loftFeature.rst
new file mode 100644 (file)
index 0000000..c97cf3f
--- /dev/null
@@ -0,0 +1,11 @@
+
+  .. _tui_loft:
+
+loft
+====
+
+.. literalinclude:: examples/loft.py      
+    :linenos:
+    :language: python
+
+:download:`Download this script <examples/loft.py>`
diff --git a/src/FeaturesPlugin/doc/examples/loft.py b/src/FeaturesPlugin/doc/examples/loft.py
new file mode 100644 (file)
index 0000000..f3f9dfe
--- /dev/null
@@ -0,0 +1,45 @@
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Sketch
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+
+### Create SketchLine
+SketchLine_1 = Sketch_1.addLine(65.56914119359536, 34.84279475982533, -62.33478893740904, 34.84279475982533)
+
+### Create SketchLine
+SketchLine_2 = Sketch_1.addLine(-62.33478893740904, 34.84279475982533, -62.33478893740904, -28.08005822416302)
+
+### Create SketchLine
+SketchLine_3 = Sketch_1.addLine(-62.33478893740904, -28.08005822416302, 65.56914119359536, -28.08005822416302)
+
+### Create SketchLine
+SketchLine_4 = Sketch_1.addLine(65.56914119359536, -28.08005822416302, 65.56914119359536, 34.84279475982533)
+Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+Sketch_1.setHorizontal(SketchLine_1.result())
+Sketch_1.setVertical(SketchLine_2.result())
+Sketch_1.setHorizontal(SketchLine_3.result())
+Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+
+### Create Plane
+Plane_1 = model.addPlane(Part_1_doc, model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("VERTEX", "Sketch_1/SketchLine_3_StartVertex"), False)
+
+### Create Plane
+Plane_2 = model.addPlane(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f"), 100, False)
+
+### Create Loft
+Loft_1 = model.addLoft(Part_1_doc, model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2"))
+
+model.end()
diff --git a/src/FeaturesPlugin/doc/images/loft.png b/src/FeaturesPlugin/doc/images/loft.png
new file mode 100644 (file)
index 0000000..892ead9
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/loft.png differ
diff --git a/src/FeaturesPlugin/doc/images/loftPropertyPanel.png b/src/FeaturesPlugin/doc/images/loftPropertyPanel.png
new file mode 100644 (file)
index 0000000..7602443
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/loftPropertyPanel.png differ
diff --git a/src/FeaturesPlugin/doc/images/resultLoft.png b/src/FeaturesPlugin/doc/images/resultLoft.png
new file mode 100644 (file)
index 0000000..acf0013
Binary files /dev/null and b/src/FeaturesPlugin/doc/images/resultLoft.png differ
diff --git a/src/FeaturesPlugin/doc/loftFeature.rst b/src/FeaturesPlugin/doc/loftFeature.rst
new file mode 100644 (file)
index 0000000..d053bba
--- /dev/null
@@ -0,0 +1,45 @@
+.. |loft.icon|    image:: images/loft.png
+
+Loft
+====
+
+**Loft** feature is used to create a face, shell or a solid shape from two or more objects.
+The two objects can be edges, wires or faces but must be of the same type
+
+To create a Loft in the active part:
+
+#. select in the Main Menu *Features - > Loft* item  or
+#. click |loft.icon| **Loft** button in the toolbar
+
+The following property panel appears.
+
+.. figure:: images/loftPropertyPanel.png
+   :align: center
+
+   Loft property panel
+
+Input fields:
+
+- **First object** defines the first shape (edge, wire, face) selected in 3D OCC viewer or object browser;
+- **Second object** defines the second shape (edge, wire, face) selected in 3D OCC viewer or object browser;
+
+**TUI Command**:
+
+.. py:function:: model.addLoft(Part_doc, [shape], [shape])
+
+    :param part: The current part object.
+    :param object: A shape in format *model.selection(TYPE, shape)*.
+    :param object: A shape in format *model.selection(TYPE, shape)*.
+    :return: Created object.
+
+Result
+""""""
+
+Result of loft between two faces.
+
+.. figure:: images/resultLoft.png
+   :align: center
+
+   Loft between two faces
+
+**See Also** a sample TUI Script of :ref:`tui_loft` operation.
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..21dc390
--- /dev/null
@@ -0,0 +1,19 @@
+<source>
+  <shape_selector id="first_object"
+                  label="First object:"
+                  tooltip="Select a object"
+                  shape_types="edge face wire"
+                  concealment="true"
+                  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"
+                  concealment="true"
+                  default="">
+    <validator id="GeomValidators_ShapeType" parameters="line,edge,wire,face,shell"/>
+  </shape_selector>
+  <validator id="FeaturesPlugin_ValidatorLoftSameTypeShape"/>
+</source>
index 0292c038ce228d2c71bdcf967359867000744ec9..ccaa0c036b9e271f0a14b61a8574c7830e337053 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="loftFeature.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 f239bdc761c6488c15316ed5d9ad2c809ec6fefe..ecf379dc20c6087a0810ae325c2a6a887f348db8 100644 (file)
@@ -178,7 +178,7 @@ SET(TEST_NAMES
                TestMeasurementAngle3Points.py
                TestMeasurementPresentation.py
                TestFusionFaces.py
-               TestFusionFaces2697.py 
+               TestFusionFaces2697.py
                Test1379.py
                Test1922.py
                Test1942.py
@@ -527,4 +527,5 @@ SET(TEST_NAMES
                TestBoundingBox.py
                Test23885.py
                TestNormalToFace.py
+               TestLoft.py
 )
index eec42e1bd193f8dd46c46c780ae498a57d6a56fe..640ae3a1f4cca5dc119c2bc86aa65a930cbbaf9c 100644 (file)
@@ -61,6 +61,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_PointCloudOnFace.h
     GeomAlgoAPI_Intersection.h
     GeomAlgoAPI_Pipe.h
+    GeomAlgoAPI_Loft.h
     GeomAlgoAPI_WireBuilder.h
     GeomAlgoAPI_Sewing.h
     GeomAlgoAPI_ShapeBuilder.h
@@ -137,6 +138,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_PointCloudOnFace.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..199fd18
--- /dev/null
@@ -0,0 +1,118 @@
+// Copyright (C) 2014-2022  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_DFLoader.h"
+#include "GeomAlgoAPI_Loft.h"
+#include "GeomAlgoAPI_WireBuilder.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 = false;
+
+  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();
+    anIsSolid = true;
+  }
+
+  if (aFirstShape.ShapeType() == TopAbs_WIRE) {
+    aFirstShapeOut = aFirstShape;
+    aSecondShapeOut = aSecondShape;
+  }
+
+  if (aFirstShape.ShapeType() == TopAbs_EDGE)
+  {
+    GeomShapePtr aFirstWire, aSecondWire;
+    ListOfShape aFirstEdge, aSecondEdge;
+
+    // Convert first edge to wire
+    aFirstEdge.push_back(theFirstShape);
+    aFirstWire = GeomAlgoAPI_WireBuilder::wire(aFirstEdge);
+    TopoDS_Shape aFirstShape = aFirstWire->impl<TopoDS_Shape>();
+
+    // Convert first edge to wire
+    aSecondEdge.push_back(theSecondShape);
+    aSecondWire = GeomAlgoAPI_WireBuilder::wire(aSecondEdge);
+    TopoDS_Shape aSecondShape = aSecondWire->impl<TopoDS_Shape>();
+
+    aFirstShapeOut = aFirstShape;
+    aSecondShapeOut = aSecondShape;
+  }
+
+  // Initialize and build
+  BRepOffsetAPI_ThruSections * ThruSections =
+                              new BRepOffsetAPI_ThruSections(anIsSolid);
+  ThruSections->AddWire( TopoDS::Wire( aFirstShapeOut ) );
+  ThruSections->AddWire( TopoDS::Wire( aSecondShapeOut) );
+
+  try
+  {
+    ThruSections->Build();
+  }
+  catch (Standard_Failure& aFail)
+  {
+    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);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h b/src/GeomAlgoAPI/GeomAlgoAPI_Loft.h
new file mode 100644 (file)
index 0000000..da5da2c
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2014-2022  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:
+/// 2 edges -> Face
+/// 2 Wire -> Shell
+/// 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);
+
+  private:
+    void build(const GeomShapePtr theFirstShape,
+              const GeomShapePtr theSecondShape);
+
+};
+
+#endif
index c0faaacf68f1a13834a7cf23583d15200659ea3f..043f9c72690ee30d4f9cf05d5e6991df6175408c 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