Salome HOME
Implementation of 3D Fillet operation
authorazv <azv@opencascade.com>
Thu, 30 Nov 2017 10:04:31 +0000 (13:04 +0300)
committerazv <azv@opencascade.com>
Mon, 4 Dec 2017 07:53:47 +0000 (10:53 +0300)
24 files changed:
src/FeaturesAPI/CMakeLists.txt
src/FeaturesAPI/FeaturesAPI.i
src/FeaturesAPI/FeaturesAPI_Fillet.cpp [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_Fillet.h [new file with mode: 0644]
src/FeaturesAPI/FeaturesAPI_swig.h
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Fillet.h [new file with mode: 0644]
src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/FeaturesPlugin/FeaturesPlugin_Validators.h
src/FeaturesPlugin/Test/TestFillet.py [new file with mode: 0644]
src/FeaturesPlugin/fillet_widget.xml [new file with mode: 0644]
src/FeaturesPlugin/icons/fillet.png [new file with mode: 0644]
src/FeaturesPlugin/icons/fillet_fixed_radius.png [new file with mode: 0644]
src/FeaturesPlugin/icons/fillet_var_radius.png [new file with mode: 0644]
src/FeaturesPlugin/plugin-Features.xml
src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.cpp
src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h [new file with mode: 0644]
src/Model/Model_BodyBuilder.cpp
src/PythonAPI/model/features/__init__.py

index 791859eedd8d904a1846a1f271742ca1c1e91647..1c549224202d4f881ecb6d847c8bad37a59ac8b4 100644 (file)
@@ -25,6 +25,7 @@ SET(PROJECT_HEADERS
   FeaturesAPI_Boolean.h
   FeaturesAPI_Extrusion.h
   FeaturesAPI_ExtrusionBoolean.h
   FeaturesAPI_Boolean.h
   FeaturesAPI_Extrusion.h
   FeaturesAPI_ExtrusionBoolean.h
+  FeaturesAPI_Fillet.h
   FeaturesAPI_Intersection.h
   FeaturesAPI_MultiRotation.h
   FeaturesAPI_MultiTranslation.h
   FeaturesAPI_Intersection.h
   FeaturesAPI_MultiRotation.h
   FeaturesAPI_MultiTranslation.h
@@ -46,6 +47,7 @@ SET(PROJECT_SOURCES
   FeaturesAPI_Boolean.cpp
   FeaturesAPI_Extrusion.cpp
   FeaturesAPI_ExtrusionBoolean.cpp
   FeaturesAPI_Boolean.cpp
   FeaturesAPI_Extrusion.cpp
   FeaturesAPI_ExtrusionBoolean.cpp
+  FeaturesAPI_Fillet.cpp
   FeaturesAPI_Intersection.cpp
   FeaturesAPI_MultiRotation.cpp
   FeaturesAPI_MultiTranslation.cpp
   FeaturesAPI_Intersection.cpp
   FeaturesAPI_MultiRotation.cpp
   FeaturesAPI_MultiTranslation.cpp
index e77373949f43a83a4012c468cb321f6b38173e7e..62afc3e4889829499a60f6e0870b7319d3ffee73 100644 (file)
@@ -44,6 +44,7 @@
 %shared_ptr(FeaturesAPI_ExtrusionBoolean)
 %shared_ptr(FeaturesAPI_ExtrusionCut)
 %shared_ptr(FeaturesAPI_ExtrusionFuse)
 %shared_ptr(FeaturesAPI_ExtrusionBoolean)
 %shared_ptr(FeaturesAPI_ExtrusionCut)
 %shared_ptr(FeaturesAPI_ExtrusionFuse)
+%shared_ptr(FeaturesAPI_Fillet)
 %shared_ptr(FeaturesAPI_Intersection)
 %shared_ptr(FeaturesAPI_MultiRotation)
 %shared_ptr(FeaturesAPI_MultiTranslation)
 %shared_ptr(FeaturesAPI_Intersection)
 %shared_ptr(FeaturesAPI_MultiRotation)
 %shared_ptr(FeaturesAPI_MultiTranslation)
@@ -66,6 +67,7 @@
 %include "FeaturesAPI_Boolean.h"
 %include "FeaturesAPI_Extrusion.h"
 %include "FeaturesAPI_ExtrusionBoolean.h"
 %include "FeaturesAPI_Boolean.h"
 %include "FeaturesAPI_Extrusion.h"
 %include "FeaturesAPI_ExtrusionBoolean.h"
+%include "FeaturesAPI_Fillet.h"
 %include "FeaturesAPI_Intersection.h"
 %include "FeaturesAPI_MultiRotation.h"
 %include "FeaturesAPI_MultiTranslation.h"
 %include "FeaturesAPI_Intersection.h"
 %include "FeaturesAPI_MultiRotation.h"
 %include "FeaturesAPI_MultiTranslation.h"
diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.cpp b/src/FeaturesAPI/FeaturesAPI_Fillet.cpp
new file mode 100644 (file)
index 0000000..17878f0
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "FeaturesAPI_Fillet.h"
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Dumper.h>
+////#include <ModelHighAPI_Reference.h>
+#include <ModelHighAPI_Tools.h>
+
+FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+  : ModelHighAPI_Interface(theFeature)
+{
+  initialize();
+}
+
+FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                       const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                       const ModelHighAPI_Double& theRadius)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod);
+    fillAttribute(theBaseObjects, mybaseObjects);
+    fillAttribute(theRadius, myradius);
+  }
+}
+
+FeaturesAPI_Fillet::FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                                       const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                                       const ModelHighAPI_Double& theRadius1,
+                                       const ModelHighAPI_Double& theRadius2)
+  : ModelHighAPI_Interface(theFeature)
+{
+  if (initialize()) {
+    fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod);
+    fillAttribute(theBaseObjects, mybaseObjects);
+    fillAttribute(theRadius1, mystartRadius);
+    fillAttribute(theRadius2, myendRadius);
+  }
+}
+
+FeaturesAPI_Fillet::~FeaturesAPI_Fillet()
+{
+}
+
+//==================================================================================================
+void FeaturesAPI_Fillet::setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects)
+{
+  mybaseObjects->clear();
+  fillAttribute(theBaseObjects, mybaseObjects);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Fillet::setRadius(const ModelHighAPI_Double& theRadius)
+{
+  fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS(), mycreationMethod);
+  fillAttribute(theRadius, myradius);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Fillet::setRadius(const ModelHighAPI_Double& theRadius1,
+                                   const ModelHighAPI_Double& theRadius2)
+{
+  fillAttribute(FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS(), mycreationMethod);
+  fillAttribute(theRadius1, mystartRadius);
+  fillAttribute(theRadius2, myendRadius);
+
+  execIfBaseNotEmpty();
+}
+
+void FeaturesAPI_Fillet::dump(ModelHighAPI_Dumper& theDumper) const
+{
+  FeaturePtr aBase = feature();
+  const std::string& aDocName = theDumper.name(aBase->document());
+
+  AttributeSelectionListPtr anAttrObjects =
+    aBase->selectionList(FeaturesPlugin_Fillet::OBJECT_LIST_ID());
+
+  theDumper << aBase << " = model.addFillet(" << aDocName << ", " << anAttrObjects;
+
+  std::string aCreationMethod = aBase->string(FeaturesPlugin_Fillet::CREATION_METHOD())->value();
+
+  if(aCreationMethod == FeaturesPlugin_Fillet::CREATION_METHOD_SINGLE_RADIUS()) {
+    AttributeDoublePtr anAttrRadius = aBase->real(FeaturesPlugin_Fillet::RADIUS_ID());
+    theDumper << ", " << anAttrRadius;
+  } else if(aCreationMethod == FeaturesPlugin_Fillet::CREATION_METHOD_VARYING_RADIUS()) {
+    AttributeDoublePtr anAttrRadius1 = aBase->real(FeaturesPlugin_Fillet::START_RADIUS_ID());
+    AttributeDoublePtr anAttrRadius2 = aBase->real(FeaturesPlugin_Fillet::END_RADIUS_ID());
+    theDumper << ", " << anAttrRadius1 << ", " << anAttrRadius2;
+  }
+
+  theDumper << ")" << std::endl;
+}
+
+void FeaturesAPI_Fillet::execIfBaseNotEmpty()
+{
+  if (mybaseObjects->size() > 0)
+    execute();
+}
+
+
+//==================================================================================================
+
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Fillet::ID());
+  return FilletPtr(new FeaturesAPI_Fillet(aFeature, theBaseObjects, theRadius));
+}
+
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius1,
+                    const ModelHighAPI_Double& theRadius2)
+{
+  std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(FeaturesAPI_Fillet::ID());
+  return FilletPtr(new FeaturesAPI_Fillet(aFeature, theBaseObjects, theRadius1, theRadius2));
+}
diff --git a/src/FeaturesAPI/FeaturesAPI_Fillet.h b/src/FeaturesAPI/FeaturesAPI_Fillet.h
new file mode 100644 (file)
index 0000000..e622408
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef FeaturesAPI_Fillet_H_
+#define FeaturesAPI_Fillet_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Fillet.h>
+
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Double;
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Fillet
+/// \ingroup CPPHighAPI
+/// \brief Interface for Fillet feature.
+class FeaturesAPI_Fillet: public ModelHighAPI_Interface
+{
+public:
+  /// Constructor without values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                              const ModelHighAPI_Double& theRadius);
+
+  /// Constructor with values.
+  FEATURESAPI_EXPORT
+  explicit FeaturesAPI_Fillet(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+                              const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                              const ModelHighAPI_Double& theRadius1,
+                              const ModelHighAPI_Double& theRadius2);
+
+  /// Destructor.
+  FEATURESAPI_EXPORT
+  virtual ~FeaturesAPI_Fillet();
+
+  INTERFACE_5(FeaturesPlugin_Fillet::ID(),
+              creationMethod, FeaturesPlugin_Fillet::CREATION_METHOD(),
+                              ModelAPI_AttributeString,
+                              /** Creation method */,
+              baseObjects, FeaturesPlugin_Fillet::OBJECT_LIST_ID(),
+                           ModelAPI_AttributeSelectionList,
+                           /** Base objects */,
+              radius, FeaturesPlugin_Fillet::RADIUS_ID(),
+                      ModelAPI_AttributeDouble,
+                      /** Value of the fixed radius fillet */,
+              startRadius, FeaturesPlugin_Fillet::START_RADIUS_ID(),
+                           ModelAPI_AttributeDouble,
+                           /** Start radius of the varying radius fillet */,
+              endRadius, FeaturesPlugin_Fillet::END_RADIUS_ID(),
+                         ModelAPI_AttributeDouble,
+                         /** End radius of the varying radius fillet */)
+
+  /// Modify base objects of the fillet.
+  FEATURESAPI_EXPORT
+  void setBase(const std::list<ModelHighAPI_Selection>& theBaseObjects);
+
+  /// Modify fillet to have fixed radius
+  FEATURESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theRadius);
+
+  /// Modify fillet to have varying radius
+  FEATURESAPI_EXPORT
+  void setRadius(const ModelHighAPI_Double& theRadius1, const ModelHighAPI_Double& theRadius2);
+
+  /// Dump wrapped feature
+  FEATURESAPI_EXPORT
+  virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+  void execIfBaseNotEmpty();
+};
+
+/// Pointer on Fillet object.
+typedef std::shared_ptr<FeaturesAPI_Fillet> FilletPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Fillet feature.
+FEATURESAPI_EXPORT
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius);
+
+/// \ingroup CPPHighAPI
+/// \brief Create Fillet feature.
+FEATURESAPI_EXPORT
+FilletPtr addFillet(const std::shared_ptr<ModelAPI_Document>& thePart,
+                    const std::list<ModelHighAPI_Selection>& theBaseObjects,
+                    const ModelHighAPI_Double& theRadius1,
+                    const ModelHighAPI_Double& theRadius2);
+
+#endif // FeaturesAPI_Fillet_H_
index 9a6637c03bffd8aa6229af5ea5d4c5fd5523fccf..8b6ce0005d468d1366028a17764a6ba9a7fea3cd 100644 (file)
@@ -27,6 +27,7 @@
   #include "FeaturesAPI_Boolean.h"
   #include "FeaturesAPI_Extrusion.h"
   #include "FeaturesAPI_ExtrusionBoolean.h"
   #include "FeaturesAPI_Boolean.h"
   #include "FeaturesAPI_Extrusion.h"
   #include "FeaturesAPI_ExtrusionBoolean.h"
+  #include "FeaturesAPI_Fillet.h"
   #include "FeaturesAPI_Intersection.h"
   #include "FeaturesAPI_MultiRotation.h"
   #include "FeaturesAPI_MultiTranslation.h"
   #include "FeaturesAPI_Intersection.h"
   #include "FeaturesAPI_MultiRotation.h"
   #include "FeaturesAPI_MultiTranslation.h"
index d527286bb8f73fc659bddf2c70240d84f1ceef29..3b9197381959b52fa0603906b16fe5bea4311c5a 100644 (file)
@@ -51,6 +51,7 @@ SET(PROJECT_HEADERS
     FeaturesPlugin_Scale.h
     FeaturesPlugin_MultiTranslation.h
     FeaturesPlugin_MultiRotation.h
     FeaturesPlugin_Scale.h
     FeaturesPlugin_MultiTranslation.h
     FeaturesPlugin_MultiRotation.h
+    FeaturesPlugin_Fillet.h
 )
 
 SET(PROJECT_SOURCES
 )
 
 SET(PROJECT_SOURCES
@@ -82,6 +83,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Scale.cpp
     FeaturesPlugin_MultiTranslation.cpp
     FeaturesPlugin_MultiRotation.cpp
     FeaturesPlugin_Scale.cpp
     FeaturesPlugin_MultiTranslation.cpp
     FeaturesPlugin_MultiRotation.cpp
+    FeaturesPlugin_Fillet.cpp
 )
 
 SET(XML_RESOURCES
 )
 
 SET(XML_RESOURCES
@@ -106,6 +108,7 @@ SET(XML_RESOURCES
   scale_widget.xml
   multitranslation_widget.xml
   multirotation_widget.xml
   scale_widget.xml
   multitranslation_widget.xml
   multirotation_widget.xml
+  fillet_widget.xml
 )
 
 SET(TEXT_RESOURCES
 )
 
 SET(TEXT_RESOURCES
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp b/src/FeaturesPlugin/FeaturesPlugin_Fillet.cpp
new file mode 100644 (file)
index 0000000..958336b
--- /dev/null
@@ -0,0 +1,231 @@
+// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "FeaturesPlugin_Fillet.h"
+
+#include <ModelAPI_Data.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAlgoAPI_Fillet.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+
+#include <GeomAPI_DataMapOfShapeMapOfShapes.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+
+
+// Obtain all sub-shapes from the shape and append them to the list
+static void collectSubs(const GeomShapePtr& theShape,
+                              ListOfShape& theSubs,
+                        const GeomAPI_Shape::ShapeType theShapeType)
+{
+  GeomAPI_ShapeExplorer anExp(theShape, theShapeType);
+  for (; anExp.more(); anExp.next()) {
+    GeomShapePtr aShape = anExp.current();
+    // Store all shapes with FORWARD orientation to avoid duplication of shared edges/vertices
+    aShape->setOrientation(GeomAPI_Shape::FORWARD);
+    theSubs.push_back(aShape);
+  }
+}
+
+// Extract edges from the list
+static ListOfShape selectEdges(const ListOfShape& theShapes)
+{
+  ListOfShape anEdges;
+  for (ListOfShape::const_iterator anIt = theShapes.begin(); anIt != theShapes.end(); ++anIt)
+    if ((*anIt)->isEdge())
+      anEdges.push_back(*anIt);
+  return anEdges;
+}
+
+// If theShape is a compound of single shape, return it
+static GeomShapePtr unwrapCompound(const GeomShapePtr& theShape)
+{
+  GeomShapePtr aShape = theShape;
+  if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+    int aSubResultsNb = 0;
+    GeomAPI_ShapeIterator anIt(aShape);
+    for(; anIt.more(); anIt.next())
+      ++aSubResultsNb;
+
+    if(aSubResultsNb == 1) {
+      anIt.init(aShape);
+      aShape = anIt.current();
+    }
+  }
+  return aShape;
+}
+
+
+FeaturesPlugin_Fillet::FeaturesPlugin_Fillet()
+{
+}
+
+void FeaturesPlugin_Fillet::initAttributes()
+{
+  data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+  data()->addAttribute(START_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+  data()->addAttribute(END_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_RADIUS_ID());
+}
+
+
+void FeaturesPlugin_Fillet::execute()
+{
+  AttributeStringPtr aCreationMethod = string(CREATION_METHOD());
+  if (!aCreationMethod)
+    return;
+
+  GeomAPI_DataMapOfShapeMapOfShapes aSolidsAndSubs;
+
+  // getting objects and sort them accroding to parent solids
+  AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECT_LIST_ID());
+  for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); ++anObjectsIndex) {
+    AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
+    GeomShapePtr anObject = anObjectAttr->value();
+    if (!anObject)
+      return;
+
+    ResultPtr aContext = anObjectAttr->context();
+    ResultCompSolidPtr aCtxOwner = ModelAPI_Tools::compSolidOwner(aContext);
+    GeomShapePtr aParent = aCtxOwner ? aCtxOwner->shape() : aContext->shape();
+    if (!aParent)
+      return;
+
+    ListOfShape anEdgesAndVertices;
+    collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::EDGE);
+    collectSubs(anObject, anEdgesAndVertices, GeomAPI_Shape::VERTEX);
+    for (ListOfShape::iterator aEIt = anEdgesAndVertices.begin();
+         aEIt != anEdgesAndVertices.end(); ++aEIt)
+      aSolidsAndSubs.add(aParent, *aEIt);
+  }
+
+  bool isFixedRadius = true;
+  double aRadius1 = 0.0, aRadius2 = 0.0;
+  if (aCreationMethod->value() == CREATION_METHOD_SINGLE_RADIUS())
+    aRadius1 = real(RADIUS_ID())->value();
+  else {
+    aRadius1 = real(START_RADIUS_ID())->value();
+    aRadius2 = real(END_RADIUS_ID())->value();
+    isFixedRadius = false;
+  }
+
+  // Perform fillet operation
+  GeomAlgoAPI_MakeShapeList aMakeShapeList;
+  std::shared_ptr<GeomAlgoAPI_Fillet> aFilletBuilder;
+  int aResultIndex = 0;
+
+  GeomAPI_DataMapOfShapeMapOfShapes::iterator anIt = aSolidsAndSubs.begin();
+  for (; anIt != aSolidsAndSubs.end(); ++anIt) {
+    GeomShapePtr aSolid = anIt.first();
+    ListOfShape aFilletEdgesAndVertices = anIt.second();
+
+    ListOfShape aFilletEdges = selectEdges(aFilletEdgesAndVertices);
+    if (isFixedRadius)
+      aFilletBuilder.reset(new GeomAlgoAPI_Fillet(aSolid, aFilletEdges, aRadius1));
+    else
+      aFilletBuilder.reset(new GeomAlgoAPI_Fillet(aSolid, aFilletEdges, aRadius1, aRadius2));
+    if (isFailed(aFilletBuilder))
+      return;
+
+    GeomShapePtr aResult = unwrapCompound(aFilletBuilder->shape());
+    std::shared_ptr<ModelAPI_ResultBody> aResultBody =
+        document()->createBody(data(), aResultIndex);
+
+    loadNamingDS(aResultBody, aSolid, aFilletEdgesAndVertices, aResult, aFilletBuilder);
+    setResult(aResultBody, aResultIndex);
+    aResultIndex++;
+  }
+  removeResults(aResultIndex);
+}
+
+bool FeaturesPlugin_Fillet::isFailed(
+    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm)
+{
+  if (!theAlgorithm->isDone()) {
+    static const std::string aFeatureError = "Error: fillet algorithm failed.";
+    setError(aFeatureError);
+    return true;
+  }
+  if (theAlgorithm->shape()->isNull()) {
+    static const std::string aShapeError = "Error: Resulting shape of fillet is Null.";
+    setError(aShapeError);
+    return true;
+  }
+  if (!theAlgorithm->isValid()) {
+    std::string aFeatureError = "Error: Resulting shape of fillet is not valid.";
+    setError(aFeatureError);
+    return true;
+  }
+  return false;
+}
+
+void FeaturesPlugin_Fillet::loadNamingDS(
+    std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+    const ListOfShape& theFilletShapes,
+    const std::shared_ptr<GeomAPI_Shape> theResultShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape)
+{
+  //load result
+  if(theBaseShape->isEqual(theResultShape)) {
+    theResultBody->store(theResultShape, false);
+    return;
+  }
+
+  std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfShapes = theMakeShape->mapOfSubShapes();
+
+  const int aDeletedTag = 1;
+  const int aModifyTag = 2;
+  const int aGeneratedTag = 3;
+  /// sub solids will be placed at labels 4, 5, etc. if result is compound of solids
+  const int aSubsolidsTag = 4;
+
+  theResultBody->storeModified(theBaseShape, theResultShape, aSubsolidsTag);
+  theResultBody->storeGenerated(theBaseShape, theResultShape);
+
+  const std::string aModFaceName = "Modified_Face";
+  const std::string aFilletFaceName = "Fillet_Face";
+
+  // Store modified faces
+  theResultBody->loadAndOrientModifiedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::FACE,
+      aModifyTag, aModFaceName, *aMapOfShapes);
+
+  // Store new faces generated from edges and vertices
+  theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::EDGE,
+      aGeneratedTag, aFilletFaceName, *aMapOfShapes);
+  theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::VERTEX,
+      aGeneratedTag, aFilletFaceName, *aMapOfShapes);
+
+  // Deleted shapes
+  theResultBody->loadDeletedShapes(theMakeShape.get(), theBaseShape,
+                                   GeomAPI_Shape::EDGE, aDeletedTag);
+  theResultBody->loadDeletedShapes(theMakeShape.get(), theBaseShape,
+                                   GeomAPI_Shape::FACE, aDeletedTag);
+}
diff --git a/src/FeaturesPlugin/FeaturesPlugin_Fillet.h b/src/FeaturesPlugin/FeaturesPlugin_Fillet.h
new file mode 100644 (file)
index 0000000..d0aa712
--- /dev/null
@@ -0,0 +1,120 @@
+// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef FeaturesPlugin_Fillet_H_
+#define FeaturesPlugin_Fillet_H_
+
+#include "FeaturesPlugin.h"
+
+#include <GeomAPI_Shape.h>
+
+#include <ModelAPI_Feature.h>
+
+class GeomAlgoAPI_MakeShape;
+class GeomAPI_DataMapOfShapeMapOfShapes;
+
+/// \class FeaturesPlugin_Fillet
+/// \ingroup Plugins
+/// \brief Feature for applying the Fillet operations on Solids.
+///        Supports fixed radius fillet and varying 2-radius fillet.
+class FeaturesPlugin_Fillet : public ModelAPI_Feature
+{
+public:
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_ID("Fillet");
+    return MY_ID;
+  }
+
+  /// \return the kind of a feature.
+  FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = FeaturesPlugin_Fillet::ID();
+    return MY_KIND;
+  }
+
+  inline static const std::string& CREATION_METHOD()
+  {
+    static std::string MY_CREATION_METHOD("creation_method");
+    return MY_CREATION_METHOD;
+  }
+
+  inline static const std::string CREATION_METHOD_SINGLE_RADIUS()
+  {
+    static std::string MY_SINGLE_RADIUS("fixed_radius");
+    return MY_SINGLE_RADIUS;
+  }
+
+  inline static const std::string CREATION_METHOD_VARYING_RADIUS()
+  {
+    static std::string MY_VARYING_RADIUS("variable_radius");
+    return MY_VARYING_RADIUS;
+  }
+
+  /// Attribute name of main objects.
+  inline static const std::string& OBJECT_LIST_ID()
+  {
+    static const std::string MY_OBJECT_LIST_ID("main_objects");
+    return MY_OBJECT_LIST_ID;
+  }
+
+  /// Attribute name of start radius.
+  inline static const std::string& START_RADIUS_ID()
+  {
+    static const std::string MY_START_RADIUS_ID("radius1");
+    return MY_START_RADIUS_ID;
+  }
+
+  /// Attribute name of end radius.
+  inline static const std::string& END_RADIUS_ID()
+  {
+    static const std::string MY_END_RADIUS_ID("radius2");
+    return MY_END_RADIUS_ID;
+  }
+
+  /// Attribute name of a radius for fillet with fixed radius.
+  inline static const std::string& RADIUS_ID()
+  {
+    return START_RADIUS_ID();
+  }
+
+  /// Creates a new part document if needed.
+  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_Fillet();
+
+private:
+  /// Check algorithm is finished correctly and store error otherwise
+  bool isFailed(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgorithm);
+
+  /// Load Naming data structure of the feature to the document
+  void loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
+                    const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+                    const ListOfShape& theFilletShapes,
+                    const std::shared_ptr<GeomAPI_Shape> theResultShape,
+                    const std::shared_ptr<GeomAlgoAPI_MakeShape>& theMakeShape);
+};
+
+#endif
index 954a0fb3c6786f30618271f2d7055b038dd8eea9..b9760dc07027ad7c55a7d4a85171ae343ad62659 100644 (file)
@@ -24,6 +24,7 @@
 #include <FeaturesPlugin_Extrusion.h>
 #include <FeaturesPlugin_ExtrusionCut.h>
 #include <FeaturesPlugin_ExtrusionFuse.h>
 #include <FeaturesPlugin_Extrusion.h>
 #include <FeaturesPlugin_ExtrusionCut.h>
 #include <FeaturesPlugin_ExtrusionFuse.h>
+#include <FeaturesPlugin_Fillet.h>
 #include <FeaturesPlugin_Intersection.h>
 #include <FeaturesPlugin_MultiRotation.h>
 #include <FeaturesPlugin_MultiTranslation.h>
 #include <FeaturesPlugin_Intersection.h>
 #include <FeaturesPlugin_MultiRotation.h>
 #include <FeaturesPlugin_MultiTranslation.h>
@@ -84,6 +85,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin()
                               new FeaturesPlugin_ValidatorUnionArguments);
   aFactory->registerValidator("FeaturesPlugin_ValidatorConcealedResult",
                               new FeaturesPlugin_ValidatorConcealedResult);
                               new FeaturesPlugin_ValidatorUnionArguments);
   aFactory->registerValidator("FeaturesPlugin_ValidatorConcealedResult",
                               new FeaturesPlugin_ValidatorConcealedResult);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelection",
+                              new FeaturesPlugin_ValidatorFilletSelection);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
 
   // register this plugin
   ModelAPI_Session::get()->registerPlugin(this);
@@ -131,6 +134,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new FeaturesPlugin_MultiTranslation);
   } else if (theFeatureID == FeaturesPlugin_MultiRotation::ID()) {
     return FeaturePtr(new FeaturesPlugin_MultiRotation);
     return FeaturePtr(new FeaturesPlugin_MultiTranslation);
   } else if (theFeatureID == FeaturesPlugin_MultiRotation::ID()) {
     return FeaturePtr(new FeaturesPlugin_MultiRotation);
+  } else if (theFeatureID == FeaturesPlugin_Fillet::ID()) {
+    return FeaturePtr(new FeaturesPlugin_Fillet);
   }
 
   // feature of such kind is not found
   }
 
   // feature of such kind is not found
index 5ec81daa0a9627b4a020d9ab7083fb81031f6ce6..4c53bcbb2bf6b58047f571810267a58d4d249803 100644 (file)
@@ -663,6 +663,47 @@ bool FeaturesPlugin_ValidatorBooleanSelection::isValid(const AttributePtr& theAt
   return true;
 }
 
   return true;
 }
 
+//==================================================================================================
+bool FeaturesPlugin_ValidatorFilletSelection::isValid(const AttributePtr& theAttribute,
+                                                      const std::list<std::string>& theArguments,
+                                                      Events_InfoMessage& theError) const
+{
+  AttributeSelectionListPtr anAttrSelectionList =
+    std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+  if(!anAttrSelectionList.get()) {
+    theError =
+      "Error: This validator can only work with selection list attributes in \"Fillet\" feature.";
+    return false;
+  }
+
+  FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+  // Check all selected entities are sub-shapes of single solid
+  GeomShapePtr aBaseSolid;
+  for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+    AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+    if(!anAttrSelection.get()) {
+      theError = "Error: Empty attribute selection.";
+      return false;
+    }
+    ResultPtr aContext = anAttrSelection->context();
+    if(!aContext.get()) {
+      theError = "Error: Empty selection context.";
+      return false;
+    }
+
+    ResultCompSolidPtr aContextOwner = ModelAPI_Tools::compSolidOwner(aContext);
+    GeomShapePtr anOwner = aContextOwner.get() ? aContextOwner->shape() : aContext->shape();
+    if (!aBaseSolid)
+      aBaseSolid = anOwner;
+    else if (!aBaseSolid->isEqual(anOwner)) {
+      theError = "Error: Sub-shapes of different solids have been selected.";
+      return false;
+    }
+  }
+
+  return true;
+}
+
 //==================================================================================================
 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
                                                        const std::list<std::string>& theArguments,
 //==================================================================================================
 bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
                                                        const std::list<std::string>& theArguments,
index d8c0a091e1a1e6ae1c09c17d7ce2cad7ba754b25..62edcb2bf7fdf7fa8128a2f809a02cd117c6fea8 100644 (file)
@@ -152,6 +152,22 @@ public:
                        Events_InfoMessage& theError) const;
 };
 
                        Events_InfoMessage& theError) const;
 };
 
+/// \class FeaturesPlugin_ValidatorFilletSelection
+/// \ingroup Validators
+/// \brief Validates selection for fillet operation.
+class FeaturesPlugin_ValidatorFilletSelection: public ModelAPI_AttributeValidator
+{
+public:
+  /// \return True if the attribute is valid. It checks whether the selection
+  /// is acceptable for boolean operation.
+  /// \param[in] theAttribute an attribute to check.
+  /// \param[in] theArguments a filter parameters.
+  /// \param[out] theError error message.
+  virtual bool isValid(const AttributePtr& theAttribute,
+                       const std::list<std::string>& theArguments,
+                       Events_InfoMessage& theError) const;
+};
+
 /// \class FeaturesPlugin_ValidatorPartitionSelection
 /// \ingroup Validators
 /// \brief Validates selection for partition.
 /// \class FeaturesPlugin_ValidatorPartitionSelection
 /// \ingroup Validators
 /// \brief Validates selection for partition.
diff --git a/src/FeaturesPlugin/Test/TestFillet.py b/src/FeaturesPlugin/Test/TestFillet.py
new file mode 100644 (file)
index 0000000..49831b3
--- /dev/null
@@ -0,0 +1,134 @@
+## Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+##
+
+"""
+      TestFillet.py
+      Unit test of FeaturesPlugin_Fillet class
+"""
+
+from ModelAPI import *
+
+__updated__ = "2017-11-30"
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+# Create a part for extrusion
+aSession.startOperation()
+aPartFeature = aDocument.addFeature("Part")
+aSession.finishOperation()
+aPart = aSession.activeDocument()
+
+# Create a box and a cylinder for filleting
+aSession.startOperation()
+aBox = aPart.addFeature("Box")
+aBox.string("CreationMethod").setValue("BoxByDimensions")
+aBox.real("dx").setValue(10)
+aBox.real("dy").setValue(10)
+aBox.real("dz").setValue(10)
+aSession.finishOperation()
+
+# a point to anchor a cylinder
+aSession.startOperation()
+aPoint = aPart.addFeature("Point")
+aPoint.string("creation_method").setValue("by_xyz")
+aPoint.real("x").setValue(20)
+aPoint.real("y").setValue(5)
+aPoint.real("z").setValue(0)
+aSession.finishOperation()
+
+aSession.startOperation()
+aCylinder = aPart.addFeature("Cylinder")
+aCylinder.string("CreationMethod").setValue("Cylinder")
+aCylinder.selection("base_point").selectSubShape("vertex", "Point_1")
+aCylinder.selection("axis").selectSubShape("edge", "PartSet/OZ")
+aCylinder.real("radius").setValue(5)
+aCylinder.real("height").setValue(10)
+aSession.finishOperation()
+
+#=========================================================================
+# Test 1. Create fillet with fixed radius
+#=========================================================================
+aSession.startOperation()
+aFillet1 = aPart.addFeature("Fillet")
+aFillet1.string("creation_method").setValue("fixed_radius")
+anObjects = aFillet1.selectionList("main_objects")
+anObjects.append("Box_1_1/Left&Box_1_1/Top", "edge")
+aFillet1.real("radius1").setValue(3)
+aSession.finishOperation()
+assert(aFillet1.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error())
+
+#=========================================================================
+# Test 2. Change fillet type
+#=========================================================================
+aSession.startOperation()
+aFillet1.string("creation_method").setValue("variable_radius")
+aFillet1.real("radius1").setValue(5)
+aFillet1.real("radius2").setValue(1)
+aSession.finishOperation()
+assert(aFillet1.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error())
+
+#=========================================================================
+# Test 3. Check fillet reports error if selected entities from different solids
+#=========================================================================
+aSession.startOperation()
+aFillet2 = aPart.addFeature("Fillet")
+aFillet2.string("creation_method").setValue("fixed_radius")
+anObjects = aFillet2.selectionList("main_objects")
+anObjects.append("Cylinder_1_1/Face_2", "face")
+anObjects.append("_Box_1_1/Right", "face")
+aFillet2.real("radius1").setValue(2)
+aSession.finishOperation()
+assert(aFillet2.error() != ""), "FAILED: Fillet does not report error"
+
+#=========================================================================
+# Test 4. Fix the error
+#=========================================================================
+aSession.startOperation()
+anObjects.removeLast()
+aSession.finishOperation()
+assert(aFillet2.error() == ""), "FAILED: Fillet reports error \"{}\"".format(aFillet1.error())
+
+#=========================================================================
+# Test 5. Check fillet reports error on smoothly connected edges
+#=========================================================================
+aSession.startOperation()
+aFillet3 = aPart.addFeature("Fillet")
+aFillet3.string("creation_method").setValue("fixed_radius")
+aFillet3.selectionList("main_objects").append("Cylinder_1_1/Modified_Face_1", "face")
+aFillet3.real("radius1").setValue(3)
+aSession.finishOperation()
+assert(aFillet3.lastResult() is None), "FAILED: Fillet should not produce a result"
+
+#=========================================================================
+# Test 6. Remove last fillet feature
+#=========================================================================
+aSession.startOperation()
+aPart.removeFeature(aFillet3)
+aSession.finishOperation()
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+from salome.shaper import model
+assert(model.checkPythonDump())
diff --git a/src/FeaturesPlugin/fillet_widget.xml b/src/FeaturesPlugin/fillet_widget.xml
new file mode 100644 (file)
index 0000000..1ccb5bc
--- /dev/null
@@ -0,0 +1,76 @@
+<!--
+Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+-->
+
+<source>
+  <toolbox id="creation_method">
+    <box id="fixed_radius"
+         title="Fixed radius"
+         tooltip="Fillet with fixed radius"
+         icon="icons/Features/fillet_fixed_radius.png">
+      <multi_selector id="main_objects"
+                      label="Faces or/and edges"
+                      icon=""
+                      tooltip="Select objects"
+                      type_choice="edges faces"
+                      use_choice="false"
+                      concealment="true">
+        <validator id="PartSet_DifferentObjects"/>
+        <validator id="FeaturesPlugin_ValidatorFilletSelection"/>
+      </multi_selector>
+      <doublevalue id="radius1"
+                   label="Radius"
+                   tooltip="Fillet radius."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+    </box>
+    <box id="variable_radius"
+         title="Varying radius"
+         tooltip="Fillet with varying radius"
+         icon="icons/Features/fillet_var_radius.png">
+      <multi_selector id="main_objects"
+                      label="Faces or/and edges"
+                      icon=""
+                      tooltip="Select objects"
+                      type_choice="edges faces"
+                      use_choice="false"
+                      concealment="true">
+        <validator id="PartSet_DifferentObjects"/>
+        <validator id="FeaturesPlugin_ValidatorFilletSelection"/>
+      </multi_selector>
+      <doublevalue id="radius1"
+                   label="Start radius"
+                   tooltip="Fillet radius at start point."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+      <doublevalue id="radius2"
+                   label="End radius"
+                   tooltip="Fillet radius at end point."
+                   min="0"
+                   default="2">
+        <validator id="GeomValidators_Positive"/>
+      </doublevalue>
+    </box>
+  </toolbox>
+</source>
diff --git a/src/FeaturesPlugin/icons/fillet.png b/src/FeaturesPlugin/icons/fillet.png
new file mode 100644 (file)
index 0000000..3b5a982
Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet.png differ
diff --git a/src/FeaturesPlugin/icons/fillet_fixed_radius.png b/src/FeaturesPlugin/icons/fillet_fixed_radius.png
new file mode 100644 (file)
index 0000000..0897bde
Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet_fixed_radius.png differ
diff --git a/src/FeaturesPlugin/icons/fillet_var_radius.png b/src/FeaturesPlugin/icons/fillet_var_radius.png
new file mode 100644 (file)
index 0000000..56e4a78
Binary files /dev/null and b/src/FeaturesPlugin/icons/fillet_var_radius.png differ
index 298723427364fc02046e55c5d8f173c59e17625d..171d8acb84c66f086b1300720bf00454cc277821 100644 (file)
@@ -80,6 +80,11 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
         <source path="recover_widget.xml"/>
       </feature>
     </group>
         <source path="recover_widget.xml"/>
       </feature>
     </group>
+    <group id="Fillet">
+      <feature id="Fillet" title="Fillet" tooltip="Perform fillet on face or edge" icon="icons/Features/fillet.png" auto_preview="true">
+        <source path="fillet_widget.xml"/>
+      </feature>
+    </group>
   </workbench>
   <workbench id="Part">
     <group id="Movement">
   </workbench>
   <workbench id="Part">
     <group id="Movement">
index d5132057c681ba2403233e98076ec0c0d364d2a4..a7497c0dc511501d449e667aa10c8c486263b47e 100644 (file)
@@ -24,7 +24,8 @@
 #include <NCollection_Map.hxx>
 #include <TopoDS_Shape.hxx>
 
 #include <NCollection_Map.hxx>
 #include <TopoDS_Shape.hxx>
 
-#define MY_MAP implPtr<NCollection_DataMap<TopoDS_Shape, NCollection_Map<TopoDS_Shape> > >()
+typedef NCollection_DataMap<TopoDS_Shape, NCollection_Map<TopoDS_Shape> > MAP;
+#define MY_MAP implPtr<MAP>()
 
 //=================================================================================================
 GeomAPI_DataMapOfShapeMapOfShapes::GeomAPI_DataMapOfShapeMapOfShapes()
 
 //=================================================================================================
 GeomAPI_DataMapOfShapeMapOfShapes::GeomAPI_DataMapOfShapeMapOfShapes()
@@ -113,3 +114,158 @@ int GeomAPI_DataMapOfShapeMapOfShapes::size() const
 {
   return MY_MAP->Size();
 }
 {
   return MY_MAP->Size();
 }
+
+
+//=================================================================================================
+//   iterator implementation
+//=================================================================================================
+
+class IteratorImpl : public GeomAPI_DataMapOfShapeMapOfShapes::iterator
+{
+public:
+  IteratorImpl() {}
+
+  IteratorImpl(const MAP::Iterator& theIterator)
+    : myIterator(theIterator)
+  {}
+
+  IteratorImpl(const std::shared_ptr<IteratorImpl>& theIterator)
+  {
+    mySelf = theIterator;
+  }
+
+  bool operator==(const std::shared_ptr<IteratorImpl>& theOther) const
+  {
+    if (theOther)
+      return theOther->myIterator.IsEqual(myIterator);
+
+    // theOther is end iterator => check the current iterator is not at the end
+    return !myIterator.More();
+  }
+
+  virtual iterator& operator++()
+  {
+    myIterator.Next();
+    return *this;
+  }
+  virtual iterator operator++(int)
+  {
+    std::shared_ptr<IteratorImpl> aSelf = std::dynamic_pointer_cast<IteratorImpl>(mySelf);
+    std::shared_ptr<IteratorImpl> aCopy(new IteratorImpl(aSelf->myIterator));
+    myIterator.Next();
+    return IteratorImpl(aCopy);
+  }
+
+  virtual key_type first() const
+  {
+    if (mySelf)
+      return iterator::first();
+
+    GeomShapePtr aShape(new GeomAPI_Shape);
+    aShape->setImpl(new TopoDS_Shape(myIterator.Key()));
+    return aShape;
+  }
+
+  virtual mapped_type second() const
+  {
+    if (mySelf)
+      return iterator::second();
+
+    ListOfShape anItems;
+    const NCollection_Map<TopoDS_Shape>& aMap = myIterator.Value();
+    for(NCollection_Map<TopoDS_Shape>::Iterator anIt(aMap); anIt.More(); anIt.Next()) {
+      std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
+      aShape->setImpl(new TopoDS_Shape(anIt.Value()));
+      anItems.push_back(aShape);
+    }
+    return anItems;
+  }
+
+private:
+  MAP::Iterator myIterator;
+};
+
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::iterator()
+{
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::iterator(
+    const GeomAPI_DataMapOfShapeMapOfShapes::iterator& theOther)
+  : mySelf(theOther.mySelf)
+{
+}
+
+const GeomAPI_DataMapOfShapeMapOfShapes::iterator&
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator=(
+      const GeomAPI_DataMapOfShapeMapOfShapes::iterator& theOther)
+{
+  mySelf = theOther.mySelf;
+  return *this;
+}
+
+bool GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator==(const iterator& theOther) const
+{
+  std::shared_ptr<IteratorImpl> aSelf = std::dynamic_pointer_cast<IteratorImpl>(mySelf);
+  std::shared_ptr<IteratorImpl> aSelfOther =
+      std::dynamic_pointer_cast<IteratorImpl>(theOther.mySelf);
+
+  return aSelf ? aSelf->operator==(aSelfOther)
+                : (aSelfOther ? aSelfOther->operator==(aSelf) : true);
+}
+
+bool GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator!=(const iterator& theOther) const
+{
+  return !operator==(theOther);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator&
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator++()
+{
+  mySelf->operator++();
+  return *this;
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::operator++(int)
+{
+  return ++(*mySelf);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::key_type
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::first() const
+{
+  return mySelf->first();
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator::mapped_type
+    GeomAPI_DataMapOfShapeMapOfShapes::iterator::second() const
+{
+  return mySelf->second();
+}
+
+
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator GeomAPI_DataMapOfShapeMapOfShapes::begin()
+{
+  MAP::Iterator anIt(*MY_MAP);
+  std::shared_ptr<IteratorImpl> anIter(new IteratorImpl(anIt));
+  return IteratorImpl(anIter);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::const_iterator GeomAPI_DataMapOfShapeMapOfShapes::begin() const
+{
+  MAP::Iterator anIt(*MY_MAP);
+  std::shared_ptr<IteratorImpl> anIter(new IteratorImpl(anIt));
+  return IteratorImpl(anIter);
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::iterator GeomAPI_DataMapOfShapeMapOfShapes::end()
+{
+  return IteratorImpl(std::shared_ptr<IteratorImpl>());
+}
+
+GeomAPI_DataMapOfShapeMapOfShapes::const_iterator GeomAPI_DataMapOfShapeMapOfShapes::end() const
+{
+  return IteratorImpl(std::shared_ptr<IteratorImpl>());
+}
index 9e631c861ebacdeaa0751971773dd328133aa25f..395abae3444c6cba1c40305d8be7a2d38a3d6da8 100644 (file)
@@ -64,6 +64,40 @@ public:
 
   /// \return size of map.
   GEOMAPI_EXPORT int size() const;
 
   /// \return size of map.
   GEOMAPI_EXPORT int size() const;
+
+public:
+  class iterator
+  {
+  public:
+    typedef GeomShapePtr key_type;
+    typedef ListOfShape  mapped_type;
+    typedef std::pair<GeomShapePtr, ListOfShape> value_type;
+
+  public:
+    GEOMAPI_EXPORT iterator();
+    GEOMAPI_EXPORT iterator(const iterator&);
+    GEOMAPI_EXPORT const iterator& operator=(const iterator&);
+
+    GEOMAPI_EXPORT bool operator==(const iterator&) const;
+    GEOMAPI_EXPORT bool operator!=(const iterator&) const;
+
+    GEOMAPI_EXPORT virtual iterator& operator++();
+    GEOMAPI_EXPORT virtual iterator  operator++(int);
+
+    GEOMAPI_EXPORT virtual key_type first() const;
+    GEOMAPI_EXPORT virtual mapped_type second() const;
+
+  protected:
+    std::shared_ptr<iterator> mySelf;
+  };
+
+  typedef iterator const_iterator;
+
+  GEOMAPI_EXPORT iterator begin();
+  GEOMAPI_EXPORT const_iterator begin() const;
+
+  GEOMAPI_EXPORT iterator end();
+  GEOMAPI_EXPORT const_iterator end() const;
 };
 
 #endif
 };
 
 #endif
index aa563452be9c29f5aa92b63c8de5e1b16c97aab6..f2b4f43305e5c6c298197e99f38dd43fc05c7f7e 100644 (file)
@@ -74,6 +74,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_Scale.h
     GeomAlgoAPI_Circ2dBuilder.h
     GeomAlgoAPI_UnifySameDomain.h
     GeomAlgoAPI_Scale.h
     GeomAlgoAPI_Circ2dBuilder.h
     GeomAlgoAPI_UnifySameDomain.h
+    GeomAlgoAPI_Fillet.h
 )
 
 SET(PROJECT_SOURCES
 )
 
 SET(PROJECT_SOURCES
@@ -126,6 +127,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_Scale.cpp
     GeomAlgoAPI_Circ2dBuilder.cpp
     GeomAlgoAPI_UnifySameDomain.cpp
     GeomAlgoAPI_Scale.cpp
     GeomAlgoAPI_Circ2dBuilder.cpp
     GeomAlgoAPI_UnifySameDomain.cpp
+    GeomAlgoAPI_Fillet.cpp
 )
 
 SET(PROJECT_LIBRARIES
 )
 
 SET(PROJECT_LIBRARIES
@@ -140,6 +142,7 @@ SET(PROJECT_LIBRARIES
     ${CAS_TKBRep}
     ${CAS_TKCAF}
     ${CAS_TKCAF}
     ${CAS_TKBRep}
     ${CAS_TKCAF}
     ${CAS_TKCAF}
+    ${CAS_TKFillet}
     ${CAS_TKLCAF}
     ${CAS_TKPrim}
     ${CAS_TKSTEP}
     ${CAS_TKLCAF}
     ${CAS_TKPrim}
     ${CAS_TKSTEP}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.cpp
new file mode 100644 (file)
index 0000000..b3d510c
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_Fillet.h"
+
+#include <BRepFilletAPI_MakeFillet.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_Fillet::GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                       const ListOfShape&  theFilletEdges,
+                                       const double        theFilletRadius)
+{
+  build(theBaseSolid, theFilletEdges, theFilletRadius);
+}
+
+//=================================================================================================
+GeomAlgoAPI_Fillet::GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                       const ListOfShape&  theFilletEdges,
+                                       const double        theStartRadius,
+                                       const double        theEndRadius)
+{
+  if (theEndRadius < 0.)
+    return;
+  build(theBaseSolid, theFilletEdges, theStartRadius, theEndRadius);
+}
+
+//=================================================================================================
+void GeomAlgoAPI_Fillet::build(const GeomShapePtr& theBaseSolid,
+                               const ListOfShape&  theFilletEdges,
+                               const double        theStartRadius,
+                               const double        theEndRadius)
+{
+  if (!theBaseSolid || theFilletEdges.empty() || theStartRadius < 0.)
+    return;
+
+  // create fillet builder
+  BRepFilletAPI_MakeFillet* aFilletBuilder =
+      new BRepFilletAPI_MakeFillet(theBaseSolid->impl<TopoDS_Shape>());
+  setImpl(aFilletBuilder);
+  setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+  // assign filleting edges
+  for (ListOfShape::const_iterator anIt = theFilletEdges.begin();
+       anIt != theFilletEdges.end(); ++anIt) {
+    if ((*anIt)->isEdge())
+      aFilletBuilder->Add( (*anIt)->impl<TopoDS_Edge>() );
+  }
+
+  // assign fillet radii for each contour of filleting edges
+  bool isFixedRadius = theEndRadius < 0.;
+  int aNbContours = aFilletBuilder->NbContours();
+  for (int ind = 1; ind <= aNbContours; ++ind) {
+    if (isFixedRadius)
+      aFilletBuilder->SetRadius(theStartRadius, ind, 1);
+    else
+      aFilletBuilder->SetRadius(theStartRadius, theEndRadius, ind, 1);
+  }
+
+  // build and get result
+  aFilletBuilder->Build();
+  if (!aFilletBuilder->IsDone())
+    return;
+  const TopoDS_Shape& aResult = aFilletBuilder->Shape();
+
+  std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+  aShape->setImpl(new TopoDS_Shape(aResult));
+  setShape(aShape);
+  setDone(true);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h b/src/GeomAlgoAPI/GeomAlgoAPI_Fillet.h
new file mode 100644 (file)
index 0000000..56648cd
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2017  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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_Fillet_H_
+#define GeomAlgoAPI_Fillet_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_Fillet
+/// \ingroup DataAlgo
+/// \brief Perform fillet
+class GeomAlgoAPI_Fillet : public GeomAlgoAPI_MakeShape
+{
+public:
+  /// Run fillet operation with fixed radius.
+  /// \param theBaseSolid    a changing solid
+  /// \param theFilletEdges  list of edges the fillet is performed on
+  /// \param theFilletRadius radius of the fillet
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                        const ListOfShape&  theFilletEdges,
+                                        const double        theFilletRadius);
+
+  /// Run fillet operation with variable radius.
+  /// \param theBaseSolid    a changing solid
+  /// \param theFilletEdges  list of edges the fillet is performed on
+  /// \param theStartRadius  start radius of the fillet
+  /// \param theEndRadius    end radius of the fillet
+  GEOMALGOAPI_EXPORT GeomAlgoAPI_Fillet(const GeomShapePtr& theBaseSolid,
+                                        const ListOfShape&  theFilletEdges,
+                                        const double        theStartRadius,
+                                        const double        theEndRadius);
+
+private:
+  /// Perform fillet operation.
+  /// If theEndRadius is less than 0., the fixed radius fillet will be built.
+  /// \param theBaseSolid    a changing solid
+  /// \param theFilletEdges  list of edges the fillet is performed on
+  /// \param theStartRadius  start radius of the fillet
+  /// \param theEndRadius    end radius of the fillet
+  void build(const GeomShapePtr& theBaseSolid,
+             const ListOfShape&  theFilletEdges,
+             const double        theStartRadius,
+             const double        theEndRadius = -1.0);
+};
+
+#endif
index 24acebc1736d86712342fb8787224d2df1ec5291..f582556ff68ab900b7b42f78b8c912b86c1e4244 100755 (executable)
@@ -446,8 +446,8 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes (
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
-    if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
-      continue; // there is no sence to write history is old shape does not persented in document
+    //if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
+    //  continue; // there is no sence to write history is old shape does not persented in document
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
     ListOfShape aList;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
index a69fea2d010d28f9cb992ecfdaef9b1f10b2e4c9..0347b26b273484f14c39702e969245bb5e132788 100644 (file)
@@ -9,3 +9,4 @@ from FeaturesAPI import addPipe
 from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addFill
 from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
 from FeaturesAPI import addRecover
 from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addFill
 from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
 from FeaturesAPI import addRecover
+from FeaturesAPI import addFillet