FeaturesAPI_NormalToFace.h
FeaturesAPI_MultiRotation.h
FeaturesAPI_MultiTranslation.h
+ FeaturesAPI_Offset.h
FeaturesAPI_Partition.h
FeaturesAPI_Pipe.h
FeaturesAPI_Loft.h
+ FeaturesAPI_Thickness.h
FeaturesAPI_Placement.h
FeaturesAPI_PointCloudOnFace.h
FeaturesAPI_Recover.h
FeaturesAPI_NormalToFace.cpp
FeaturesAPI_MultiRotation.cpp
FeaturesAPI_MultiTranslation.cpp
+ FeaturesAPI_Offset.cpp
FeaturesAPI_Partition.cpp
FeaturesAPI_Pipe.cpp
FeaturesAPI_Loft.cpp
+ FeaturesAPI_Thickness.cpp
FeaturesAPI_Placement.cpp
FeaturesAPI_PointCloudOnFace.cpp
FeaturesAPI_Recover.cpp
%shared_ptr(FeaturesAPI_MultiRotation)
%shared_ptr(FeaturesAPI_MultiTranslation)
%shared_ptr(FeaturesAPI_NormalToFace)
+%shared_ptr(FeaturesAPI_Offset)
%shared_ptr(FeaturesAPI_Partition)
%shared_ptr(FeaturesAPI_Pipe)
%shared_ptr(FeaturesAPI_Placement)
%shared_ptr(FeaturesAPI_Sewing)
%shared_ptr(FeaturesAPI_SharedFaces)
%shared_ptr(FeaturesAPI_Symmetry)
+%shared_ptr(FeaturesAPI_Thickness)
%shared_ptr(FeaturesAPI_Translation)
%shared_ptr(FeaturesAPI_Union)
%include "FeaturesAPI_NormalToFace.h"
%include "FeaturesAPI_MultiRotation.h"
%include "FeaturesAPI_MultiTranslation.h"
+%include "FeaturesAPI_Offset.h"
%include "FeaturesAPI_Partition.h"
%include "FeaturesAPI_Pipe.h"
%include "FeaturesAPI_Placement.h"
%include "FeaturesAPI_Sewing.h"
%include "FeaturesAPI_SharedFaces.h"
%include "FeaturesAPI_Symmetry.h"
+%include "FeaturesAPI_Thickness.h"
%include "FeaturesAPI_Translation.h"
%include "FeaturesAPI_Union.h"
--- /dev/null
+// Copyright (C) 2017-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "FeaturesAPI_Offset.h"
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+
+FeaturesAPI_Offset::FeaturesAPI_Offset(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+ : ModelHighAPI_Interface(theFeature)
+{
+ initialize();
+}
+
+FeaturesAPI_Offset::FeaturesAPI_Offset(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const bool isPipeJoint)
+ : FeaturesAPI_Offset(theFeature)
+{
+ if (initialize()) {
+ fillAttribute(FeaturesPlugin_Offset::CREATION_METHOD_EQUAL(), mycreationMethod);
+ fillAttribute(theBaseObject, mybaseObject);
+ fillAttribute(theOffset, myoffsetValue);
+ fillAttribute(isPipeJoint, myisPipeJoint);
+
+ execute();
+ }
+}
+
+FeaturesAPI_Offset::FeaturesAPI_Offset(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const std::list<ModelHighAPI_Selection>& theFaces)
+ : FeaturesAPI_Offset(theFeature)
+{
+ if (initialize()) {
+ fillAttribute(FeaturesPlugin_Offset::CREATION_METHOD_PARTIAL(), mycreationMethod);
+ fillAttribute(theBaseObject, mybaseObject);
+ fillAttribute(theOffset, myoffsetValue);
+ fillAttribute(theFaces, myfaces);
+
+ execute();
+ }
+}
+
+FeaturesAPI_Offset::~FeaturesAPI_Offset()
+{
+}
+
+void FeaturesAPI_Offset::dump(ModelHighAPI_Dumper& theDumper) const
+{
+ FeaturePtr aBase = feature();
+ const std::string& aDocName = theDumper.name(aBase->document());
+
+ AttributeSelectionPtr anAttrShape =
+ aBase->selection(FeaturesPlugin_Offset::BASE_SHAPE_ID());
+
+ AttributeDoublePtr anAttrOffset = aBase->real(FeaturesPlugin_Offset::OFFSET_VALUE_ID());
+
+ std::string aCreationMethod =
+ aBase->string(FeaturesPlugin_Offset::CREATION_METHOD_ID())->value();
+
+ if (aCreationMethod == FeaturesPlugin_Offset::CREATION_METHOD_EQUAL()) {
+ AttributeBooleanPtr anAttrIsPipe = aBase->boolean(FeaturesPlugin_Offset::PIPE_JOINT_ID());
+
+ theDumper << aBase << " = model.addOffset(" << aDocName << ", " << anAttrShape;
+ theDumper << ", " << anAttrOffset << ", " << anAttrIsPipe << ")" << std::endl;
+ }
+ else if (aCreationMethod == FeaturesPlugin_Offset::CREATION_METHOD_PARTIAL()) {
+ AttributeSelectionListPtr anAttrFaces =
+ aBase->selectionList(FeaturesPlugin_Offset::FACES_ID());
+
+ theDumper << aBase << " = model.addOffsetPartial(" << aDocName << ", " << anAttrShape;
+ theDumper << ", " << anAttrOffset << ", " << anAttrFaces << ")" << std::endl;
+ }
+}
+
+//==================================================================================================
+
+OffsetPtr addOffset(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const bool isPipeJoint)
+{
+ FeaturePtr aFeature = thePart->addFeature(FeaturesAPI_Offset::ID());
+
+ OffsetPtr aOffset (new FeaturesAPI_Offset(aFeature, theBaseObject, theOffset, isPipeJoint));
+ return aOffset;
+}
+
+OffsetPtr addOffsetPartial(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const std::list<ModelHighAPI_Selection>& theFaces)
+{
+ FeaturePtr aFeature = thePart->addFeature(FeaturesAPI_Offset::ID());
+
+ OffsetPtr aOffset (new FeaturesAPI_Offset(aFeature, theBaseObject, theOffset, theFaces));
+ return aOffset;
+}
--- /dev/null
+// Copyright (C) 2017-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef FeaturesAPI_Offset_H_
+#define FeaturesAPI_Offset_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Offset.h>
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Offset
+/// \ingroup CPPHighAPI
+/// \brief Interface for Offset feature.
+class FeaturesAPI_Offset: public ModelHighAPI_Interface
+{
+public:
+ /// Constructor without values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Offset(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Offset(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const bool isPipeJoint);
+
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Offset(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const std::list<ModelHighAPI_Selection>& theFaces);
+
+ /// Destructor.
+ FEATURESAPI_EXPORT
+ virtual ~FeaturesAPI_Offset();
+
+ INTERFACE_5(FeaturesPlugin_Offset::ID(),
+
+ creationMethod, FeaturesPlugin_Offset::CREATION_METHOD_ID(),
+ ModelAPI_AttributeString, /** Creation method */,
+
+ baseObject, FeaturesPlugin_Offset::BASE_SHAPE_ID(),
+ ModelAPI_AttributeSelection, /** Base object */,
+
+ offsetValue, FeaturesPlugin_Offset::OFFSET_VALUE_ID(),
+ ModelAPI_AttributeDouble, /** Value of the offset */,
+
+ isPipeJoint, FeaturesPlugin_Offset::PIPE_JOINT_ID(),
+ ModelAPI_AttributeBoolean, /** Is pipe or intersection joint */,
+
+ faces, FeaturesPlugin_Offset::FACES_ID(),
+ ModelAPI_AttributeSelectionList, /** List of faces for partial offset */)
+
+ /// Dump wrapped feature
+ FEATURESAPI_EXPORT
+ virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on the offset object.
+typedef std::shared_ptr<FeaturesAPI_Offset> OffsetPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Offset feature.
+FEATURESAPI_EXPORT
+OffsetPtr addOffset(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const bool isPipeJoint = true);
+
+/// \ingroup CPPHighAPI
+/// \brief Create Offset feature.
+FEATURESAPI_EXPORT
+OffsetPtr addOffsetPartial(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theOffset,
+ const std::list<ModelHighAPI_Selection>& theFaces);
+
+#endif // FeaturesAPI_Offset_H_
--- /dev/null
+// Copyright (C) 2017-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "FeaturesAPI_Thickness.h"
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+//==================================================================================================
+
+FeaturesAPI_Thickness::FeaturesAPI_Thickness(const std::shared_ptr<ModelAPI_Feature>& theFeature)
+ : ModelHighAPI_Interface(theFeature)
+{
+ initialize();
+}
+
+FeaturesAPI_Thickness::FeaturesAPI_Thickness(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const bool isInside)
+ : FeaturesAPI_Thickness(theFeature)
+{
+ if (initialize()) {
+ fillAttribute(FeaturesPlugin_Thickness::CREATION_METHOD_THICK(), mycreationMethod);
+ fillAttribute(theBaseObject, mybaseObject);
+ fillAttribute(theThickness, mythicknessValue);
+ fillAttribute(isInside, myisInside);
+
+ execute();
+ }
+}
+
+FeaturesAPI_Thickness::FeaturesAPI_Thickness(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const std::list<ModelHighAPI_Selection>& theFaces,
+ const bool isInside)
+ : FeaturesAPI_Thickness(theFeature)
+{
+ if (initialize()) {
+ fillAttribute(FeaturesPlugin_Thickness::CREATION_METHOD_HOLLOWED(), mycreationMethod);
+ fillAttribute(theBaseObject, mybaseObject);
+ fillAttribute(theThickness, mythicknessValue);
+ fillAttribute(theFaces, myfaces);
+ fillAttribute(isInside, myisInside);
+
+ execute();
+ }
+}
+
+FeaturesAPI_Thickness::~FeaturesAPI_Thickness()
+{
+}
+
+void FeaturesAPI_Thickness::dump(ModelHighAPI_Dumper& theDumper) const
+{
+ FeaturePtr aBase = feature();
+ const std::string& aDocName = theDumper.name(aBase->document());
+
+ AttributeSelectionPtr anAttrShape =
+ aBase->selection(FeaturesPlugin_Thickness::BASE_SHAPE_ID());
+
+ AttributeDoublePtr anAttrThickness =
+ aBase->real(FeaturesPlugin_Thickness::THICKNESS_VALUE_ID());
+
+ AttributeBooleanPtr anAttrIsInside =
+ aBase->boolean(FeaturesPlugin_Thickness::INSIDE_ID());
+
+ std::string aCreationMethod =
+ aBase->string(FeaturesPlugin_Thickness::CREATION_METHOD_ID())->value();
+
+ if (aCreationMethod == FeaturesPlugin_Thickness::CREATION_METHOD_THICK()) {
+ theDumper << aBase << " = model.addThickness(" << aDocName;
+ theDumper << ", " << anAttrShape << ", " << anAttrThickness;
+ theDumper << ", " << anAttrIsInside << ")" << std::endl;
+ }
+ else if (aCreationMethod == FeaturesPlugin_Thickness::CREATION_METHOD_HOLLOWED()) {
+ AttributeSelectionListPtr anAttrFaces =
+ aBase->selectionList(FeaturesPlugin_Thickness::FACES_ID());
+
+ theDumper << aBase << " = model.addHollowedSolid(" << aDocName;
+ theDumper << ", " << anAttrShape << ", " << anAttrThickness;
+ theDumper << ", " << anAttrFaces;
+ theDumper << ", " << anAttrIsInside << ")" << std::endl;
+ }
+}
+
+//==================================================================================================
+
+ThicknessPtr addThickness(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const bool isInside)
+{
+ FeaturePtr aFeature = thePart->addFeature(FeaturesAPI_Thickness::ID());
+
+ ThicknessPtr aThickness (new FeaturesAPI_Thickness(aFeature, theBaseObject, theThickness, isInside));
+ return aThickness;
+}
+
+ThicknessPtr addHollowedSolid(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const std::list<ModelHighAPI_Selection>& theFaces,
+ const bool isInside)
+{
+ FeaturePtr aFeature = thePart->addFeature(FeaturesAPI_Thickness::ID());
+
+ ThicknessPtr aThickness (new FeaturesAPI_Thickness(aFeature, theBaseObject, theThickness, theFaces, isInside));
+ return aThickness;
+}
--- /dev/null
+// Copyright (C) 2017-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef FeaturesAPI_Thickness_H_
+#define FeaturesAPI_Thickness_H_
+
+#include "FeaturesAPI.h"
+
+#include <FeaturesPlugin_Thickness.h>
+
+#include <ModelHighAPI_Double.h>
+#include <ModelHighAPI_Interface.h>
+#include <ModelHighAPI_Macro.h>
+
+class ModelHighAPI_Selection;
+
+/// \class FeaturesAPI_Thickness
+/// \ingroup CPPHighAPI
+/// \brief Interface for Thickness feature.
+class FeaturesAPI_Thickness: public ModelHighAPI_Interface
+{
+public:
+ /// Constructor without values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Thickness(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Thickness(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const bool isInside);
+
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_Thickness(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const std::list<ModelHighAPI_Selection>& theFaces,
+ const bool isInside);
+
+ /// Destructor.
+ FEATURESAPI_EXPORT
+ virtual ~FeaturesAPI_Thickness();
+
+ INTERFACE_5(FeaturesPlugin_Thickness::ID(),
+
+ creationMethod, FeaturesPlugin_Thickness::CREATION_METHOD_ID(),
+ ModelAPI_AttributeString, /** Creation method */,
+
+ baseObject, FeaturesPlugin_Thickness::BASE_SHAPE_ID(),
+ ModelAPI_AttributeSelection, /** Base object */,
+
+ thicknessValue, FeaturesPlugin_Thickness::THICKNESS_VALUE_ID(),
+ ModelAPI_AttributeDouble, /** Value of the thickness */,
+
+ faces, FeaturesPlugin_Thickness::FACES_ID(),
+ ModelAPI_AttributeSelectionList, /** List of faces to remove in hollowed solid mode */,
+
+ isInside, FeaturesPlugin_Thickness::INSIDE_ID(),
+ ModelAPI_AttributeBoolean, /** Do thicken towards inside */)
+
+ /// Dump wrapped feature
+ FEATURESAPI_EXPORT
+ virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on the thickness object.
+typedef std::shared_ptr<FeaturesAPI_Thickness> ThicknessPtr;
+
+/// \ingroup CPPHighAPI
+/// \brief Create Thickness feature.
+FEATURESAPI_EXPORT
+ThicknessPtr addThickness(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const bool isInside = true);
+
+/// \ingroup CPPHighAPI
+/// \brief Create Thickness feature.
+FEATURESAPI_EXPORT
+ThicknessPtr addHollowedSolid(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const ModelHighAPI_Selection& theBaseObject,
+ const ModelHighAPI_Double& theThickness,
+ const std::list<ModelHighAPI_Selection>& theFaces,
+ const bool isInside = true);
+
+#endif // FeaturesAPI_Thickness_H_
#include "FeaturesAPI_NormalToFace.h"
#include "FeaturesAPI_MultiRotation.h"
#include "FeaturesAPI_MultiTranslation.h"
+ #include "FeaturesAPI_Offset.h"
#include "FeaturesAPI_Partition.h"
#include "FeaturesAPI_Pipe.h"
#include "FeaturesAPI_Loft.h"
+ #include "FeaturesAPI_Thickness.h"
#include "FeaturesAPI_Placement.h"
#include "FeaturesAPI_PointCloudOnFace.h"
#include "FeaturesAPI_Recover.h"
FeaturesPlugin_Partition.h
FeaturesPlugin_Pipe.h
FeaturesPlugin_Loft.h
+ FeaturesPlugin_Thickness.h
FeaturesPlugin_Placement.h
FeaturesPlugin_PointCloudOnFace.h
FeaturesPlugin_CompositeBoolean.h
FeaturesPlugin_Union.h
FeaturesPlugin_ValidatorTransform.h
FeaturesPlugin_Validators.h
+ FeaturesPlugin_Offset.h
FeaturesPlugin_RemoveSubShapes.h
FeaturesPlugin_Tools.h
FeaturesPlugin_Symmetry.h
FeaturesPlugin_Partition.cpp
FeaturesPlugin_Pipe.cpp
FeaturesPlugin_Loft.cpp
+ FeaturesPlugin_Thickness.cpp
FeaturesPlugin_Placement.cpp
FeaturesPlugin_PointCloudOnFace.cpp
FeaturesPlugin_CompositeBoolean.cpp
FeaturesPlugin_Union.cpp
FeaturesPlugin_ValidatorTransform.cpp
FeaturesPlugin_Validators.cpp
+ FeaturesPlugin_Offset.cpp
FeaturesPlugin_RemoveSubShapes.cpp
FeaturesPlugin_Tools.cpp
FeaturesPlugin_Symmetry.cpp
intersection_widget.xml
pipe_widget.xml
loft_widget.xml
+ thickness_widget.xml
+ offset_widget.xml
remove_subshapes_widget.xml
union_widget.xml
symmetry_widget.xml
--- /dev/null
+// Copyright (C) 2014-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "FeaturesPlugin_Offset.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAlgoAPI_Offset.h>
+#include <GeomAlgoAPI_Tools.h>
+
+//==================================================================================================
+FeaturesPlugin_Offset::FeaturesPlugin_Offset()
+{
+}
+
+//==================================================================================================
+void FeaturesPlugin_Offset::initAttributes()
+{
+ data()->addAttribute(CREATION_METHOD_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(OFFSET_VALUE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(PIPE_JOINT_ID(), ModelAPI_AttributeBoolean::typeId());
+ data()->addAttribute(FACES_ID(), ModelAPI_AttributeSelectionList::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PIPE_JOINT_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FACES_ID());
+}
+
+//==================================================================================================
+void FeaturesPlugin_Offset::execute()
+{
+ // Get base shape and sub-shapes list.
+ AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+ if (!aShapeAttrSelection.get()) {
+ return;
+ }
+
+ // Get base shape.
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ if (!aBaseShape.get()) {
+ return;
+ }
+
+ // Get offset value.
+ double anOffset = real(OFFSET_VALUE_ID())->value();
+
+ // Getting creation method.
+ std::string aCreationMethod = string(CREATION_METHOD_ID())->value();
+
+ // Perform total or partial offset
+ std::shared_ptr<GeomAlgoAPI_Offset> anOffsetAlgo;
+
+ if (aCreationMethod == CREATION_METHOD_EQUAL()) {
+ // total offset can have pipe or intersection joints
+ bool isPipeJoint = boolean(PIPE_JOINT_ID())->value();
+
+ anOffsetAlgo = std::shared_ptr<GeomAlgoAPI_Offset>
+ (new GeomAlgoAPI_Offset (aBaseShape, anOffset, isPipeJoint));
+ }
+ else {
+ // partial offset has faces argument
+ AttributeSelectionListPtr aFacesAttrList = selectionList(FACES_ID());
+ if (!aShapeAttrSelection.get() || !aFacesAttrList.get()) {
+ return;
+ }
+
+ ListOfShape aFaces;
+ for (int anIndex = 0; anIndex < aFacesAttrList->size(); ++anIndex) {
+ AttributeSelectionPtr aFaceAttrInList = aFacesAttrList->value(anIndex);
+ GeomShapePtr aFace = aFaceAttrInList->value();
+ if (!aFace.get()) {
+ return;
+ }
+ aFaces.push_back(aFace);
+ }
+
+ anOffsetAlgo = std::shared_ptr<GeomAlgoAPI_Offset>
+ (new GeomAlgoAPI_Offset (aBaseShape, aFaces, anOffset));
+ }
+
+ std::string anError;
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(anOffsetAlgo, getKind(), anError)) {
+ setError(anError);
+ return;
+ }
+
+ GeomShapePtr aResult = anOffsetAlgo->shape();
+
+ // Store result.
+ int anIndex = 0;
+ ResultBodyPtr aResultBody = document()->createBody(data(), anIndex);
+ aResultBody->storeModified(aBaseShape, aResult);
+ aResultBody->loadModifiedShapes(anOffsetAlgo, aBaseShape, GeomAPI_Shape::FACE);
+ aResultBody->loadGeneratedShapes(anOffsetAlgo, aBaseShape, GeomAPI_Shape::FACE);
+ setResult(aResultBody, anIndex);
+}
--- /dev/null
+// Copyright (C) 2014-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef FeaturesPlugin_Offset_H_
+#define FeaturesPlugin_Offset_H_
+
+#include "FeaturesPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class FeaturesPlugin_Offset
+/// \ingroup Plugins
+/// \brief Feature for offset.
+class FeaturesPlugin_Offset: public ModelAPI_Feature
+{
+public:
+ /// Use plugin manager for features creation
+ FeaturesPlugin_Offset();
+
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Offset3d");
+ return MY_ID;
+ }
+
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_ID()
+ {
+ static const std::string MY_CREATION_METHOD_ID("creation_method");
+ return MY_CREATION_METHOD_ID;
+ }
+
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_EQUAL()
+ {
+ static const std::string MY_CREATION_METHOD_EQUAL("offset_equal");
+ return MY_CREATION_METHOD_EQUAL;
+ }
+
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_PARTIAL()
+ {
+ static const std::string MY_CREATION_METHOD_PARTIAL("offset_partial");
+ return MY_CREATION_METHOD_PARTIAL;
+ }
+
+ /// Attribute name of base shape.
+ inline static const std::string& BASE_SHAPE_ID()
+ {
+ static const std::string MY_BASE_SHAPE_ID("base_shape");
+ return MY_BASE_SHAPE_ID;
+ }
+
+ /// Attribute name of offset value.
+ inline static const std::string& OFFSET_VALUE_ID()
+ {
+ static const std::string MY_OFFSET_VALUE_ID("offset_value");
+ return MY_OFFSET_VALUE_ID;
+ }
+
+ /// Attribute name of pipe/intersection joint bool flag.
+ inline static const std::string& PIPE_JOINT_ID()
+ {
+ static const std::string MY_PIPE_JOINT_ID("pipe_joint");
+ return MY_PIPE_JOINT_ID;
+ }
+
+ /// Attribute name of sub-faces to offset (for partial offset).
+ inline static const std::string& FACES_ID()
+ {
+ static const std::string MY_FACES_ID("faces_to_offset");
+ return MY_FACES_ID;
+ }
+
+
+ /// \return the kind of a feature.
+ FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = FeaturesPlugin_Offset::ID();
+ return MY_KIND;
+ }
+
+ /// Request for initialization of data model of the feature: adding all attributes.
+ FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Performs the algorithm and stores results it in the data structure.
+ FEATURESPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
#include <FeaturesPlugin_Partition.h>
#include <FeaturesPlugin_Pipe.h>
#include <FeaturesPlugin_Loft.h>
+#include <FeaturesPlugin_Thickness.h>
+#include <FeaturesPlugin_Offset.h>
#include <FeaturesPlugin_Placement.h>
#include <FeaturesPlugin_PointCloudOnFace.h>
#include <FeaturesPlugin_Recover.h>
new FeaturesPlugin_ValidatorExtrusionBoundaryFace);
aFactory->registerValidator("FeaturesPlugin_ValidatorBooleanSelection",
new FeaturesPlugin_ValidatorBooleanSelection);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorOffsetFacesSelection",
+ new FeaturesPlugin_ValidatorOffsetFacesSelection);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorThicknessSelection",
+ new FeaturesPlugin_ValidatorThicknessSelection);
aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection",
new FeaturesPlugin_ValidatorPartitionSelection);
aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesSelection",
return FeaturePtr(new FeaturesPlugin_Pipe);
} else if (theFeatureID == FeaturesPlugin_Loft::ID()) {
return FeaturePtr(new FeaturesPlugin_Loft);
+ } else if (theFeatureID == FeaturesPlugin_Thickness::ID()) {
+ return FeaturePtr(new FeaturesPlugin_Thickness);
} else if (theFeatureID == FeaturesPlugin_Placement::ID()) {
return FeaturePtr(new FeaturesPlugin_Placement);
} else if (theFeatureID == FeaturesPlugin_Recover::ID()) {
return FeaturePtr(new FeaturesPlugin_Symmetry);
} else if (theFeatureID == FeaturesPlugin_Scale::ID()) {
return FeaturePtr(new FeaturesPlugin_Scale);
+ } else if (theFeatureID == FeaturesPlugin_Offset::ID()) {
+ return FeaturePtr(new FeaturesPlugin_Offset);
} else if (theFeatureID == FeaturesPlugin_Sewing::ID()) {
return FeaturePtr(new FeaturesPlugin_Sewing);
} else if (theFeatureID == FeaturesPlugin_MultiTranslation::ID()) {
--- /dev/null
+// Copyright (C) 2014-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "FeaturesPlugin_Thickness.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAlgoAPI_Thickness.h>
+#include <GeomAlgoAPI_Tools.h>
+
+//==================================================================================================
+FeaturesPlugin_Thickness::FeaturesPlugin_Thickness()
+{
+}
+
+//==================================================================================================
+void FeaturesPlugin_Thickness::initAttributes()
+{
+ data()->addAttribute(CREATION_METHOD_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
+ data()->addAttribute(FACES_ID(), ModelAPI_AttributeSelectionList::typeId());
+ data()->addAttribute(THICKNESS_VALUE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(INSIDE_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FACES_ID());
+}
+
+//==================================================================================================
+void FeaturesPlugin_Thickness::execute()
+{
+ // Getting creation method.
+ std::string aCreationMethod = string(CREATION_METHOD_ID())->value();
+
+ // Get base shape
+ AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+ if (!aShapeAttrSelection.get()) {
+ return;
+ }
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ if (!aBaseShape.get()) {
+ return;
+ }
+
+ // Get thickness value.
+ double aThickness = real(THICKNESS_VALUE_ID())->value();
+
+ // Get thickening direction
+ bool isInside = boolean(INSIDE_ID())->value();
+
+ // Perform thickness
+ std::shared_ptr<GeomAlgoAPI_Thickness> aThicknessAlgo;
+
+ if (aCreationMethod == CREATION_METHOD_THICK()) {
+ aThicknessAlgo = std::shared_ptr<GeomAlgoAPI_Thickness>
+ (new GeomAlgoAPI_Thickness (aBaseShape, aThickness, isInside));
+ }
+ else {
+ // hollowed solid algorithm has faces argument
+ AttributeSelectionListPtr aFacesAttrList = selectionList(FACES_ID());
+ if (!aShapeAttrSelection.get() || !aFacesAttrList.get()) {
+ return;
+ }
+
+ ListOfShape aFaces;
+ for (int anIndex = 0; anIndex < aFacesAttrList->size(); ++anIndex) {
+ AttributeSelectionPtr aFaceAttrInList = aFacesAttrList->value(anIndex);
+ GeomShapePtr aFace = aFaceAttrInList->value();
+ if (!aFace.get()) {
+ return;
+ }
+ aFaces.push_back(aFace);
+ }
+
+ aThicknessAlgo = std::shared_ptr<GeomAlgoAPI_Thickness>
+ (new GeomAlgoAPI_Thickness (aBaseShape, aFaces, aThickness, isInside));
+ }
+
+ std::string anError;
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aThicknessAlgo, getKind(), anError)) {
+ setError(anError);
+ return;
+ }
+
+ GeomShapePtr aResult = aThicknessAlgo->shape();
+
+ // Store result.
+ int anIndex = 0;
+ ResultBodyPtr aResultBody = document()->createBody(data(), anIndex);
+ if (aCreationMethod == CREATION_METHOD_THICK()) {
+ aResultBody->storeGenerated(aBaseShape, aResult);
+ }
+ else {
+ aResultBody->storeModified(aBaseShape, aResult);
+ }
+ aResultBody->loadModifiedShapes(aThicknessAlgo, aBaseShape, GeomAPI_Shape::FACE);
+ aResultBody->loadGeneratedShapes(aThicknessAlgo, aBaseShape, GeomAPI_Shape::FACE);
+ aResultBody->loadGeneratedShapes(aThicknessAlgo, aBaseShape, GeomAPI_Shape::EDGE);
+ aResultBody->loadGeneratedShapes(aThicknessAlgo, aBaseShape, GeomAPI_Shape::VERTEX);
+ setResult(aResultBody, anIndex);
+}
+
+//==================================================================================================
+void FeaturesPlugin_Thickness::attributeChanged(const std::string& theID)
+{
+ if (theID == CREATION_METHOD_ID()) {
+ // clean base shape, as it has different type in different modes,
+ // so, it cannot be the same
+ AttributeSelectionPtr aBaseAttr = selection(BASE_SHAPE_ID());
+ AttributeSelectionListPtr aFaceAttr = selectionList(FACES_ID());
+ data()->blockSendAttributeUpdated(true, false);
+ aBaseAttr->reset();
+ aFaceAttr->clear(); // reset doesn't work for a list
+ data()->blockSendAttributeUpdated(false, false);
+ }
+ ModelAPI_Feature::attributeChanged(theID);
+}
--- /dev/null
+// Copyright (C) 2014-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef FeaturesPlugin_Thickness_H_
+#define FeaturesPlugin_Thickness_H_
+
+#include "FeaturesPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class FeaturesPlugin_Thickness
+/// \ingroup Plugins
+/// \brief Feature for thickness.
+class FeaturesPlugin_Thickness: public ModelAPI_Feature
+{
+public:
+ /// Use plugin manager for features creation
+ FeaturesPlugin_Thickness();
+
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Thickness");
+ return MY_ID;
+ }
+
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_ID()
+ {
+ static const std::string MY_CREATION_METHOD_ID("creation_method");
+ return MY_CREATION_METHOD_ID;
+ }
+
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_THICK()
+ {
+ static const std::string MY_CREATION_METHOD_THICK("thickness");
+ return MY_CREATION_METHOD_THICK;
+ }
+
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_HOLLOWED()
+ {
+ static const std::string MY_CREATION_METHOD_HOLLOWED("hollowed_solid");
+ return MY_CREATION_METHOD_HOLLOWED;
+ }
+
+ /// Attribute name of base shape.
+ inline static const std::string& BASE_SHAPE_ID()
+ {
+ static const std::string MY_BASE_SHAPE_ID("base_shape");
+ return MY_BASE_SHAPE_ID;
+ }
+
+ /// Attribute name of sub-faces to remove (for hollowed solid mode).
+ inline static const std::string& FACES_ID()
+ {
+ static const std::string MY_FACES_ID("faces_to_remove");
+ return MY_FACES_ID;
+ }
+
+ /// Attribute name of thickness value.
+ inline static const std::string& THICKNESS_VALUE_ID()
+ {
+ static const std::string MY_THICKNESS_VALUE_ID("thickness_value");
+ return MY_THICKNESS_VALUE_ID;
+ }
+
+ /// Attribute name of pipe/intersection joint bool flag.
+ inline static const std::string& INSIDE_ID()
+ {
+ static const std::string MY_INSIDE_ID("is_inside");
+ return MY_INSIDE_ID;
+ }
+
+
+ /// \return the kind of a feature.
+ FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = FeaturesPlugin_Thickness::ID();
+ return MY_KIND;
+ }
+
+ /// Request for initialization of data model of the feature: adding all attributes.
+ FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Performs the algorithm and stores results it in the data structure.
+ FEATURESPLUGIN_EXPORT virtual void execute();
+
+ /// Called on change of any argument-attribute of this object.
+ /// \param[in] theID identifier of changed attribute.
+ FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+};
+
+#endif
#include <GeomValidators_ShapeType.h>
#include <GeomAPI_DataMapOfShapeShape.h>
+#include <GeomAPI_IndexedMapOfShape.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_Pln.h>
return true;
}
+//=============================================================================================
+bool FeaturesPlugin_ValidatorOffsetFacesSelection::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ AttributeSelectionListPtr aSubShapesAttrList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if (!aSubShapesAttrList.get()) {
+ theError = "Error: This validator can only work with selection list in \"Offset\" feature.";
+ return false;
+ }
+
+ static const std::string aBaseShapeID = "base_shape";
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
+
+ if (!aShapeAttrSelection.get()) {
+ theError = "Error: Could not get \"%1\" attribute.";
+ theError.arg(aBaseShapeID);
+ return false;
+ }
+
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ ResultPtr aContext = aShapeAttrSelection->context();
+ if (!aContext.get()) {
+ theError = "Error: Empty context.";
+ return false;
+ }
+ if (!aBaseShape.get()) {
+ aBaseShape = aContext->shape();
+ }
+ if (!aBaseShape.get()) {
+ theError = "Error: Empty base shape.";
+ return false;
+ }
+
+ if (!aSubShapesAttrList->size()) {
+ theError = "Error: No faces selected.";
+ return false;
+ }
+
+ GeomAPI_IndexedMapOfShape aSubShapesMap (aBaseShape);
+ for (int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+ GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+ if (!aShapeToAdd.get()) {
+ theError = "Error: Wrong shape selected.";
+ return false;
+ }
+ if (!aSubShapesMap.FindIndex(aShapeToAdd)) {
+ theError = "Error: Only sub-shapes of selected shape are allowed for selection.";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//=============================================================================================
+bool FeaturesPlugin_ValidatorThicknessSelection::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ static const std::string aBaseShapeID = "base_shape";
+ static const std::string aCreationMethodID = "creation_method";
+ static const std::string aCreationMethodTH = "thickness";
+
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+
+ AttributeSelectionPtr aShapeAttrSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+ if (aShapeAttrSelection.get()) {
+ // 1. Check main objects type (depends on creation method)
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ ResultPtr aContext = aShapeAttrSelection->context();
+ if (!aContext.get()) {
+ theError = "Error: Empty context.";
+ return false;
+ }
+ if (!aBaseShape.get()) {
+ aBaseShape = aContext->shape();
+ }
+ if (!aBaseShape.get()) {
+ theError = "Error: Empty base shape.";
+ return false;
+ }
+
+ AttributeStringPtr aCreationMethodAttr = aFeature->string(aCreationMethodID);
+ if (aCreationMethodAttr->value() == aCreationMethodTH) {
+ // should be a face or a shell
+ return aBaseShape->isShell() || aBaseShape->isFace();
+ }
+
+ // shoud be a solid
+ return aBaseShape->isSolid();
+ }
+
+ // 2. Check faces selection
+ AttributeSelectionListPtr aSubShapesAttrList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if (!aSubShapesAttrList.get()) {
+ theError = "Error: This validator can only work with selection in \"Thickness\" feature.";
+ return false;
+ }
+
+ // base shape
+ aShapeAttrSelection = aFeature->selection(aBaseShapeID);
+
+ if (!aShapeAttrSelection.get()) {
+ theError = "Error: Could not get \"%1\" attribute.";
+ theError.arg(aBaseShapeID);
+ return false;
+ }
+
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ ResultPtr aContext = aShapeAttrSelection->context();
+ if (!aContext.get()) {
+ theError = "Error: Empty context.";
+ return false;
+ }
+ if (!aBaseShape.get()) {
+ aBaseShape = aContext->shape();
+ }
+ if (!aBaseShape.get()) {
+ theError = "Error: Empty base shape.";
+ return false;
+ }
+
+ if (!aSubShapesAttrList->size()) {
+ theError = "Error: No faces selected.";
+ return false;
+ }
+
+ GeomAPI_IndexedMapOfShape aSubShapesMap (aBaseShape);
+ for (int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+ GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+ if (!aShapeToAdd.get()) {
+ theError = "Error: Wrong shape selected.";
+ return false;
+ }
+ if (!aSubShapesMap.FindIndex(aShapeToAdd)) {
+ theError = "Error: Only sub-shapes of selected shape are allowed for selection.";
+ return false;
+ }
+ if (!aShapeToAdd->isFace()) {
+ theError = "Error: Only faces are allowed for selection.";
+ return false;
+ }
+ }
+
+ return true;
+}
+
//==================================================================================================
bool FeaturesPlugin_ValidatorPartitionSelection::isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const;
};
+/// \class FeaturesPlugin_ValidatorOffsetFacesSelection
+/// \ingroup Validators
+/// \brief Validates selection for "Offset" feature.
+class FeaturesPlugin_ValidatorOffsetFacesSelection: public ModelAPI_AttributeValidator
+{
+public:
+ /// \return True if the attribute is valid. It checks whether the selection
+ /// is acceptable for 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_ValidatorThicknessSelection
+/// \ingroup Validators
+/// \brief Validates selection for "Thickness" feature.
+class FeaturesPlugin_ValidatorThicknessSelection: public ModelAPI_AttributeValidator
+{
+public:
+ /// \return True if the attribute is valid. It checks whether the selection
+ /// is acceptable for 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.
<source>Normal to a face</source>
<translation>Normale d'une face</translation>
</message>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Thickness</source>
+ <translation>Épaisseur</translation>
+ </message>
<message>
<source>Partition</source>
<translation>Partition</translation>
</message>
</context>
+ <!-- Offset -->
+ <context>
+ <name>Offset3d</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Perform offset</source>
+ <translation>Effectuer des décalage</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:base_shape</name>
+ <message>
+ <source>Shape:</source>
+ <translation>Forme:</translation>
+ </message>
+ <message>
+ <source>Select a shape to offset.</source>
+ <translation>Sélectionnez une forme à décaler.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:offset_value</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:creation_method</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Partial offset</source>
+ <translation>Décalage partiel</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:pipe_joint</name>
+ <message>
+ <source>Join by pipes</source>
+ <translation>Rejoindre par des tuyaux</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:faces_to_offset</name>
+ <message>
+ <source>Faces to offset:</source>
+ <translation>Faces à décaler :</translation>
+ </message>
+ <message>
+ <source>Select faces of the main shape.</source>
+ <translation>Sélectionnez les faces de la forme principale.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Offset3d:faces_to_offset:FeaturesPlugin_ValidatorOffsetFacesSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ <message>
+ <source>Error: No faces selected.</source>
+ <translation>Erreur: Aucun face sélectionné.</translation>
+ </message>
+ </context>
+
+ <!-- Thickness -->
+ <context>
+ <name>Thickness</name>
+ <message>
+ <source>Thickness</source>
+ <translation>Épaisseur</translation>
+ </message>
+ <message>
+ <source>Make a thickness or a hollowed solid</source>
+ <translation>Réaliser une épaisseur ou un solide creux</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:creation_method</name>
+ <message>
+ <source>Thickness</source>
+ <translation>Épaisseur</translation>
+ </message>
+ <message>
+ <source>Hollowed Solid</source>
+ <translation>Solide évidé</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:base_shape</name>
+ <message>
+ <source>Face or Shell:</source>
+ <translation>Face ou Coque:</translation>
+ </message>
+ <message>
+ <source>Select a face or a shell.</source>
+ <translation>Sélectionnez une face ou une coque.</translation>
+ </message>
+ <message>
+ <source>Solid:</source>
+ <translation>Solide:</translation>
+ </message>
+ <message>
+ <source>Select a solid.</source>
+ <translation>Sélectionnez un solide.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:base_shape:FeaturesPlugin_ValidatorThicknessSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:faces_to_remove</name>
+ <message>
+ <source>Faces to remove:</source>
+ <translation>Faces à supprimer:</translation>
+ </message>
+ <message>
+ <source>Select faces of the main shape.</source>
+ <translation>Sélectionnez les faces de la forme principale.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:faces_to_remove:FeaturesPlugin_ValidatorThicknessSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ <message>
+ <source>Error: No faces selected.</source>
+ <translation>Erreur: Aucun face sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:thickness_value</name>
+ <message>
+ <source>Thickness</source>
+ <translation>Épaisseur</translation>
+ </message>
+ <message>
+ <source>Thickness value</source>
+ <translation>Valeur d'épaisseur</translation>
+ </message>
+ </context>
+ <context>
+ <name>Thickness:is_inside</name>
+ <message>
+ <source>Thicken towards the inside</source>
+ <translation>Épaissir vers l'intérieur</translation>
+ </message>
+ </context>
+
<!-- Partition -->
<context>
<name>Partition</name>
--- /dev/null
+# Copyright (C) 2018-2024 CEA, EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Box
+Box_1 = model.addBox(Part_1_doc, 200, 200, 200)
+Box_2 = model.addBox(Part_1_doc, 200, 200, 200)
+Box_3 = model.addBox(Part_1_doc, 200, 200, 200)
+
+### Create Shell
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+ model.selection("FACE", "Box_1_1/Front"),
+ model.selection("FACE", "Box_1_1/Left")])
+
+# Global offset (pipe joints)
+Offset_1 = model.addOffset(Part_1_doc, model.selection("SHELL", "Shell_1_1"), 70., True)
+
+# Global offset (intersection joints)
+Offset_2 = model.addOffset(Part_1_doc, model.selection("SOLID", "Box_2_1"), 60., False)
+
+# Partial offset
+Offset_3 = model.addOffsetPartial(Part_1_doc,
+ model.selection("SOLID", "Box_3_1"),
+ 50.,
+ [model.selection("FACE", "Box_3_1/Top"),
+ model.selection("FACE", "Box_3_1/Back"),
+ model.selection("FACE", "Box_3_1/Right")])
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+#test Offset_1
+model.testNbResults(Offset_1, 1)
+model.testNbSubResults(Offset_1, [0])
+model.testNbSubShapes(Offset_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(Offset_1, GeomAPI_Shape.FACE, [7])
+model.testNbSubShapes(Offset_1, GeomAPI_Shape.EDGE, [27])
+model.testNbSubShapes(Offset_1, GeomAPI_Shape.VERTEX, [54])
+model.testResultsAreas(Offset_1, [193670.3477])
+
+#test Offset_2
+model.testNbResults(Offset_1, 1)
+model.testNbSubResults(Offset_2, [0])
+model.testNbSubShapes(Offset_2, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Offset_2, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Offset_2, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Offset_2, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Offset_2, [32768000])
+
+#test Offset_3
+model.testNbResults(Offset_3, 1)
+model.testNbSubResults(Offset_3, [0])
+model.testNbSubShapes(Offset_3, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Offset_3, GeomAPI_Shape.FACE, [6])
+model.testNbSubShapes(Offset_3, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(Offset_3, GeomAPI_Shape.VERTEX, [48])
+model.testResultsVolumes(Offset_3, [15625000])
--- /dev/null
+# Copyright (C) 2018-2024 CEA, EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Box
+Box_1 = model.addBox(Part_1_doc, 200, 200, 200)
+Box_2 = model.addBox(Part_1_doc, 200, 200, 200)
+Box_3 = model.addBox(Part_1_doc, 200, 200, 200)
+
+### Create Shell
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+ model.selection("FACE", "Box_1_1/Front"),
+ model.selection("FACE", "Box_1_1/Left")])
+Shell_2 = model.addShell(Part_1_doc, [model.selection("FACE", "Box_2_1/Top"),
+ model.selection("FACE", "Box_2_1/Front"),
+ model.selection("FACE", "Box_2_1/Left")])
+
+# Thickness mode 1: thicken a shell/face
+Thickness_1 = model.addThickness(Part_1_doc, model.selection("SHELL", "Shell_1_1"), 30, False)
+Thickness_2 = model.addThickness(Part_1_doc, model.selection("SHELL", "Shell_2_1"), 30, True)
+
+# Thickness mode 2: hollowed solid
+Thickness_3 = model.addHollowedSolid(Part_1_doc,
+ model.selection("SOLID", "Box_3_1"),
+ 40,
+ [model.selection("FACE", "Box_3_1/Top"),
+ model.selection("FACE", "Box_3_1/Left")],
+ False)
+
+model.end()
+
+from GeomAPI import GeomAPI_Shape
+
+#test Thickness_1
+model.testNbResults(Thickness_1, 1)
+model.testNbSubResults(Thickness_1, [0])
+model.testNbSubShapes(Thickness_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Thickness_1, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Thickness_1, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Thickness_1, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Thickness_1, [4167000])
+
+#test Thickness_2
+model.testNbResults(Thickness_1, 1)
+model.testNbSubResults(Thickness_2, [0])
+model.testNbSubShapes(Thickness_2, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Thickness_2, GeomAPI_Shape.FACE, [12])
+model.testNbSubShapes(Thickness_2, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Thickness_2, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Thickness_2, [3087000])
+
+#test Thickness_3
+model.testNbResults(Thickness_3, 1)
+model.testNbSubResults(Thickness_3, [0])
+model.testNbSubShapes(Thickness_3, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Thickness_3, GeomAPI_Shape.FACE, [10])
+model.testNbSubShapes(Thickness_3, GeomAPI_Shape.EDGE, [48])
+model.testNbSubShapes(Thickness_3, GeomAPI_Shape.VERTEX, [96])
+model.testResultsVolumes(Thickness_3, [8128000])
loftFeature.rst
measurementFeature.rst
normalToFaceFeature.rst
+ offsetFeature.rst
pipeFeature.rst
placementFeature.rst
pointCoordinatesFeature.rst
rotationFeature.rst
sewingFeature.rst
symmetryFeature.rst
+ thicknessFeature.rst
transformationFeature.rst
translationFeature.rst
--- /dev/null
+
+ .. _tui_offset:
+
+offset
+======
+
+.. literalinclude:: examples/offset.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/offset.py>`
--- /dev/null
+
+ .. _tui_thickness:
+
+thickness
+=========
+
+.. literalinclude:: examples/thickness.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/thickness.py>`
--- /dev/null
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Box
+Box_1 = model.addBox(Part_1_doc, 200, 200, 200)
+Box_2 = model.addBox(Part_1_doc, 200, 200, 200)
+
+### Create Shell
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+ model.selection("FACE", "Box_1_1/Front"),
+ model.selection("FACE", "Box_1_1/Left")])
+
+# Offset of the whole shape, pipe joints (isPipeJoint = True)
+Offset_1 = model.addOffset(Part_1_doc, model.selection("SHELL", "Shell_1_1"), 70., True)
+
+# Partial offset. Negative offset value means offset in direction, opposite to normale.
+Offset_2 = model.addOffsetPartial(Part_1_doc,
+ model.selection("SOLID", "Box_2_1"),
+ -50.,
+ [model.selection("FACE", "Box_2_1/Top")])
+
+model.end()
--- /dev/null
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+
+### Create Part
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+### Create Box
+Box_1 = model.addBox(Part_1_doc, 200, 200, 200)
+Box_2 = model.addBox(Part_1_doc, 200, 200, 200)
+
+### Create Shell
+Shell_1 = model.addShell(Part_1_doc, [model.selection("FACE", "Box_1_1/Top"),
+ model.selection("FACE", "Box_1_1/Front"),
+ model.selection("FACE", "Box_1_1/Left")])
+
+# Thickness mode 1: thicken a shell/face
+# isInside = False, so thicken towards outside
+Thickness_1 = model.addThickness(Part_1_doc, model.selection("SHELL", "Shell_1_1"), 30, False)
+
+# Thickness mode 2: hollowed solid
+# isInside = True, so thicken towards inside
+Thickness_2 = model.addHollowedSolid(Part_1_doc,
+ model.selection("SOLID", "Box_2_1"),
+ 40,
+ [model.selection("FACE", "Box_2_1/Top"),
+ model.selection("FACE", "Box_2_1/Left")],
+ True)
+
+model.end()
--- /dev/null
+.. |offset.icon| image:: images/offset3D.png
+
+Offset
+======
+
+**Offset** feature translates each point of the **Shape**
+along a local normal by the given **Offset distance**
+(signed number, negative value means inner offset).
+
+To create an Offset in the active part:
+
+#. select in the Main Menu *Features - > Offset* item or
+#. click |offset.icon| **Offset** button in the toolbar
+
+Two Offset algorithms are:
+
+.. figure:: images/offset3D.png
+ :align: left
+ :height: 24px
+
+offset the whole shape by the same value
+
+.. figure:: images/offset3D_partial.png
+ :align: left
+ :height: 24px
+
+offset selected faces by the given value, other faces by zero.
+
+--------------------------------------------------------------------------------
+
+Offset the whole shape by the same value
+----------------------------------------
+
+.. figure:: images/offsetPropertyPanel.png
+ :align: center
+
+ Offset by the same value property panel
+
+Input fields:
+
+- **Shape** defines the base shape (solid, shell or face) selected in 3D OCC viewer or object browser;
+- **Distance** defines the offset value. Negative value meaning inner offset;
+- **Join by pipes** check box defines the mode of filling the gaps between translated
+ adjacent surfaces:
+
+ - if <b>Join by pipes</b> is activated, they are filled with pipes;
+ - else the surfaces are extended and intersected, so that sharp edges are preserved;
+
+**TUI Command**:
+
+.. py:function:: model.addOffset(Part_doc, shape, dist, isPipeJoint)
+
+ :param part: The current part object.
+ :param object: A shape in format *model.selection(TYPE, shape)*.
+ :param real: Offset distance value.
+ :param boolean: Join by pipes/intersection flag.
+ :return: Created object.
+
+Result
+""""""
+
+Result of offset of a box. Join by pipes activated.
+
+.. figure:: images/offset_result.png
+ :align: center
+
+ Offset of a box
+
+**See Also** a sample TUI Script of :ref:`tui_offset` operation.
+
+
+Offset selected faces by the given value, other faces by zero
+-------------------------------------------------------------
+
+.. figure:: images/offsetPartialPropertyPanel.png
+ :align: center
+
+ Partial Offset property panel
+
+Input fields:
+
+- **Shape** defines the base shape (solid, shell or face) selected in 3D OCC viewer or object browser;
+- **Distance** defines the offset value. Negative value meaning inner offset;
+- **Faces to offset** defines the faces of the base shape, which should be offset;
+
+*Note*: In Partial Offset mode gaps are allways filled by intersection.
+
+**TUI Command**:
+
+.. py:function:: model.addOffsetPartial(Part_doc, shape, dist, faces)
+
+ :param part: The current part object.
+ :param object: A shape in format *model.selection(TYPE, shape)*.
+ :param real: Offset distance value.
+ :param objects: Faces of the shape in format *[model.selection(TYPE, shape), ...]*.
+ :return: Created object.
+
+Result
+""""""
+
+Result of partial offset of a box. Top and front faces selected.
+
+.. figure:: images/offset_partial_result.png
+ :align: center
+
+ Partial offset of a box
+
+**See Also** a sample TUI Script of :ref:`tui_offset` operation.
--- /dev/null
+.. |thickness.icon| image:: images/thickness.png
+
+Thickness
+=========
+
+To create a **Thickness** or a **Hollowed Solid** in the active part:
+
+#. select in the Main Menu *Features - > Thickness* item or
+#. click |thickness.icon| **Thickness** button in the toolbar
+
+Two Thickness algorithms are:
+
+.. figure:: images/thickness.png
+ :align: left
+ :height: 24px
+
+make a thickness of a shell or a face
+
+.. figure:: images/thickness2.png
+ :align: left
+ :height: 24px
+
+make a hollowed solid
+
+--------------------------------------------------------------------------------
+
+Thickness of a shell or a face
+------------------------------
+
+.. figure:: images/thicknessPropertyPanel.png
+ :align: center
+
+ Thickness property panel
+
+Input fields:
+
+- **Shape** defines the base shape (shell or face) selected in 3D OCC viewer or object browser;
+- **Distance** defines the thickness value. Negative values are not allowed;
+- **Thicken towards the inside** check box defines the thickening direction;
+
+**TUI Command**:
+
+.. py:function:: model.addThickness(Part_doc, shape, dist, isInside)
+
+ :param part: The current part object.
+ :param object: A shape in format *model.selection(TYPE, shape)*.
+ :param real: Thickness value.
+ :param boolean: Inside/outside direction flag.
+ :return: Created object.
+
+Result
+""""""
+
+Result of thickness of a shell.
+
+.. figure:: images/thickness_result.png
+ :align: center
+
+ Thickness of a shell
+
+**See Also** a sample TUI Script of :ref:`tui_thickness` operation.
+
+
+Hollowed solid
+--------------
+
+.. figure:: images/thicknessPropertyPanel2.png
+ :align: center
+
+ Hollowed Solid property panel
+
+Input fields:
+
+- **Shape** defines the base shape (solid) selected in 3D OCC viewer or object browser;
+- **Distance** defines the thickness value. Negative values are not allowed;
+- **Faces to remove** defines the faces of the base solid, where the hole is done;
+- **Thicken towards the inside** check box defines the thickening direction;
+
+**TUI Command**:
+
+.. py:function:: model.addHollowedSolid(Part_doc, shape, dist, faces, isInside)
+
+ :param part: The current part object.
+ :param object: A shape in format *model.selection("SOLID", shape)*.
+ :param real: Thickness value.
+ :param objects: Faces of the solid in format *[model.selection("FACE", shape), ...]*.
+ :param boolean: Inside/outside direction flag.
+ :return: Created object.
+
+Result
+""""""
+
+Result of hollowed solid of a box. Left and front faces selected.
+
+.. figure:: images/thickness_result2.png
+ :align: center
+
+ Hollowed solid of a box
+
+**See Also** a sample TUI Script of :ref:`tui_thickness` operation.
--- /dev/null
+<source>
+ <shape_selector id="base_shape"
+ label="Shape:"
+ tooltip="Select a shape to offset."
+ shape_types="objects"
+ concealment="true">
+ <validator id="GeomValidators_ShapeType" parameters="face,shell,solid"/>
+ </shape_selector>
+ <doublevalue id="offset_value"
+ label="Offset"
+ step="1.0"
+ default="1.0"
+ icon="icons/Features/dimension_v.png"
+ tooltip="Offset"/>
+ <toolbox id="creation_method">
+ <box id="offset_equal"
+ title="Offset"
+ icon="icons/Features/offset3D.png">
+ <boolvalue id="pipe_joint" label="Join by pipes" default="true" tooltip="Join by pipes"/>
+ </box>
+ <box id="offset_partial"
+ title="Partial offset"
+ icon="icons/Features/offset3D_partial.png">
+ <multi_selector id="faces_to_offset"
+ label="Faces to offset:"
+ tooltip="Select faces of the main shape."
+ shape_types="faces"
+ clear_in_neutral_point="false">
+ <validator id="FeaturesPlugin_ValidatorOffsetFacesSelection"/>
+ </multi_selector>
+ </box>
+ </toolbox>
+</source>
icon="icons/Features/scale.png" helpfile="transformationFeature.html">
<source path="scale_widget.xml"/>
</feature>
+ <feature id="Offset3d" title="Offset" tooltip="Perform offset"
+ icon="icons/Features/offset3D.png" helpfile="offsetFeature.html">
+ <source path="offset_widget.xml"/>
+ </feature>
</group>
<group id="Extrusion">
<feature id="Extrusion" title="Extrusion" tooltip="Create a solid by extrusion of a face"
icon="icons/Features/loft.png" helpfile="loftFeature.html">
<source path="loft_widget.xml"/>
</feature>
+ <feature id="Thickness" title="Thickness" tooltip="Make a thickness or a hollowed solid"
+ icon="icons/Features/thickness.png" helpfile="thicknessFeature.html">
+ <source path="thickness_widget.xml"/>
+ </feature>
</group>
<group id="Boolean" toolbar="yes">
<feature id="Cut" title="Cut" tooltip="Perform boolean cut operation with objects"
Test23885.py
TestNormalToFace.py
TestLoft.py
+ TestOffset.py
+ TestThickness.py
TestSewing_Manifold.py
TestSewing_NonManifold.py
TestSewing_Groups.py
--- /dev/null
+<source>
+ <toolbox id="creation_method">
+ <box id="thickness"
+ title="Thickness"
+ icon="icons/Features/thickness.png">
+ <shape_selector id="base_shape"
+ label="Face or Shell:"
+ tooltip="Select a face or a shell."
+ shape_types="objects"
+ concealment="true">
+ <validator id="GeomValidators_ShapeType" parameters="face,shell,solid"/>
+ <validator id="FeaturesPlugin_ValidatorThicknessSelection"/>
+ </shape_selector>
+ </box>
+ <box id="hollowed_solid"
+ title="Hollowed Solid"
+ icon="icons/Features/thickness2.png">
+ <shape_selector id="base_shape"
+ label="Solid:"
+ tooltip="Select a solid."
+ shape_types="objects"
+ concealment="true">
+ <validator id="GeomValidators_ShapeType" parameters="face,shell,solid"/>
+ <validator id="FeaturesPlugin_ValidatorThicknessSelection"/>
+ </shape_selector>
+ <multi_selector id="faces_to_remove"
+ label="Faces to remove:"
+ tooltip="Select faces of the main shape."
+ shape_types="faces"
+ clear_in_neutral_point="false">
+ <validator id="FeaturesPlugin_ValidatorThicknessSelection"/>
+ </multi_selector>
+ </box>
+ </toolbox>
+ <doublevalue id="thickness_value"
+ label="Thickness"
+ step="1.0"
+ default="1.0"
+ min="1e-07"
+ icon="icons/Features/dimension_v.png"
+ tooltip="Thickness value"/>
+ <boolvalue id="is_inside"
+ label="Thicken towards the inside" default="false" tooltip="Thicken towards the inside"/>
+</source>
GeomAlgoAPI_CurveBuilder.h
GeomAlgoAPI_NExplode.h
GeomAlgoAPI_Offset.h
+ GeomAlgoAPI_Thickness.h
GeomAlgoAPI_SolidClassifier.h
GeomAlgoAPI_MapShapesAndAncestors.h
GeomAlgoAPI_Projection.h
GeomAlgoAPI_NormalToFace.h
GeomAlgoAPI_Tube.h
GeomAlgoAPI_ShapeInfo.h
- GeomAlgoAPI_CanonicalRecognition.h
+ GeomAlgoAPI_CanonicalRecognition.h
GeomAlgoAPI_GlueFaces.h
GeomAlgoAPI_LimitTolerance.h
GeomAlgoAPI_Utils.h
GeomAlgoAPI_CurveBuilder.cpp
GeomAlgoAPI_NExplode.cpp
GeomAlgoAPI_Offset.cpp
+ GeomAlgoAPI_Thickness.cpp
GeomAlgoAPI_SolidClassifier.cpp
GeomAlgoAPI_MapShapesAndAncestors.cpp
GeomAlgoAPI_Projection.cpp
GeomAlgoAPI_NormalToFace.cpp
GeomAlgoAPI_Tube.cpp
GeomAlgoAPI_ShapeInfo.cpp
- GeomAlgoAPI_CanonicalRecognition.cpp
+ GeomAlgoAPI_CanonicalRecognition.cpp
GeomAlgoAPI_GlueFaces.cpp
- GeomAlgoAPI_CanonicalRecognition.cpp
GeomAlgoAPI_LimitTolerance.cpp
GeomAlgoAPI_Utils.cpp
GeomAlgoAPI_NonPlanarFace.cpp
#include <BRepBuilderAPI_MakeShape.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepGProp.hxx>
+#include <BRepOffset_MakeOffset.hxx>
#include <GProp_GProps.hxx>
#include <Precision.hxx>
#include <TopExp_Explorer.hxx>
} else if(myBuilderType == OCCT_BOPAlgo_Builder) {
BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
aList = aBOPBuilder->Generated(theOldShape->impl<TopoDS_Shape>());
+ } else if(myBuilderType == OCCT_BRepOffset_MakeOffset) {
+ BRepOffset_MakeOffset* aMakeOffset = implPtr<BRepOffset_MakeOffset>();
+ aList = aMakeOffset->Generated(theOldShape->impl<TopoDS_Shape>());
}
for(TopTools_ListIteratorOfListOfShape anIt(aList); anIt.More(); anIt.Next()) {
GeomShapePtr aShape(new GeomAPI_Shape());
} else if(myBuilderType == OCCT_BOPAlgo_Builder) {
BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
aList = aBOPBuilder->Modified(theOldShape->impl<TopoDS_Shape>());
+ } else if(myBuilderType == OCCT_BRepOffset_MakeOffset) {
+ BRepOffset_MakeOffset* aMakeOffset = implPtr<BRepOffset_MakeOffset>();
+ try {
+ aList = aMakeOffset->Modified(theOldShape->impl<TopoDS_Shape>());
+ } catch(Standard_NoSuchObject const&) {
+ }
}
for(TopTools_ListIteratorOfListOfShape anIt(aList); anIt.More(); anIt.Next()) {
GeomShapePtr aShape(new GeomAPI_Shape());
} else if(myBuilderType == OCCT_BOPAlgo_Builder) {
BOPAlgo_Builder* aBOPBuilder = implPtr<BOPAlgo_Builder>();
isDeleted = aBOPBuilder->IsDeleted(theOldShape->impl<TopoDS_Shape>()) == Standard_True;
+ } else if(myBuilderType == OCCT_BRepOffset_MakeOffset) {
+ BRepOffset_MakeOffset* aMakeOffset = implPtr<BRepOffset_MakeOffset>();
+ isDeleted = aMakeOffset->IsDeleted(theOldShape->impl<TopoDS_Shape>()) == Standard_True;
}
return isDeleted;
myShape->setImpl(new TopoDS_Shape(implPtr<BOPAlgo_Builder>()->Shape()));
break;
}
+ case OCCT_BRepOffset_MakeOffset: {
+ myDone = implPtr<BRepOffset_MakeOffset>()->IsDone() == Standard_True;
+ myShape.reset(new GeomAPI_Shape());
+ myShape->setImpl(new TopoDS_Shape(implPtr<BRepOffset_MakeOffset>()->Shape()));
+ break;
+ }
default:
break;
}
enum BuilderType {
Unknown,
OCCT_BRepBuilderAPI_MakeShape,
- OCCT_BOPAlgo_Builder
+ OCCT_BOPAlgo_Builder,
+ OCCT_BRepOffset_MakeOffset
};
public:
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomShapePtr& theShape,
- const double theOffsetValue)
+ const double theOffsetValue)
{
- build(theShape, theOffsetValue);
+ buildSimple(theShape, theOffsetValue);
}
-void GeomAlgoAPI_Offset::build(const GeomShapePtr& theShape, const double theOffsetValue)
+GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomShapePtr& theShape,
+ const double theOffsetValue,
+ const bool isPipeJoint)
+{
+ buildByJoin(theShape, theOffsetValue, isPipeJoint);
+}
+
+GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theOffsetValue)
+{
+ buildPartial(theShape, theFaces, theOffsetValue);
+}
+
+GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomPlanePtr& thePlane,
+ const GeomShapePtr& theEdgeOrWire,
+ const double theOffsetValue,
+ const GeomAlgoAPI_OffsetJoint theJoint,
+ const bool theIsApprox)
+{
+ build2d(thePlane, theEdgeOrWire, theOffsetValue, theJoint, theIsApprox);
+}
+
+void GeomAlgoAPI_Offset::generated(const GeomShapePtr theOldShape,
+ ListOfShape& theNewShapes)
+{
+ try {
+ GeomAlgoAPI_MakeShape::generated(theOldShape, theNewShapes);
+ } catch(...) {
+ // nothing is generated
+ }
+}
+
+void GeomAlgoAPI_Offset::buildSimple(const GeomShapePtr& theShape,
+ const double theOffsetValue)
{
BRepOffsetAPI_MakeOffsetShape* anOffsetAlgo = new BRepOffsetAPI_MakeOffsetShape;
anOffsetAlgo->PerformBySimple(theShape->impl<TopoDS_Shape>(), theOffsetValue);
}
}
-void GeomAlgoAPI_Offset::generated(const GeomShapePtr theOldShape,
- ListOfShape& theNewShapes)
+void GeomAlgoAPI_Offset::buildByJoin(const GeomShapePtr& theShape,
+ const double theOffsetValue,
+ const bool isPipeJoint)
{
- try {
- GeomAlgoAPI_MakeShape::generated(theOldShape, theNewShapes);
- } catch(...) {
- // nothing is generated
+ Standard_Real aTol = Precision::Confusion();
+ BRepOffset_Mode aMode = BRepOffset_Skin;
+ Standard_Boolean anIntersection = Standard_False;
+ Standard_Boolean aSelfInter = Standard_False;
+
+ BRepOffsetAPI_MakeOffsetShape* anOffsetAlgo = new BRepOffsetAPI_MakeOffsetShape;
+ anOffsetAlgo->PerformByJoin(theShape->impl<TopoDS_Shape>(),
+ theOffsetValue,
+ aTol,
+ aMode,
+ anIntersection,
+ aSelfInter,
+ isPipeJoint ? GeomAbs_Arc : GeomAbs_Intersection);
+ setImpl(anOffsetAlgo);
+ setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+ if (anOffsetAlgo->IsDone()) {
+ const TopoDS_Shape& aResult = anOffsetAlgo->Shape();
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
}
}
-GeomAlgoAPI_Offset::GeomAlgoAPI_Offset(const GeomPlanePtr& thePlane,
- const GeomShapePtr& theEdgeOrWire,
- const double theOffsetValue,
- const GeomAlgoAPI_OffsetJoint theJoint,
- const bool theIsApprox)
+void GeomAlgoAPI_Offset::buildPartial(const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theOffsetValue)
+{
+ if (theFaces.empty())
+ return;
+
+ TopoDS_Shape aShapeBase = theShape->impl<TopoDS_Shape>();
+
+ Standard_Real aTol = Precision::Confusion();
+ BRepOffset_Mode aMode = BRepOffset_Skin;
+ Standard_Boolean anIntersection = Standard_False;
+ Standard_Boolean aSelfInter = Standard_False;
+
+ BRepOffset_MakeOffset* aMakeOffset = new BRepOffset_MakeOffset;
+ aMakeOffset->Initialize(aShapeBase,
+ theOffsetValue, // set offset on all faces to anOffset
+ aTol,
+ aMode,
+ anIntersection,
+ aSelfInter,
+ GeomAbs_Intersection,
+ Standard_False);
+
+ // put selected faces into a map
+ TopTools_MapOfShape aMapFaces;
+ for (ListOfShape::const_iterator anIt = theFaces.begin();
+ anIt != theFaces.end(); ++anIt) {
+ if ((*anIt)->isFace())
+ aMapFaces.Add((*anIt)->impl<TopoDS_Shape>());
+ }
+
+ // set offset on non-selected faces to zero
+ TopExp_Explorer anExp (aShapeBase, TopAbs_FACE);
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &aFace = anExp.Current();
+ if (!aMapFaces.Contains(aFace)) {
+ aMakeOffset->SetOffsetOnFace(TopoDS::Face(aFace), 0.0);
+ }
+ }
+
+ // perform offset operation
+ aMakeOffset->MakeOffsetShape();
+
+ setImpl(aMakeOffset);
+ setBuilderType(OCCT_BRepOffset_MakeOffset);
+
+ if (aMakeOffset->IsDone()) {
+ const TopoDS_Shape& aResult = aMakeOffset->Shape();
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
+ }
+}
+
+void GeomAlgoAPI_Offset::build2d(const GeomPlanePtr& thePlane,
+ const GeomShapePtr& theEdgeOrWire,
+ const double theOffsetValue,
+ const GeomAlgoAPI_OffsetJoint theJoint,
+ const bool theIsApprox)
{
// 1. Make wire from edge, if need
TopoDS_Wire aWire;
class GeomAlgoAPI_Offset : public GeomAlgoAPI_MakeShape
{
public:
- /// \brief Construct offset.
+ /// \brief Perform simple offset.
+ /// \param[in] theShape base shape
+ /// \param[in] theOffsetValue offset distance, it can be negative
GEOMALGOAPI_EXPORT GeomAlgoAPI_Offset(const GeomShapePtr& theShape,
const double theOffsetValue);
- /// \brief Perform the offset algorithm on the plane
+ /// \brief Perform 3d offset algorithm
+ /// \param[in] theShape base shape
+ /// \param[in] theOffsetValue offset distance, it can be negative
+ /// \param[in] isPipeJoint type of joint of faces (pipes or intersections)
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Offset
+ (const GeomShapePtr& theShape,
+ const double theOffsetValue,
+ const bool isPipeJoint);
+
+ /// \brief Perform partial 3d offset algorithm
+ /// \param[in] theShape base shape
+ /// \param[in] theFaces list of faces to be offset
+ /// \param[in] theOffsetValue offset distance for selected faces, it can be negative
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Offset
+ (const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theOffsetValue);
+
+ /// \brief Perform 2d offset algorithm on the plane
/// \param[in] thePlane base plane for all offsets
/// \param[in] theEdgesOrWire base shapes
/// \param[in] theOffsetValue offset distance, it can be negative
GEOMALGOAPI_EXPORT virtual void generated(const GeomShapePtr theOldShape,
ListOfShape& theNewShapes);
-
private:
- /// \brief Perform offset operation
- void build(const GeomShapePtr& theShape, const double theOffsetValue);
+ /// \brief Perform simple offset operation
+ void buildSimple(const GeomShapePtr& theShape,
+ const double theOffsetValue);
+
+ /// \brief Perform 3d offset algorithm by join
+ void buildByJoin(const GeomShapePtr& theShape,
+ const double theOffsetValue,
+ const bool isPipeJoint);
+
+ /// \brief Perform partial 3d offset algorithm
+ void buildPartial(const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theOffsetValue);
+
+ /// \brief Perform 2d offset algorithm on the plane
+ void build2d(const std::shared_ptr<GeomAPI_Pln>& thePlane,
+ const GeomShapePtr& theEdgeOrWire,
+ const double theOffsetValue,
+ const GeomAlgoAPI_OffsetJoint theJoint = GeomAlgoAPI_OffsetJoint::KeepDistance,
+ const bool theIsApprox = false);
};
#endif
--- /dev/null
+// Copyright (C) 2019-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "GeomAlgoAPI_Thickness.h"
+
+#include <GeomAPI_Pln.h>
+
+#include <BRepClass3d_SolidClassifier.hxx>
+#include <BRepOffsetAPI_MakeThickSolid.hxx>
+#include <BRepOffset_MakeOffset.hxx>
+
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+static GeomShapePtr convert(const TopoDS_Shape& theShape)
+{
+ GeomShapePtr aNewShape(new GeomAPI_Shape);
+ aNewShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(theShape));
+ return aNewShape;
+}
+
+GeomAlgoAPI_Thickness::GeomAlgoAPI_Thickness(const GeomShapePtr& theShape,
+ const double theThickness,
+ const bool isInside)
+{
+ buildThickening(theShape, theThickness, isInside);
+}
+
+GeomAlgoAPI_Thickness::GeomAlgoAPI_Thickness(const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theThickness,
+ const bool isInside)
+{
+ buildHollowedSolid(theShape, theFaces, theThickness, isInside);
+}
+
+void GeomAlgoAPI_Thickness::generated(const GeomShapePtr theOldShape,
+ ListOfShape& theNewShapes)
+{
+ GeomAlgoAPI_MakeShape::generated(theOldShape, theNewShapes);
+
+ MapModified::iterator aFound = myGenerated.find(theOldShape);
+ if (aFound != myGenerated.end())
+ theNewShapes.insert(theNewShapes.end(),
+ aFound->second.begin(), aFound->second.end());
+}
+
+void GeomAlgoAPI_Thickness::buildThickening(const GeomShapePtr& theShape,
+ const double theThickness,
+ const bool isInside)
+{
+ Standard_Real aTol = Precision::Confusion();
+ if (theThickness < aTol) {
+ myError = "The thickness value is Too small or negative";
+ return;
+ }
+
+ Standard_Real anOffset = theThickness;
+ if (isInside)
+ anOffset = -anOffset;
+
+ const TopoDS_Shape& aShapeBase = theShape->impl<TopoDS_Shape>();
+ const TopAbs_ShapeEnum aType = aShapeBase.ShapeType();
+
+ if (aType != TopAbs_FACE && aType != TopAbs_SHELL) {
+ myError = "The base shape for thickening should be a face or a shell";
+ return;
+ }
+
+ BRepClass3d_SolidClassifier aClassifier(aShapeBase);
+ aClassifier.PerformInfinitePoint(Precision::Confusion());
+ if (aClassifier.State()==TopAbs_IN) {
+ // If the generated pipe faces normals are oriented towards the inside,
+ // the offset is negative, so that the thickening is still towards outside
+ anOffset = -anOffset;
+ }
+
+ Standard_Boolean anIntersection = Standard_False;
+ Standard_Boolean aSelfInter = Standard_False;
+ Standard_Boolean isThickening = Standard_True;
+
+ BRepOffset_MakeOffset* aMakeOffset =
+ new BRepOffset_MakeOffset(aShapeBase,
+ anOffset,
+ aTol,
+ BRepOffset_Skin,
+ anIntersection,
+ aSelfInter,
+ GeomAbs_Intersection,
+ isThickening);
+
+ setImpl(aMakeOffset);
+ setBuilderType(OCCT_BRepOffset_MakeOffset);
+
+ if (aMakeOffset->IsDone()) {
+ TopoDS_Shape aResult = aMakeOffset->Shape();
+
+ // Control the solid orientation. This is mostly done to fix a bug in case
+ // of extrusion of a circle. The built solid is then badly oriented.
+ BRepClass3d_SolidClassifier anotherClassifier(aResult);
+ anotherClassifier.PerformInfinitePoint(Precision::Confusion());
+ if (anotherClassifier.State() == TopAbs_IN) {
+ aResult.Reverse();
+ }
+
+ std::shared_ptr<GeomAPI_Shape> aShape (new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
+
+ // History for ThickShell is incomplete (OCCT bug 33844)
+ // Here we try to add generated walls (FACE from EDGE or VERTEX)
+
+ // 1. Gather all generated/modified/initial faces in a map
+ // (for that faces we don't need to adjust history).
+ // Collect also edges and vertices of initial shape in a separate map.
+ TopTools_MapOfShape aFacesMap;
+ TopTools_MapOfShape anInitialMap;
+ TopTools_ListOfShape aList, aListTmp;
+ {
+ TopExp_Explorer anExp (aShapeBase, TopAbs_FACE);
+ for (; anExp.More(); anExp.Next()) {
+ TopoDS_Shape aFace = anExp.Current();
+ aList.Append(aFace);
+
+ aListTmp = aMakeOffset->Modified(aFace);
+ aList.Append(aListTmp);
+ aListTmp = aMakeOffset->Generated(aFace);
+ aList.Append(aListTmp);
+ }
+ }
+ {
+ TopExp_Explorer anExp (aShapeBase, TopAbs_EDGE);
+ for (; anExp.More(); anExp.Next()) {
+ TopoDS_Shape anEdge = anExp.Current();
+ anInitialMap.Add(anEdge);
+
+ aListTmp = aMakeOffset->Modified(anEdge);
+ aList.Append(aListTmp);
+ aListTmp = aMakeOffset->Generated(anEdge);
+ aList.Append(aListTmp);
+ }
+ }
+ {
+ TopExp_Explorer anExp (aShapeBase, TopAbs_VERTEX);
+ for (; anExp.More(); anExp.Next()) {
+ TopoDS_Shape aVertex = anExp.Current();
+ anInitialMap.Add(aVertex);
+
+ aListTmp = aMakeOffset->Modified(aVertex);
+ aList.Append(aListTmp);
+ aListTmp = aMakeOffset->Generated(aVertex);
+ aList.Append(aListTmp);
+ }
+ }
+ TopTools_ListIteratorOfListOfShape anIt (aList);
+ for (; anIt.More(); anIt.Next()) {
+ TopoDS_Shape aSh = anIt.Value();
+ if (aSh.ShapeType() == TopAbs_FACE) {
+ aFacesMap.Add(aSh);
+ }
+ }
+
+ // 2. Explode result shape into faces, try to construct new
+ // history for the faces, that are not in the map.
+ TopExp_Explorer anExp (aResult, TopAbs_FACE);
+ for (; anExp.More(); anExp.Next()) {
+ TopoDS_Shape aFace = anExp.Current();
+ if (!aFacesMap.Contains(aFace)) {
+ bool isFound = false;
+ // a. Try to find initial edge in this face
+ TopExp_Explorer anExpE (aFace, TopAbs_EDGE);
+ for (; anExpE.More() && !isFound; anExpE.Next()) {
+ TopoDS_Shape anEdge = anExpE.Current();
+ if (anInitialMap.Contains(anEdge)) {
+ myGenerated[convert(anEdge)].push_back(convert(aFace));
+ isFound = true;
+ }
+ }
+ if (!isFound) {
+ // b. Try to find initial vertex in this face
+ TopExp_Explorer anExpV (aFace, TopAbs_VERTEX);
+ for (; anExpV.More() && !isFound; anExpV.Next()) {
+ TopoDS_Shape aVertex = anExpV.Current();
+ if (anInitialMap.Contains(aVertex)) {
+ myGenerated[convert(aVertex)].push_back(convert(aFace));
+ isFound = true;
+ }
+ }
+ }
+ }
+ }
+ // END: history adjustment
+ }
+}
+
+void GeomAlgoAPI_Thickness::buildHollowedSolid(const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theThickness,
+ const bool isInside)
+{
+ if (theFaces.empty())
+ return;
+
+ Standard_Real aTol = Precision::Confusion();
+ if (theThickness < aTol) {
+ myError = "The thickness value is Too small or negative";
+ return;
+ }
+
+ Standard_Real anOffset = theThickness;
+ if (isInside)
+ anOffset = -anOffset;
+
+ //TopoDS_Shape aShapeBase = theShape->impl<TopoDS_Shape>();
+ const TopoDS_Shape& aShapeBase = theShape->impl<TopoDS_Shape>();
+ const TopAbs_ShapeEnum aType = aShapeBase.ShapeType();
+
+ if (aType != TopAbs_SOLID) {
+ myError = "The base shape for hollowed solid creation should be a solid";
+ return;
+ }
+
+ // put selected faces into a list
+ TopTools_ListOfShape aFacesToRm;
+ for (ListOfShape::const_iterator anIt = theFaces.begin();
+ anIt != theFaces.end(); ++anIt) {
+ if ((*anIt)->isFace())
+ aFacesToRm.Append((*anIt)->impl<TopoDS_Shape>());
+ }
+
+ Standard_Boolean anIntersection = Standard_False;
+ Standard_Boolean aSelfInter = Standard_False;
+
+ // Create a hollowed solid.
+ BRepOffsetAPI_MakeThickSolid* aMkSolid = new BRepOffsetAPI_MakeThickSolid();
+ aMkSolid->MakeThickSolidByJoin(aShapeBase,
+ aFacesToRm,
+ anOffset,
+ aTol,
+ BRepOffset_Skin,
+ anIntersection,
+ aSelfInter,
+ GeomAbs_Intersection);
+
+ setImpl(aMkSolid);
+ setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
+
+ if (aMkSolid->IsDone()) {
+ const TopoDS_Shape& aResult = aMkSolid->Shape();
+ std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aResult));
+ setShape(aShape);
+ setDone(true);
+ }
+}
--- /dev/null
+// Copyright (C) 2019-2024 CEA, EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef GeomAlgoAPI_Thickness_H_
+#define GeomAlgoAPI_Thickness_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_MakeShape.h>
+
+/// \class GeomAlgoAPI_Thickness
+/// \ingroup DataAlgo
+/// \brief Perform Thickness or Hollowed Solid algorithm for the shape
+class GeomAlgoAPI_Thickness : public GeomAlgoAPI_MakeShape
+{
+ typedef std::map<GeomShapePtr, ListOfShape, GeomAPI_Shape::Comparator> MapModified;
+
+public:
+ /// \brief Perform thickening algorithm
+ /// \param[in] theShape base shape (Face or Shell)
+ /// \param[in] theThickness thickness of the resulting solid
+ /// \param[in] isInside if true, the thickness is applied towards inside
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Thickness
+ (const GeomShapePtr& theShape,
+ const double theThickness,
+ const bool isInside);
+
+ /// \brief Perform hollowed solid algorithm
+ /// \param[in] theShape base shape (Solid)
+ /// \param[in] theFaces the list of faces to be removed from the result
+ /// \param[in] theThickness thickness of the resulting solid
+ /// \param[in] isInside if true, the thickness is applied towards inside
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Thickness
+ (const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theThickness,
+ const bool isInside);
+
+ /// \return the list of shapes generated from the shape \a theShape.
+ /// \param[in] theOldShape base shape.
+ /// \param[out] theNewShapes shapes generated from \a theShape. Does not cleared!
+ GEOMALGOAPI_EXPORT virtual void generated(const GeomShapePtr theOldShape,
+ ListOfShape& theNewShapes);
+
+private:
+ /// \brief Perform thickening algorithm
+ void buildThickening(const GeomShapePtr& theShape,
+ const double theThickness,
+ const bool isInside);
+
+ /// \brief Perform hollowed solid algorithm
+ void buildHollowedSolid(const GeomShapePtr& theShape,
+ const ListOfShape& theFaces,
+ const double theThickness,
+ const bool isInside);
+
+private:
+ MapModified myGenerated;
+};
+
+#endif
from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse
from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse
from FeaturesAPI import addPipe, addLoft
+from FeaturesAPI import addOffset, addOffsetPartial, addThickness, addHollowedSolid
from FeaturesAPI import addCut, addFuse, addCommon, addSmash, addSplit
from FeaturesAPI import addIntersection, addPartition, addUnion, addRemoveSubShapes
from FeaturesAPI import addRecover
<parameter name="Features/Intersection" value=""/>
<parameter name="Features/LimitTolerance" value=""/>
<parameter name="Features/Loft" value=""/>
+ <parameter name="Features/Offset3d" value=""/>
<parameter name="Features/Partition" value=""/>
<parameter name="Features/Pipe" value=""/>
<parameter name="Features/Recover" value=""/>
<parameter name="Features/SketchCopy" value=""/>
<parameter name="Features/Smash" value=""/>
<parameter name="Features/Split" value=""/>
+ <parameter name="Features/Thickness" value=""/>
<parameter name="File/Export/Part" value=""/>
<parameter name="File/Export/PartSet" value=""/>
<parameter name="File/Export/Shape" value=""/>
}
}
},
+ "Offset3d": {
+ "iconPath": "%SHAPER_ROOT_DIR%/share/salome/resources/shaper/icons/Features/offset3D.png",
+ "langDependentAssets": {
+ "en": {
+ "name": "Offset (3D)",
+ "tooltip": "Offset face or shell"
+ },
+ "fr": {
+ "name": "Offset (3D)",
+ "tooltip": "Face ou coque décalée"
+ }
+ }
+ },
"Partition": {
"iconPath": "%SHAPER_ROOT_DIR%/share/salome/resources/shaper/icons/Features/partition.png",
"langDependentAssets": {
"tooltip": "Effectuer l'opération booléenne division avec des objets"
}
}
+ },
+ "Thickness": {
+ "iconPath": "%SHAPER_ROOT_DIR%/share/salome/resources/shaper/icons/Features/thickness.png",
+ "langDependentAssets": {
+ "en": {
+ "name": "Thickness (3D)",
+ "tooltip": "Thicken faces"
+ },
+ "fr": {
+ "name": "Thickness (3D)",
+ "tooltip": "Épaissir les visages"
+ }
+ }
}
}
},
#
"""
- TestOffset.py
+ TestOffset1.py
Unit test of SketchPlugin_Offset class
SketchPlugin_Offset