From: cg246364 Date: Mon, 30 Aug 2021 06:41:48 +0000 (+0200) Subject: CEA : Lot2 - Normal to a face X-Git-Tag: V9_8_0a1~18^2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Fcgt%2FNormalToFace;p=modules%2Fshaper.git CEA : Lot2 - Normal to a face --- diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index 9cb86e10b..6cd9ba368 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -32,6 +32,7 @@ SET(PROJECT_HEADERS FeaturesAPI_Fillet.h FeaturesAPI_Intersection.h FeaturesAPI_Measurement.h + FeaturesAPI_NormalToFace.h FeaturesAPI_MultiRotation.h FeaturesAPI_MultiTranslation.h FeaturesAPI_Partition.h @@ -68,6 +69,7 @@ SET(PROJECT_SOURCES FeaturesAPI_Fillet.cpp FeaturesAPI_Intersection.cpp FeaturesAPI_Measurement.cpp + FeaturesAPI_NormalToFace.cpp FeaturesAPI_MultiRotation.cpp FeaturesAPI_MultiTranslation.cpp FeaturesAPI_Partition.cpp diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index 01804317a..d9fa7c0b5 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -63,6 +63,7 @@ %shared_ptr(FeaturesAPI_BooleanSmash) %shared_ptr(FeaturesAPI_BooleanFill) %shared_ptr(FeaturesAPI_Chamfer) +%shared_ptr(FeaturesAPI_NormalToFace) %shared_ptr(FeaturesAPI_Extrusion) %shared_ptr(FeaturesAPI_ExtrusionBoolean) %shared_ptr(FeaturesAPI_ExtrusionCut) @@ -212,6 +213,7 @@ %include "FeaturesAPI_Fillet.h" %include "FeaturesAPI_Intersection.h" %include "FeaturesAPI_Measurement.h" +%include "FeaturesAPI_NormalToFace.h" %include "FeaturesAPI_MultiRotation.h" %include "FeaturesAPI_MultiTranslation.h" %include "FeaturesAPI_Partition.h" diff --git a/src/FeaturesAPI/FeaturesAPI_NormalToFace.cpp b/src/FeaturesAPI/FeaturesAPI_NormalToFace.cpp new file mode 100644 index 000000000..0dd67e05e --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_NormalToFace.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "FeaturesAPI_NormalToFace.h" + +#include +#include +#include + +//================================================================================================= +FeaturesAPI_NormalToFace::FeaturesAPI_NormalToFace( + const std::shared_ptr& theFeature) + : ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================= +FeaturesAPI_NormalToFace::FeaturesAPI_NormalToFace( + const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionalPoint) +:ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(theBaseFace, myfaceSelected); + fillAttribute(theOptionalPoint, myvertexSelected); + feature()->string(FeaturesPlugin_NormalToFace::VERTEX_OPTION_ID())->setValue("true"); + execute(); + } +} + +//================================================================================================= +FeaturesAPI_NormalToFace::FeaturesAPI_NormalToFace( + const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theBaseFace) +:ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(theBaseFace, myfaceSelected); + feature()->string(FeaturesPlugin_NormalToFace::VERTEX_OPTION_ID())->setValue(""); + execute(); + } +} + +//================================================================================================= +FeaturesAPI_NormalToFace::~FeaturesAPI_NormalToFace() +{ +} + +//================================================================================================= +void FeaturesAPI_NormalToFace::dump(ModelHighAPI_Dumper& theDumper) const +{ + FeaturePtr aBase = feature(); + const std::string& aDocName = theDumper.name(aBase->document()); + + AttributeSelectionPtr anAttrObject; + anAttrObject = aBase->selection(FeaturesPlugin_NormalToFace::FACE_SELECTED_ID()); + + theDumper << aBase << " = model.getNormal(" << aDocName << ", " << anAttrObject; + + if (!aBase->string(FeaturesPlugin_NormalToFace::VERTEX_OPTION_ID())->value().empty()) { + + AttributeSelectionPtr anAttrVertex = + aBase->selection(FeaturesPlugin_NormalToFace::VERTEX_SELECTED_ID()); + + theDumper << ", " << anAttrVertex; + } + + theDumper << ")" << std::endl; +} + +//================================================================================================== +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionalPoint) +{ + + FeaturePtr aFeature = thePart->addFeature(FeaturesPlugin_NormalToFace::ID()); + NormalPtr aNormalToface; + aNormalToface.reset(new FeaturesAPI_NormalToFace(aFeature, theBaseFace, theOptionalPoint)); + + return aNormalToface; +} + +//================================================================================================= +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace) +{ + + FeaturePtr aFeature = thePart->addFeature(FeaturesPlugin_NormalToFace::ID()); + NormalPtr aNormalToface; + aNormalToface.reset(new FeaturesAPI_NormalToFace(aFeature, theBaseFace)); + + return aNormalToface; +} + diff --git a/src/FeaturesAPI/FeaturesAPI_NormalToFace.h b/src/FeaturesAPI/FeaturesAPI_NormalToFace.h new file mode 100644 index 000000000..da0719b06 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_NormalToFace.h @@ -0,0 +1,93 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef FeaturesAPI_NormalToFace_H_ +#define FeaturesAPI_NormalToFace_H_ + +#include "FeaturesAPI.h" + +#include + +#include +#include + + +class ModelHighAPI_Selection; + +/// \class FeaturesAPI_NormalToFace +/// \ingroup CPPHighAPI +/// \brief Interface for NormalToface feature. +class FeaturesAPI_NormalToFace: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_NormalToFace(const std::shared_ptr& theFeature); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_NormalToFace(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionalPoint); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_NormalToFace(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theBaseFace); + + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_NormalToFace(); + + INTERFACE_3(FeaturesPlugin_NormalToFace::ID(), + faceSelected, FeaturesPlugin_NormalToFace::FACE_SELECTED_ID(), + ModelAPI_AttributeSelection, /** base face */, + vertexSelected, FeaturesPlugin_NormalToFace::VERTEX_SELECTED_ID(), + ModelAPI_AttributeSelection, /** vertex */, + vertexOption, FeaturesPlugin_NormalToFace::VERTEX_OPTION_ID(), + ModelAPI_AttributeString, /** use a vertex */) + + /// Dump wrapped feature + FEATURESAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; + +}; + +/// Pointer on the NormalToface object. +typedef std::shared_ptr NormalPtr; + +/// \ingroup CPPHighAPI +/// \brief Create normal to a face feature +/// \param thePart the part +/// \param theBaseFace the selected face +/// \param theOptionalPoint the selected point +FEATURESAPI_EXPORT +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionalPoint); + +/// \ingroup CPPHighAPI +/// \brief Create normal to a face feature +/// \param thePart the part +/// \param theBaseFace the selected face +FEATURESAPI_EXPORT +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace); + +#endif // FeaturesAPI_NormalToFace_H_ diff --git a/src/FeaturesAPI/FeaturesAPI_swig.h b/src/FeaturesAPI/FeaturesAPI_swig.h index ce4a8887e..ede8f2c11 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -35,6 +35,7 @@ #include "FeaturesAPI_Fillet.h" #include "FeaturesAPI_Intersection.h" #include "FeaturesAPI_Measurement.h" + #include "FeaturesAPI_NormalToFace.h" #include "FeaturesAPI_MultiRotation.h" #include "FeaturesAPI_MultiTranslation.h" #include "FeaturesAPI_Partition.h" diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 91dee176f..e3f25e81d 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -72,6 +72,8 @@ SET(PROJECT_HEADERS FeaturesPlugin_BoundingBox.h FeaturesPlugin_BoundingBoxBase.h FeaturesPlugin_InspectBoundingBox.h + FeaturesPlugin_NormalToFace.h + FeaturesPlugin_InspectNormalToFace.h ) SET(PROJECT_SOURCES @@ -124,6 +126,8 @@ SET(PROJECT_SOURCES FeaturesPlugin_BoundingBox.cpp FeaturesPlugin_BoundingBoxBase.cpp FeaturesPlugin_InspectBoundingBox.cpp + FeaturesPlugin_NormalToFace.cpp + FeaturesPlugin_InspectNormalToFace.cpp ) SET(XML_RESOURCES @@ -164,6 +168,8 @@ SET(XML_RESOURCES geometry_calculation_widget.xml bounding_box_widget.xml create_bounding_box_widget.xml + normal_to_face_widget.xml + create_normal_to_face_widget.xml ) SET(TEXT_RESOURCES diff --git a/src/FeaturesPlugin/FeaturesPlugin_InspectNormalToFace.cpp b/src/FeaturesPlugin/FeaturesPlugin_InspectNormalToFace.cpp new file mode 100644 index 000000000..7cf17a3a2 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_InspectNormalToFace.cpp @@ -0,0 +1,165 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "FeaturesPlugin_InspectNormalToFace.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +//================================================================================================= +FeaturesPlugin_InspectNormalToFace::FeaturesPlugin_InspectNormalToFace() {} + +//================================================================================================= +void FeaturesPlugin_InspectNormalToFace::initAttributes() +{ + // attribute for object selected + data()->addAttribute(FACE_SELECTED_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(VERTEX_SELECTED_ID(), ModelAPI_AttributeSelection::typeId()); + // attributes for result message and values + data()->addAttribute(CREATENORMAL_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(VERTEX_OPTION_ID(), ModelAPI_AttributeString::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERTEX_SELECTED_ID()); + +} + +//================================================================================================= +void FeaturesPlugin_InspectNormalToFace::execute() +{ + AttributeSelectionPtr aSelectionFace = selection(FACE_SELECTED_ID()); + AttributeSelectionPtr aSelectionPoint = selection(VERTEX_SELECTED_ID()); + + GeomShapePtr aShape; + GeomShapePtr aShapePoint; + if (!string(VERTEX_OPTION_ID())->value().empty()) { + if (aSelectionPoint && aSelectionPoint->isInitialized()) { + aShapePoint = aSelectionPoint->value(); + if (!aShapePoint && aSelectionPoint->context()) + aShapePoint = aSelectionPoint->context()->shape(); + } + } + + if (aSelectionFace && aSelectionFace->isInitialized()) { + aShape = aSelectionFace->value(); + if (!aShape && aSelectionFace->context()) + aShape = aSelectionFace->context()->shape(); + } + + if (aShape) { + std::string aError; + std::shared_ptr theNormal(new GeomAPI_Edge); + if (!GeomAlgoAPI_NormalToFace::normal(aShape, + aShapePoint, + theNormal, + aError)) + setError("Error in bounding box calculation :" + aError); + + GeomDirPtr theDir; + std::shared_ptr aPnt = theNormal->lastPoint(); + if (theNormal.get()) { + if (theNormal->isLine()) { + theDir = theNormal->line()->direction(); + } + } + aPnt->translate(theDir, 100); + + std::shared_ptr anEdge = + GeomAlgoAPI_EdgeBuilder::line(theNormal->firstPoint(), aPnt); + + ResultConstructionPtr aConstr = document()->createConstruction(data()); + aConstr->setInfinite(true); + aConstr->setShape(anEdge); + setResult(aConstr); + } + + if (boolean(CREATENORMAL_ID())->value()) { + if (!myCreateFeature.get()) + createNormal(); + updateNormal(); + } else { + if (myCreateFeature.get()) { + myCreateFeature->eraseResults(); + SessionPtr aSession = ModelAPI_Session::get(); + DocumentPtr aDoc = aSession->activeDocument(); + aDoc->removeFeature(myCreateFeature); + myCreateFeature.reset(); + } + } +} + +//================================================================================================= +void FeaturesPlugin_InspectNormalToFace::attributeChanged(const std::string& theID) +{ + if (theID == FACE_SELECTED_ID()) { + if (myCreateFeature.get()) + updateNormal(); + } +} + +//================================================================================================= +void FeaturesPlugin_InspectNormalToFace::createNormal() +{ + SessionPtr aSession = ModelAPI_Session::get(); + + DocumentPtr aDoc = aSession->activeDocument(); + + if (aDoc.get()) { + myCreateFeature = aDoc->addFeature(FeaturesPlugin_NormalToFace::ID()); + } +} + +//================================================================================================= +void FeaturesPlugin_InspectNormalToFace::updateNormal() +{ + myCreateFeature->selection(FeaturesPlugin_NormalToFace::FACE_SELECTED_ID()) + ->setValue(selection(FACE_SELECTED_ID())->context() , + selection(FACE_SELECTED_ID())->value()); + + myCreateFeature->string(FeaturesPlugin_NormalToFace::VERTEX_OPTION_ID()) + ->setValue(string(VERTEX_OPTION_ID())->value()); + + if (!string(VERTEX_OPTION_ID())->value().empty()) { + myCreateFeature->selection(FeaturesPlugin_NormalToFace::VERTEX_SELECTED_ID()) + ->setValue(selection(VERTEX_SELECTED_ID())->context() , + selection(VERTEX_SELECTED_ID())->value()); + } + + myCreateFeature->execute(); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_InspectNormalToFace.h b/src/FeaturesPlugin/FeaturesPlugin_InspectNormalToFace.h new file mode 100644 index 000000000..014c5c613 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_InspectNormalToFace.h @@ -0,0 +1,103 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef FeaturesPlugin_InspectNormalToFace_H_ +#define FeaturesPlugin_InspectNormalToFace_H_ + +#include "FeaturesPlugin.h" +#include + +#include +#include + +/// \class FeaturesPlugin_InspectNormalToFace +/// \ingroup Plugins +/// \brief Feature to view the normal to face + +class FeaturesPlugin_InspectNormalToFace : public ModelAPI_Feature +{ +public: + /// Normal to face macro kind. + inline static const std::string& ID() + { + static const std::string MY_ID("NormalMacro"); + return MY_ID; + } + + /// Attribute name for face selected. + inline static const std::string& FACE_SELECTED_ID() + { + static const std::string MY_FACE_SELECTED_ID("face"); + return MY_FACE_SELECTED_ID; + } + + /// Attribute name for vertex selected. + inline static const std::string& VERTEX_SELECTED_ID() + { + static const std::string MY_VERTEX_SELECTED_ID("vertex"); + return MY_VERTEX_SELECTED_ID; + } + + /// Attribute name for checkbox create box. + inline static const std::string& CREATENORMAL_ID() + { + static const std::string MY_CREATENORMAL_ID("createnormal"); + return MY_CREATENORMAL_ID; + } + + /// Attribute name of vertex option. + inline static const std::string& VERTEX_OPTION_ID() + { + static const std::string MY_VERTEX_OPTION_ID("vertex_option"); + return MY_VERTEX_OPTION_ID; + } + + /// \return the kind of a feature. + virtual const std::string& getKind() + { + return ID(); + } + + /// Performs the algorithm and stores results it in the data structure. + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Reimplemented from ModelAPI_Feature::isMacro(). Returns true. + FEATURESPLUGIN_EXPORT virtual bool isMacro() const { return true; } + + /// Use plugin manager for features creation + FeaturesPlugin_InspectNormalToFace(); + + private: + /// Create normal in feature + void createNormal(); + /// Update normal in feature + void updateNormal(); + /// Feature to create normal + FeaturePtr myCreateFeature; + +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.cpp b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.cpp new file mode 100644 index 000000000..862707655 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "FeaturesPlugin_NormalToFace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//================================================================================================= +FeaturesPlugin_NormalToFace::FeaturesPlugin_NormalToFace() +{ +} + +//================================================================================================= +void FeaturesPlugin_NormalToFace::initAttributes() +{ + // attribute for object selected + data()->addAttribute(FACE_SELECTED_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(VERTEX_SELECTED_ID(), ModelAPI_AttributeSelection::typeId()); + + // attributes for result message and values + data()->addAttribute(VERTEX_OPTION_ID(), ModelAPI_AttributeString::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERTEX_SELECTED_ID()); +} + +//================================================================================================= +void FeaturesPlugin_NormalToFace::attributeChanged(const std::string& theID) +{ +} + +//================================================================================================= +void FeaturesPlugin_NormalToFace::execute() +{ + + AttributeSelectionPtr aSelectionFace = selection(FACE_SELECTED_ID()); + AttributeSelectionPtr aSelectionPoint = selection(VERTEX_SELECTED_ID()); + + GeomShapePtr aShape; + GeomShapePtr aShapePoint; + if (!string(VERTEX_OPTION_ID())->value().empty()) { + if (aSelectionPoint && aSelectionPoint->isInitialized()) { + aShapePoint = aSelectionPoint->value(); + if (!aShapePoint && aSelectionPoint->context()) + aShapePoint = aSelectionPoint->context()->shape(); + } + } + + if (aSelectionFace && aSelectionFace->isInitialized()) { + aShape = aSelectionFace->value(); + if (!aShape && aSelectionFace->context()) + aShape = aSelectionFace->context()->shape(); + } + + if (aShape) { + std::string aError; + std::shared_ptr theNormal(new GeomAPI_Edge); + if (!GeomAlgoAPI_NormalToFace::normal(aShape, + aShapePoint, + theNormal, + aError)) + setError("Error in bounding box calculation :" + aError); + + GeomDirPtr theDir; + std::shared_ptr aPnt = theNormal->lastPoint(); + if (theNormal.get()) { + if (theNormal->isLine()) { + theDir = theNormal->line()->direction(); + } + } + aPnt->translate(theDir, 100); + + std::shared_ptr anEdge = + GeomAlgoAPI_EdgeBuilder::line(theNormal->firstPoint(), + aPnt); + + ResultConstructionPtr aConstr = document()->createConstruction(data()); + aConstr->setInfinite(true); + aConstr->setShape(anEdge); + setResult(aConstr); + } +} + + diff --git a/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.h b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.h new file mode 100644 index 000000000..0c62694c1 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.h @@ -0,0 +1,84 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef FeaturesPlugin_NormalToFace_H_ +#define FeaturesPlugin_NormalToFace_H_ + +#include "FeaturesPlugin.h" +#include + +#include +#include + +/// \class FeaturesPlugin_NormalToFace +/// \ingroup Plugins +/// \brief Persistence feature to construct normal to face +class FeaturesPlugin_NormalToFace : public ModelAPI_Feature +{ +public: + /// Normal to face kind. + inline static const std::string& ID() + { + static const std::string MY_ID("Normal"); + return MY_ID; + } + + /// Attribute name for face selected. + inline static const std::string& FACE_SELECTED_ID() + { + static const std::string MY_FACE_ID("face"); + return MY_FACE_ID; + } + + /// Attribute name for vertex selected. + inline static const std::string& VERTEX_SELECTED_ID() + { + static const std::string MY_VERTEX_SELECTED_ID("vertex"); + return MY_VERTEX_SELECTED_ID; + } + + /// Attribute name of vertex option. + inline static const std::string& VERTEX_OPTION_ID() + { + static const std::string MY_VERTEX_OPTION_ID("vertex_option"); + return MY_VERTEX_OPTION_ID; + } + + /// \return the kind of a feature. + virtual const std::string& getKind() + { + return ID(); + } + + /// Performs the algorithm and stores results it in the data structure. + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Called on change of any argument-attribute of this object + /// \param theID identifier of changed attribute + FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Use plugin manager for features creation + FeaturesPlugin_NormalToFace(); + +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 20121610e..3d00700d6 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -34,11 +34,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -209,6 +211,10 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_InspectBoundingBox); } else if (theFeatureID == FeaturesPlugin_BoundingBox::ID()) { return FeaturePtr(new FeaturesPlugin_BoundingBox); + } else if (theFeatureID == FeaturesPlugin_InspectNormalToFace::ID()) { + return FeaturePtr(new FeaturesPlugin_InspectNormalToFace); + } else if (theFeatureID == FeaturesPlugin_NormalToFace::ID()) { + return FeaturePtr(new FeaturesPlugin_NormalToFace); } diff --git a/src/FeaturesPlugin/Test/TestNormalToFace.py b/src/FeaturesPlugin/Test/TestNormalToFace.py new file mode 100644 index 000000000..51ed2424c --- /dev/null +++ b/src/FeaturesPlugin/Test/TestNormalToFace.py @@ -0,0 +1,77 @@ +# Copyright (C) 2014-2021 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 +# + +""" + Unit test of ... +""" +#========================================================================= +# Initialization of the test +#========================================================================= + + +import os +import math + +from ModelAPI import * +from salome.shaper import model + + +__updated__ = "2020-11-12" + +#========================================================================= +# Initialization of the test +#========================================================================= +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, 10, 10, 10) +model.do() + +#========================================================================= +# Test 1. Create a normal to a face with only a face +#========================================================================= +Normal_1 = model.getNormal(Part_1_doc, model.selection("FACE", "Box_1_1/Top")) +model.do() + +#========================================================================= +# Test 2. Create a normal to a face with a face and a vertex +#========================================================================= +Normal_2 = model.getNormal(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]")) +model.do() + +model.end() + +assert (len(Normal_1.results()) > 0) +assert(Normal_1.feature().error() == "") +anAxisResult = modelAPI_ResultConstruction(Normal_1.feature().firstResult()) +assert (anAxisResult is not None) + +assert (len(Normal_2.results()) > 0) +assert(Normal_2.feature().error() == "") +anAxisResult = modelAPI_ResultConstruction(Normal_2.feature().firstResult()) +assert (anAxisResult is not None) + +#========================================================================= +# End of test +#========================================================================= diff --git a/src/FeaturesPlugin/create_normal_to_face_widget.xml b/src/FeaturesPlugin/create_normal_to_face_widget.xml new file mode 100644 index 000000000..82ee3be95 --- /dev/null +++ b/src/FeaturesPlugin/create_normal_to_face_widget.xml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/src/FeaturesPlugin/doc/FeaturesPlugin.rst b/src/FeaturesPlugin/doc/FeaturesPlugin.rst index 34e8fea42..6fc8177bd 100644 --- a/src/FeaturesPlugin/doc/FeaturesPlugin.rst +++ b/src/FeaturesPlugin/doc/FeaturesPlugin.rst @@ -26,6 +26,7 @@ Features plug-in provides a set of common topological operations. It implements importResultFeature.rst linearCopyFeature.rst measurementFeature.rst + normalToFaceFeature.rst pipeFeature.rst placementFeature.rst pointCoordinatesFeature.rst diff --git a/src/FeaturesPlugin/doc/TUI_normalToFaceFeature.rst b/src/FeaturesPlugin/doc/TUI_normalToFaceFeature.rst new file mode 100644 index 000000000..196cebf1d --- /dev/null +++ b/src/FeaturesPlugin/doc/TUI_normalToFaceFeature.rst @@ -0,0 +1,22 @@ + + .. _tui_create_normal_to_face: + +Create normal to a face +======================= + +.. literalinclude:: examples/create_normal_to_face.py + :linenos: + :language: python + +:download:`Download this script ` + + .. _tui_create_normal_to_face_at_vertex: + +Create normal to a face at vertex +================================= + +.. literalinclude:: examples/create_normal_to_face_at_vertex.py + :linenos: + :language: python + +:download:`Download this script ` diff --git a/src/FeaturesPlugin/doc/examples/create_normal_to_face.py b/src/FeaturesPlugin/doc/examples/create_normal_to_face.py new file mode 100644 index 000000000..c89e07c6b --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/create_normal_to_face.py @@ -0,0 +1,12 @@ +from salome.shaper import model +import os + +model.begin() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +model.do() + +### Create BoundingBox +Normal_1 = model.getNormal(Part_1_doc, model.selection("FACE", "Box_1_1/Top")) +model.do() + +model.end() diff --git a/src/FeaturesPlugin/doc/examples/create_normal_to_face_at_vertex.py b/src/FeaturesPlugin/doc/examples/create_normal_to_face_at_vertex.py new file mode 100644 index 000000000..eb0071efb --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/create_normal_to_face_at_vertex.py @@ -0,0 +1,12 @@ + +from salome.shaper import model +import os + +model.begin() +Box_1 = model.addBox(Part_1_doc, 10, 10, 10) +model.do() + +Normal_1 = model.getNormal(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Bottom]")) +model.do() + +model.end() diff --git a/src/FeaturesPlugin/doc/images/normal.png b/src/FeaturesPlugin/doc/images/normal.png new file mode 100644 index 000000000..16080764e Binary files /dev/null and b/src/FeaturesPlugin/doc/images/normal.png differ diff --git a/src/FeaturesPlugin/doc/images/normalToFacePropertyPanel.png b/src/FeaturesPlugin/doc/images/normalToFacePropertyPanel.png new file mode 100644 index 000000000..6ed5e8095 Binary files /dev/null and b/src/FeaturesPlugin/doc/images/normalToFacePropertyPanel.png differ diff --git a/src/FeaturesPlugin/doc/images/normalToFaceResult.png b/src/FeaturesPlugin/doc/images/normalToFaceResult.png new file mode 100644 index 000000000..ecfb260ab Binary files /dev/null and b/src/FeaturesPlugin/doc/images/normalToFaceResult.png differ diff --git a/src/FeaturesPlugin/doc/images/normalToFaceResultWithVertex.png b/src/FeaturesPlugin/doc/images/normalToFaceResultWithVertex.png new file mode 100644 index 000000000..98f1aa8ed Binary files /dev/null and b/src/FeaturesPlugin/doc/images/normalToFaceResultWithVertex.png differ diff --git a/src/FeaturesPlugin/doc/normalToFaceFeature.rst b/src/FeaturesPlugin/doc/normalToFaceFeature.rst new file mode 100644 index 000000000..e9da2793c --- /dev/null +++ b/src/FeaturesPlugin/doc/normalToFaceFeature.rst @@ -0,0 +1,71 @@ +.. |normalToFace.icon| image:: images/normal.png + +Normal to a face +================ + +The **Normal to a face** feature displays the normal to a face. A vertex can be specified to indicate the position of the normal else the center of face is used. + +The resulting normal can be created via a dedicated check-box **Create normal**. If this last is checked corresponding result and feature would be created. + +If the check-box **Create normal** isn't checked, **Apply** button does not generate any result and has the same effect as **Cancel** for this feature. + +To display the normal to a face in the active part: + +#. select in the Main Menu *Inspection - > Normal to a face* item or +#. click |normalToFace.icon| **Normal to a face** button in the toolbar + +The property panel is shown below. + +.. figure:: images/normalToFacePropertyPanel.png + :align: center + + Normal to a face + + +Input fields: + +- **Face** contains face selected in 3D OCC viewer or object browser. +- **Vertex** contains optionnal vertex selected in 3D OCC viewer or object browser. +- **Create normal** check-box allow the creation of the normal (result and feature). + +**TUI Command**: + +.. py:function:: model.getNormal(Part, face) + + :param part: The current part object. + :param object: A face in format *model.selection("FACE", face)*. + :return: Created normal to a face in the center of the face. + +Result +"""""" + +Result of **Normal to a face**. + +.. figure:: images/normalToFaceResult.png + :align: center + + Normal to a face + +**See Also** a sample TUI Script of :ref:`tui_create_normal_to_face` operation. + + +**TUI Command**: + +.. py:function:: model.getNormal(Part, face, vertex) + + :param part: The current part object. + :param object: A face in format *model.selection("FACE", face)*. + :param object: A vertex in format *model.selection("VERTEX", vertex)*. + :return: Created normal to a face at vertex. + +Result +"""""" + +Result of **Normal to aface** where **Vertex** is selecteted. + +.. figure:: images/normalToFaceResultWithVertex.png + :align: center + + Normal to a face at vertex + +**See Also** a sample TUI Script of :ref:`tui_create_normal_to_face_at_vertex` operation. diff --git a/src/FeaturesPlugin/icons/normale.png b/src/FeaturesPlugin/icons/normale.png new file mode 100644 index 000000000..16080764e Binary files /dev/null and b/src/FeaturesPlugin/icons/normale.png differ diff --git a/src/FeaturesPlugin/normal_to_face_widget.xml b/src/FeaturesPlugin/normal_to_face_widget.xml new file mode 100644 index 000000000..71cde51e1 --- /dev/null +++ b/src/FeaturesPlugin/normal_to_face_widget.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 7fb18f31f..87e47c378 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -196,5 +196,15 @@ + + + + + + + + diff --git a/src/FeaturesPlugin/tests.set b/src/FeaturesPlugin/tests.set index 404476a40..7e5e58612 100644 --- a/src/FeaturesPlugin/tests.set +++ b/src/FeaturesPlugin/tests.set @@ -521,4 +521,5 @@ SET(TEST_NAMES TestGeometryCalculation.py TestBoundingBox.py Test23885.py + TestNormalToFace.py ) diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 0c549a45b..2fa736470 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -91,6 +91,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Chamfer.h GeomAlgoAPI_Defeaturing.h GeomAlgoAPI_BoundingBox.h + GeomAlgoAPI_NormalToFace.h ) SET(PROJECT_SOURCES @@ -161,6 +162,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Chamfer.cpp GeomAlgoAPI_Defeaturing.cpp GeomAlgoAPI_BoundingBox.cpp + GeomAlgoAPI_NormalToFace.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.cpp new file mode 100644 index 000000000..2028b9902 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.cpp @@ -0,0 +1,242 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include "GeomAlgoAPI_NormalToFace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + /*! + * \brief Return type of shape for explode. In case of compound it will be a type of its first sub shape. + * \param theShape The shape to get type of. + * \retval TopAbs_ShapeEnum Return type of shape for explode. + */ +TopAbs_ShapeEnum GetTypeOfSimplePart(const TopoDS_Shape& theShape) +{ + TopAbs_ShapeEnum aType = theShape.ShapeType(); + if (aType == TopAbs_VERTEX) return TopAbs_VERTEX; + else if (aType == TopAbs_EDGE || aType == TopAbs_WIRE) return TopAbs_EDGE; + else if (aType == TopAbs_FACE || aType == TopAbs_SHELL) return TopAbs_FACE; + else if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID) return TopAbs_SOLID; + else if (aType == TopAbs_COMPOUND) { + // Only the iType of the first shape in the compound is taken into account + TopoDS_Iterator It (theShape, Standard_False, Standard_False); + if (It.More()) { + return GetTypeOfSimplePart(It.Value()); + } + } + return TopAbs_SHAPE; +} + + /*! + * \brief Get Local Coordinate System, corresponding to the given shape. + * \param theShape The shape to get type of. + * \retval gp_Ax3 Return axis. + * + * Origin of the LCS is situated at the shape's center of mass. + * Axes of the LCS are obtained from shape's location or, + * if the shape is a planar face, from position of its plane. + */ +gp_Ax3 GetPosition(const TopoDS_Shape& theShape) +{ + gp_Ax3 aResult; + + if (theShape.IsNull()) + return aResult; + + // Axes + aResult.Transform(theShape.Location().Transformation()); + if (theShape.ShapeType() == TopAbs_FACE) { + Handle(Geom_Surface) aGS = BRep_Tool::Surface(TopoDS::Face(theShape)); + if (!aGS.IsNull() && aGS->IsKind(STANDARD_TYPE(Geom_Plane))) { + Handle(Geom_Plane) aGPlane = Handle(Geom_Plane)::DownCast(aGS); + gp_Pln aPln = aGPlane->Pln(); + aResult = aPln.Position(); + // In case of reverse orinetation of the face invert the plane normal + // (the face's normal does not mathc the plane's normal in this case) + if (theShape.Orientation() == TopAbs_REVERSED) { + gp_Dir Vx = aResult.XDirection(); + gp_Dir N = aResult.Direction().Mirrored(Vx); + gp_Pnt P = aResult.Location(); + aResult = gp_Ax3(P, N, Vx); + } + } + } + + // Origin + gp_Pnt aPnt; + + TopAbs_ShapeEnum aShType = theShape.ShapeType(); + + if (aShType == TopAbs_VERTEX) { + aPnt = BRep_Tool::Pnt(TopoDS::Vertex(theShape)); + } else { + if (aShType == TopAbs_COMPOUND) { + aShType = GetTypeOfSimplePart(theShape); + } + + GProp_GProps aSystem; + if (aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) + BRepGProp::LinearProperties(theShape, aSystem); + else if (aShType == TopAbs_FACE || aShType == TopAbs_SHELL) + BRepGProp::SurfaceProperties(theShape, aSystem); + else + BRepGProp::VolumeProperties(theShape, aSystem); + + aPnt = aSystem.CentreOfMass(); + } + + aResult.SetLocation(aPnt); + + return aResult; +} + +//================================================================================================= +bool GeomAlgoAPI_NormalToFace::normal(GeomShapePtr theFace, + GeomShapePtr thePoint, + GeomEdgePtr theNormal, + std::string& theError) +{ + #ifdef _DEBUG + std::cout << "GeomAlgoAPI_NormalToFace::normal" << std::endl; + #endif + + if (!theFace.get()) { + theError = "Face for normale calculation is null"; + return false; + } + + TopoDS_Shape aShape = theFace->impl(); + + if (aShape.ShapeType() != TopAbs_FACE) { + theError = "Shape for normale calculation is not a face"; + return false; + } + + TopoDS_Face aFace = TopoDS::Face(aShape); + + // Point + gp_Pnt p1 (0,0,0); + // Point parameters on surface + double u1, u2, v1, v2; + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf); + gp_Ax3 aPos = GetPosition(aFace); + p1 = aPos.Location(); + // Set default starting point using UV bounds + ShapeAnalysis::GetFaceUVBounds(aFace, u1, u2, v1, v2); + gp_Pnt2d pUV ((u2 + u1) * 0.5, (v2 + v1) * 0.5); + + // Change to Vertex coord if selected + if (thePoint.get()) { + TopoDS_Shape anOptPnt = thePoint->impl(); + if (anOptPnt.IsNull()) { + theError = "Invalid shape given for point argument"; + return false; + } + p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt)); + pUV = aSurfAna->ValueOfUV(p1, Precision::Confusion()); + } + + // Normal direction + gp_Vec Vec1,Vec2; + BRepAdaptor_Surface SF (aFace); + SF.D1(pUV.X(), pUV.Y(), p1, Vec1, Vec2); + if (Vec1.Magnitude() < Precision::Confusion()) { + gp_Vec tmpV; + gp_Pnt tmpP; + SF.D1(pUV.X(), pUV.Y()-0.1, tmpP, Vec1, tmpV); + } + else if (Vec2.Magnitude() < Precision::Confusion()) { + gp_Vec tmpV; + gp_Pnt tmpP; + SF.D1(pUV.X()-0.1, pUV.Y(), tmpP, tmpV, Vec2); + } + + gp_Vec V = Vec1.Crossed(Vec2); + Standard_Real mod = V.Magnitude(); + if (mod < Precision::Confusion()) + Standard_NullObject::Raise("Normal vector of a face has null magnitude"); + + // Set length of normal vector to average radius of curvature + Standard_Real radius = 0.0; + GeomLProp_SLProps aProperties (aSurf, pUV.X(), pUV.Y(), 2, Precision::Confusion()); + if (aProperties.IsCurvatureDefined()) { + Standard_Real radius1 = Abs(aProperties.MinCurvature()); + Standard_Real radius2 = Abs(aProperties.MaxCurvature()); + if (Abs(radius1) > Precision::Confusion()) { + radius = 1.0 / radius1; + if (Abs(radius2) > Precision::Confusion()) { + radius = (radius + 1.0 / radius2) / 2.0; + } + } else { + if (Abs(radius2) > Precision::Confusion()) { + radius = 1.0 / radius2; + } + } + } + + // Set length of normal vector to average dimension of the face + // (only if average radius of curvature is not appropriate) + if (radius < Precision::Confusion()) { + Bnd_Box B; + Standard_Real Xmin, Xmax, Ymin, Ymax, Zmin, Zmax; + BRepBndLib::Add(aFace, B); + B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); + radius = ((Xmax - Xmin) + (Ymax - Ymin) + (Zmax - Zmin)) / 3.0; + } + + if (radius < Precision::Confusion()) + radius = 1.0; + + V *= radius / mod; + + // consider the face orientation + if (aFace.Orientation() == TopAbs_REVERSED || + aFace.Orientation() == TopAbs_INTERNAL) { + V = - V; + } + + // Edge + gp_Pnt p2 = p1.Translated(V); + BRepBuilderAPI_MakeEdge aBuilder (p1, p2); + if (!aBuilder.IsDone()) + Standard_NullObject::Raise("Vector construction failed"); + aShape = aBuilder.Shape(); + + theNormal->setImpl(new TopoDS_Shape(aShape)); + + return true; +} + diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.h b/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.h new file mode 100644 index 000000000..4ee12c740 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.h @@ -0,0 +1,46 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#ifndef GeomAlgoAPI_NormalToFace_H_ +#define GeomAlgoAPI_NormalToFace_H_ + +#include +#include +#include + +/**\class GeomAlgoAPI_NormalToFace + * \ingroup DataAlgo + * \brief Allows to create normal to face-shapes + */ + +class GeomAlgoAPI_NormalToFace +{ + public: + /// Get the normal to face-shapes + /// \param theface the face + /// \param thePoint the optional point + /// \param theNormal the normal + /// \param theError the error + GEOMALGOAPI_EXPORT static bool normal(GeomShapePtr theFace, + GeomShapePtr thePoint, + GeomEdgePtr theNormal, + std::string& theError); +}; + +#endif diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py index 5ce684790..62a0ca1a8 100644 --- a/src/PythonAPI/model/features/__init__.py +++ b/src/PythonAPI/model/features/__init__.py @@ -31,6 +31,7 @@ from FeaturesAPI import addFillet, addChamfer from FeaturesAPI import addFusionFaces from FeaturesAPI import measureLength, measureDistance, measureRadius, measureAngle from FeaturesAPI import getPointCoordinates, getGeometryCalculation, getBoundingBox +from FeaturesAPI import getNormal from FeaturesAPI import addRemoveResults from FeaturesAPI import addCopy, addImportResult from FeaturesAPI import addDefeaturing