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_Fillet.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_Fillet.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_Fillet)
 %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_Fillet.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_Fillet.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_Fillet.h
 )
 
 SET(PROJECT_SOURCES
@@ -82,6 +83,7 @@ SET(PROJECT_SOURCES
     FeaturesPlugin_Scale.cpp
     FeaturesPlugin_MultiTranslation.cpp
     FeaturesPlugin_MultiRotation.cpp
+    FeaturesPlugin_Fillet.cpp
 )
 
 SET(XML_RESOURCES
@@ -106,6 +108,7 @@ SET(XML_RESOURCES
   scale_widget.xml
   multitranslation_widget.xml
   multirotation_widget.xml
+  fillet_widget.xml
 )
 
 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_Fillet.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);
+  aFactory->registerValidator("FeaturesPlugin_ValidatorFilletSelection",
+                              new FeaturesPlugin_ValidatorFilletSelection);
 
   // 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);
+  } else if (theFeatureID == FeaturesPlugin_Fillet::ID()) {
+    return FeaturePtr(new FeaturesPlugin_Fillet);
   }
 
   // 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;
 }
 
+//==================================================================================================
+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,
index d8c0a091e1a1e6ae1c09c17d7ce2cad7ba754b25..62edcb2bf7fdf7fa8128a2f809a02cd117c6fea8 100644 (file)
@@ -152,6 +152,22 @@ public:
                        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.
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>
+    <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">
index d5132057c681ba2403233e98076ec0c0d364d2a4..a7497c0dc511501d449e667aa10c8c486263b47e 100644 (file)
@@ -24,7 +24,8 @@
 #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()
@@ -113,3 +114,158 @@ int GeomAPI_DataMapOfShapeMapOfShapes::size() const
 {
   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;
+
+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
index aa563452be9c29f5aa92b63c8de5e1b16c97aab6..f2b4f43305e5c6c298197e99f38dd43fc05c7f7e 100644 (file)
@@ -74,6 +74,7 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_Scale.h
     GeomAlgoAPI_Circ2dBuilder.h
     GeomAlgoAPI_UnifySameDomain.h
+    GeomAlgoAPI_Fillet.h
 )
 
 SET(PROJECT_SOURCES
@@ -126,6 +127,7 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_Scale.cpp
     GeomAlgoAPI_Circ2dBuilder.cpp
     GeomAlgoAPI_UnifySameDomain.cpp
+    GeomAlgoAPI_Fillet.cpp
 )
 
 SET(PROJECT_LIBRARIES
@@ -140,6 +142,7 @@ SET(PROJECT_LIBRARIES
     ${CAS_TKBRep}
     ${CAS_TKCAF}
     ${CAS_TKCAF}
+    ${CAS_TKFillet}
     ${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;
-    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)));
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 addFillet