From: Jérôme Date: Wed, 21 Oct 2020 17:26:35 +0000 (+0200) Subject: Integration : X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=64a1c2eb2f69296ef63245d3a777797918e79376;p=modules%2Fshaper.git Integration : { Code from : Jerome LUCAS } + Implementation create normal to face + Modification for "create normal" functionality + Add documentation and test unit + Refactoring code + Copyright update to 2021 --- 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..8cbf7bf9e --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_NormalToFace.cpp @@ -0,0 +1,119 @@ +// 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 +#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& theOptionnelPoint) +:ModelHighAPI_Interface(theFeature) +{ + if (initialize()) { + fillAttribute(theBaseFace, myfaceSelected); + fillAttribute(theOptionnelPoint, myvertexSelected); + feature()->string(FeaturesPlugin_CreateNormalToFace::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_CreateNormalToFace::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_CreateNormalToFace::FACE_SELECTED_ID()); + + theDumper << aBase << " = model.getNormal(" << aDocName << ", " << anAttrObject; + + if (!aBase->string(FeaturesPlugin_CreateNormalToFace::VERTEX_OPTION_ID())->value().empty()){ + + AttributeSelectionPtr anAttrVertex = + aBase->selection(FeaturesPlugin_CreateNormalToFace::VERTEX_SELECTED_ID()); + + theDumper << ", " << anAttrVertex; + } + + theDumper << ")" << std::endl; +} + +//================================================================================================== +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionnelPoint) +{ + + FeaturePtr aFeature = thePart->addFeature(FeaturesPlugin_CreateNormalToFace::ID()); + + NormalPtr aNormalToface; + + aNormalToface.reset(new FeaturesAPI_NormalToFace(aFeature, theBaseFace, theOptionnelPoint)); + + return aNormalToface; +} + +//================================================================================================= +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace) +{ + + FeaturePtr aFeature = thePart->addFeature(FeaturesPlugin_CreateNormalToFace::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..d305cdec2 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_NormalToFace.h @@ -0,0 +1,88 @@ +// 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); + + FEATURESAPI_EXPORT + explicit FeaturesAPI_NormalToFace(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionnelPoint); + + FEATURESAPI_EXPORT + explicit FeaturesAPI_NormalToFace(const std::shared_ptr& theFeature, + const ModelHighAPI_Selection& theBaseFace); + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_NormalToFace(); + + INTERFACE_3(FeaturesPlugin_CreateNormalToFace::ID(), + faceSelected, FeaturesPlugin_CreateNormalToFace::FACE_SELECTED_ID(), + ModelAPI_AttributeSelection, + /** base face */, + vertexSelected, FeaturesPlugin_CreateNormalToFace::VERTEX_SELECTED_ID(), + ModelAPI_AttributeSelection, + /** vetex option */, + vertexOption, FeaturesPlugin_CreateNormalToFace::VERTEX_OPTION_ID(), + ModelAPI_AttributeString, + /** option */) + + /// 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 NormalToFace feature. +FEATURESAPI_EXPORT +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace, + const ModelHighAPI_Selection& theOptionnelPoint); + +/// \ingroup CPPHighAPI +/// \brief Create NormalToFace feature. +FEATURESAPI_EXPORT +NormalPtr getNormal(const std::shared_ptr& thePart, + const ModelHighAPI_Selection& theBaseFace); + +#endif // FeaturesAPI_Fillet_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 4d52c6119..bf435e301 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -19,6 +19,17 @@ INCLUDE(Common) INCLUDE(UnitTest) +INCLUDE(UseQtExt) + +# additional include directories +INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/GeomDataAPI + ${PROJECT_SOURCE_DIR}/src/Locale + ${PROJECT_SOURCE_DIR}/src/PrimitivesPlugin + ${QT_INCLUDES}) + +# additional preprocessor / compiler flags +ADD_DEFINITIONS(${QT_DEFINITIONS}) + SET(PROJECT_HEADERS @@ -60,6 +71,8 @@ SET(PROJECT_HEADERS FeaturesPlugin_Fillet.h FeaturesPlugin_Fillet1D.h FeaturesPlugin_Measurement.h + FeaturesPlugin_NormalToFace.h + FeaturesPlugin_CreateNormalToFace.h FeaturesPlugin_FusionFaces.h FeaturesPlugin_RemoveResults.h FeaturesPlugin_Chamfer.h @@ -112,6 +125,8 @@ SET(PROJECT_SOURCES FeaturesPlugin_Fillet.cpp FeaturesPlugin_Fillet1D.cpp FeaturesPlugin_Measurement.cpp + FeaturesPlugin_NormalToFace.cpp + FeaturesPlugin_CreateNormalToFace.cpp FeaturesPlugin_FusionFaces.cpp FeaturesPlugin_RemoveResults.cpp FeaturesPlugin_Chamfer.cpp @@ -155,6 +170,8 @@ SET(XML_RESOURCES fillet_widget.xml fillet1d_widget.xml measurement_widget.xml + normal_to_face_widget.xml + create_normal_to_face_widget.xml fusion_faces_widget.xml chamfer_widget.xml copy_widget.xml @@ -198,7 +215,11 @@ SET(PROJECT_LIBRARIES ) ADD_DEFINITIONS(-DFEATURESPLUGIN_EXPORTS) -ADD_LIBRARY(FeaturesPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES} ${TEXT_RESOURCES}) +ADD_LIBRARY(FeaturesPlugin MODULE + ${PROJECT_SOURCES} + ${PROJECT_HEADERS} + ${XML_RESOURCES} + ${TEXT_RESOURCES}) TARGET_LINK_LIBRARIES(FeaturesPlugin ${PROJECT_LIBRARIES}) INSTALL(TARGETS FeaturesPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES}) @@ -215,16 +236,16 @@ ADD_UNIT_TESTS( IF(${HAVE_SALOME}) enable_testing() set(TEST_INSTALL_DIRECTORY "${SALOME_SHAPER_INSTALL_TESTS}/FeaturesPlugin") - + install(FILES CTestTestfileInstall.cmake DESTINATION ${TEST_INSTALL_DIRECTORY} RENAME CTestTestfile.cmake) install(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY}) - + set(TMP_TESTS_NAMES) foreach(tfile ${TEST_NAMES}) list(APPEND TMP_TESTS_NAMES "Test/${tfile}") endforeach(tfile ${TEST_NAMES}) - + install(FILES ${TMP_TESTS_NAMES} DESTINATION ${TEST_INSTALL_DIRECTORY}) ENDIF(${HAVE_SALOME}) diff --git a/src/FeaturesPlugin/FeaturesPlugin_CreateNormalToFace.cpp b/src/FeaturesPlugin/FeaturesPlugin_CreateNormalToFace.cpp new file mode 100644 index 000000000..f0b944b53 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_CreateNormalToFace.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_CreateNormalToFace.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//================================================================================================= +FeaturesPlugin_CreateNormalToFace::FeaturesPlugin_CreateNormalToFace() +{ +} + +//================================================================================================= +void FeaturesPlugin_CreateNormalToFace::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_CreateNormalToFace::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); + } +} + +//================================================================================================= +void FeaturesPlugin_CreateNormalToFace::attributeChanged(const std::string& theID) +{ +} + + diff --git a/src/FeaturesPlugin/FeaturesPlugin_CreateNormalToFace.h b/src/FeaturesPlugin/FeaturesPlugin_CreateNormalToFace.h new file mode 100644 index 000000000..b3a356770 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_CreateNormalToFace.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_CreateNormalToFace_H_ +#define FeaturesPlugin_CreateNormalToFace_H_ + +#include "FeaturesPlugin.h" +#include + +#include +#include + +/// \class FeaturesPlugin_CreateNormalToFace +/// \ingroup Plugins +/// \brief Feature for construct normal to face + +class FeaturesPlugin_CreateNormalToFace : public ModelAPI_Feature +{ +public: + 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_CreateNormalToFace(); + +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.cpp b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.cpp new file mode 100644 index 000000000..853c26c1d --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.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_NormalToFace.h" + +#include +#include +#include +#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(CREATENORMAL_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(VERTEX_OPTION_ID(), ModelAPI_AttributeString::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), VERTEX_SELECTED_ID()); + +} + +//================================================================================================= +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); + } + + 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_NormalToFace::attributeChanged(const std::string& theID) +{ + if (theID == FACE_SELECTED_ID()) { + if (myCreateFeature.get()) + updateNormal(); + } +} + +//================================================================================================= +void FeaturesPlugin_NormalToFace::createNormal() +{ + SessionPtr aSession = ModelAPI_Session::get(); + + DocumentPtr aDoc = aSession->activeDocument(); + + if (aDoc.get()) { + myCreateFeature = aDoc->addFeature(FeaturesPlugin_CreateNormalToFace::ID()); + } +} + +//================================================================================================= +void FeaturesPlugin_NormalToFace::updateNormal() +{ + myCreateFeature->selection(FeaturesPlugin_CreateNormalToFace::FACE_SELECTED_ID()) + ->setValue(selection(FACE_SELECTED_ID())->context() , + selection(FACE_SELECTED_ID())->value()); + + myCreateFeature->string(FeaturesPlugin_CreateNormalToFace::VERTEX_OPTION_ID()) + ->setValue(string(VERTEX_OPTION_ID())->value()); + + if (!string(VERTEX_OPTION_ID())->value().empty()) { + myCreateFeature->selection(FeaturesPlugin_CreateNormalToFace::VERTEX_SELECTED_ID()) + ->setValue(selection(VERTEX_SELECTED_ID())->context() , + selection(VERTEX_SELECTED_ID())->value()); + } + + myCreateFeature->execute(); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.h b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.h new file mode 100644 index 000000000..ce6f72bb1 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_NormalToFace.h @@ -0,0 +1,102 @@ +// 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 Feature for construct normal to face + +class FeaturesPlugin_NormalToFace : public ModelAPI_Feature +{ +public: + 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_NormalToFace(); + + 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_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 63d0241e3..b7c824d51 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -191,6 +193,10 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_Fillet1D); } else if (theFeatureID == FeaturesPlugin_Measurement::ID()) { return FeaturePtr(new FeaturesPlugin_Measurement); + } else if (theFeatureID == FeaturesPlugin_NormalToFace::ID()) { + return FeaturePtr(new FeaturesPlugin_NormalToFace); + } else if (theFeatureID == FeaturesPlugin_CreateNormalToFace::ID()) { + return FeaturePtr(new FeaturesPlugin_CreateNormalToFace); } else if (theFeatureID == FeaturesPlugin_RemoveResults::ID()) { return FeaturePtr(new FeaturesPlugin_RemoveResults); } else if (theFeatureID == FeaturesPlugin_Chamfer::ID()) { diff --git a/src/FeaturesPlugin/Test/TestNormalToFace.py b/src/FeaturesPlugin/Test/TestNormalToFace.py new file mode 100644 index 000000000..ad70044d9 --- /dev/null +++ b/src/FeaturesPlugin/Test/TestNormalToFace.py @@ -0,0 +1,66 @@ +# 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" + + +#========================================================================= +# test creating normal to face +#========================================================================= +def test_Normal_to_face(): + + model.begin() + file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Brep","box1.brep") + partSet = model.moduleDocument() + Part_1 = model.addPart(partSet) + Part_1_doc = Part_1.document() + Import_1 = model.addImport(Part_1_doc,file_path) + model.do() + ### Create Normal + Normal_1 = model.getNormal(Part_1_doc, model.selection("FACE", "box1_1/Shape_6")) + 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) + + +if __name__ == '__main__': + + test_Normal_to_face() + + #========================================================================= + # 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..2ae1c6dc3 --- /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/createNormalToFace.py + :linenos: + :language: python + +:download:`Download this script ` + + .. _tui_create_normal_to_face_at_vertex: + +Create normal to a face at vertex +================================= + +.. literalinclude:: examples/createNormalToFaceAtVertex.py + :linenos: + :language: python + +:download:`Download this script ` \ No newline at end of file diff --git a/src/FeaturesPlugin/doc/examples/createNormalToFace.py b/src/FeaturesPlugin/doc/examples/createNormalToFace.py new file mode 100644 index 000000000..a1f973011 --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/createNormalToFace.py @@ -0,0 +1,15 @@ +from salome.shaper import model +import os + +model.begin() +file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Brep","box1.brep") +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Import_1 = model.addImport(Part_1_doc,file_path) +model.do() + +### Create BoundingBox +Normal_1 = model.getNormal(Part_1_doc, model.selection("FACE", "box1_1/Shape_6")) +model.do() +model.end() diff --git a/src/FeaturesPlugin/doc/examples/createNormalToFaceAtVertex.py b/src/FeaturesPlugin/doc/examples/createNormalToFaceAtVertex.py new file mode 100644 index 000000000..c59aa67c5 --- /dev/null +++ b/src/FeaturesPlugin/doc/examples/createNormalToFaceAtVertex.py @@ -0,0 +1,17 @@ + +from salome.shaper import model +import os + +model.begin() +file_path = os.path.join(os.getenv("DATA_DIR"),"Shapes","Brep","box1.brep") +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Import_1 = model.addImport(Part_1_doc,file_path) +model.do() + +### Create BoundingBox +Normal_1 = model.getNormal(Part_1_doc, model.selection("FACE", "box1_1/Shape_6"), + model.selection("VERTEX", "[box1_1/Shape_2][box1_1/Shape_4][box1_1/Shape_6]")) +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..cf498b72d --- /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 at center. + +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. \ No newline at end of file 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..9092142dc 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -126,7 +126,7 @@ + icon="icons/Features/fillet.png" auto_preview="false" helpfile="filletFeature.html"> + icon="icons/Features/fusion_faces.png" auto_preview="true" helpfile="FeaturesPlugin/fusionFacesFeature.html"> + + + + + + + + diff --git a/src/FeaturesPlugin/tests.set b/src/FeaturesPlugin/tests.set index 404476a40..75e619ded 100644 --- a/src/FeaturesPlugin/tests.set +++ b/src/FeaturesPlugin/tests.set @@ -177,7 +177,7 @@ SET(TEST_NAMES TestMeasurementAngle3Points.py TestMeasurementPresentation.py TestFusionFaces.py - TestFusionFaces2697.py + TestFusionFaces2697.py Test1379.py Test1922.py Test1942.py @@ -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..4a04f03f8 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -33,6 +33,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Prism.h GeomAlgoAPI_Revolution.h GeomAlgoAPI_Boolean.h + GeomAlgoAPI_NormalToFace.h GeomAlgoAPI_ThroughAll.h GeomAlgoAPI_Rotation.h GeomAlgoAPI_Translation.h @@ -103,6 +104,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Prism.cpp GeomAlgoAPI_Revolution.cpp GeomAlgoAPI_Boolean.cpp + GeomAlgoAPI_NormalToFace.cpp GeomAlgoAPI_ThroughAll.cpp GeomAlgoAPI_Rotation.cpp GeomAlgoAPI_Translation.cpp diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.cpp new file mode 100644 index 000000000..bd65e01df --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_NormalToFace.cpp @@ -0,0 +1,235 @@ +// 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 + + /*! + * \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. + * + * 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; +} + +//================================================================================================= +static bool GeomAlgoAPI_NormalToFace::normal(GeomShapePtr theFace, + GeomShapePtr theOptionnelPoint, + 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); + + if (theOptionnelPoint.get()) { + TopoDS_Shape anOptPnt = theOptionnelPoint->impl(); + if (anOptPnt.IsNull()) { + theError = "Invalid shape given for point argument"; + return false; + } + p1 = BRep_Tool::Pnt(TopoDS::Vertex(anOptPnt)); + } else { + gp_Ax3 aPos = GetPosition(aFace); + p1 = aPos.Location(); + } + + // Point parameters on surface + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf); + gp_Pnt2d 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..6c54e4488 --- /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_EXPORT GeomAlgoAPI_NormalToFace +{ + public: + /// get the normal to face-shapes + /// \param theface the face + /// \param theOptionnelPoint the optionnel point + /// \param theNormal the normal + /// \param theError the error + static bool GeomAlgoAPI_NormalToFace::normal(GeomShapePtr theFace, + GeomShapePtr theOptionnelPoint, + GeomEdgePtr theNormal, + std::string& theError); +}; + +#endif diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index c6a298461..e495fe850 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -117,7 +117,7 @@ SET(PROJECT_SOURCES SET(PROJECT_LIBRARIES Config GeomAPI - Locale + ${OpenCASCADE_ApplicationFramework_LIBRARIES} ) SET(CMAKE_SWIG_FLAGS -threads -w325,321,362,383,302,403,451,473) ADD_DEFINITIONS(-DMODELAPI_EXPORTS) @@ -131,6 +131,10 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Config ${PROJECT_SOURCE_DIR}/src/GeomAPI ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI ${PROJECT_SOURCE_DIR}/src/Locale + ${OpenCASCADE_INCLUDE_DIR} + ${OpenCASCADE_DataExchange_LIBRARIES} + ${OpenCASCADE_ModelingAlgorithms_LIBRARIES} + ${OpenCASCADE_ApplicationFramework_LIBRARIES} ) @@ -172,16 +176,16 @@ ADD_UNIT_TESTS(${TEST_NAMES}) if(${HAVE_SALOME}) enable_testing() set(TEST_INSTALL_DIRECTORY "${SALOME_SHAPER_INSTALL_TESTS}/ModelAPI") - + install(FILES CTestTestfileInstall.cmake DESTINATION ${TEST_INSTALL_DIRECTORY} RENAME CTestTestfile.cmake) install(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY}) - + set(TMP_TESTS_NAMES) foreach(tfile ${TEST_NAMES}) list(APPEND TMP_TESTS_NAMES "Test/${tfile}") endforeach(tfile ${TEST_NAMES}) - + install(FILES ${TMP_TESTS_NAMES} DESTINATION ${TEST_INSTALL_DIRECTORY}) endif(${HAVE_SALOME}) diff --git a/src/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