From a06f792be11561a0a3378524d7a1f0cb7ef782bb Mon Sep 17 00:00:00 2001 From: mpv Date: Mon, 29 Aug 2016 13:09:27 +0300 Subject: [PATCH] Implementation of experimental approximated pipe creation feature done by Edouard Mei. --- src/FeaturesPlugin/CMakeLists.txt | 11 + .../FeaturesPlugin_ParameterLaw.cpp | 131 ++ .../FeaturesPlugin_ParameterLaw.h | 97 ++ .../FeaturesPlugin_PipeApprox.cpp | 314 +++++ .../FeaturesPlugin_PipeApprox.h | 105 ++ .../FeaturesPlugin_PipeApproxLaw.cpp | 460 +++++++ .../FeaturesPlugin_PipeApproxLaw.h | 146 +++ src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 12 + .../FeaturesPlugin_Validators.cpp | 46 + .../FeaturesPlugin_Validators.h | 11 + src/FeaturesPlugin/parameterlaw_widget.xml | 28 + src/FeaturesPlugin/pipeapprox_widget.xml | 74 ++ src/FeaturesPlugin/pipeapproxlaw_widget.xml | 90 ++ src/FeaturesPlugin/plugin-Features.xml | 11 + src/GeomAlgoAPI/CMakeLists.txt | 4 + src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.cpp | 314 +++++ src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.h | 40 + src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.cpp | 1107 +++++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.h | 85 ++ src/Model/Model_Update.cpp | 15 +- 20 files changed, 3100 insertions(+), 1 deletion(-) create mode 100644 src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.h create mode 100644 src/FeaturesPlugin/FeaturesPlugin_PipeApprox.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_PipeApprox.h create mode 100644 src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.h create mode 100644 src/FeaturesPlugin/parameterlaw_widget.xml create mode 100644 src/FeaturesPlugin/pipeapprox_widget.xml create mode 100644 src/FeaturesPlugin/pipeapproxlaw_widget.xml create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.h create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.h diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 451b9c002..03df9caa6 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -28,6 +28,10 @@ SET(PROJECT_HEADERS FeaturesPlugin_ValidatorTransform.h FeaturesPlugin_Validators.h FeaturesPlugin_RemoveSubShapes.h + FeaturesPlugin_PipeApprox.h + FeaturesPlugin_PipeApproxLaw.h + FeaturesPlugin_ParameterLaw.h + FeaturesPlugin_Validators.h ) SET(PROJECT_SOURCES @@ -54,6 +58,10 @@ SET(PROJECT_SOURCES FeaturesPlugin_ValidatorTransform.cpp FeaturesPlugin_Validators.cpp FeaturesPlugin_RemoveSubShapes.cpp + FeaturesPlugin_PipeApprox.cpp + FeaturesPlugin_PipeApproxLaw.cpp + FeaturesPlugin_ParameterLaw.cpp + FeaturesPlugin_Validators.cpp ) SET(XML_RESOURCES @@ -74,6 +82,9 @@ SET(XML_RESOURCES pipe_widget.xml remove_subshapes_widget.xml union_widget.xml + pipeapprox_widget.xml + pipeapproxlaw_widget.xml + parameterlaw_widget.xml ) SET(TEXT_RESOURCES diff --git a/src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.cpp b/src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.cpp new file mode 100644 index 000000000..4f38329ea --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.cpp @@ -0,0 +1,131 @@ +// Copyright + +// File: FeaturesPlugin_ParameterLaw.cpp + + +#include "FeaturesPlugin_ParameterLaw.h" +#include +#include +#include +#include +#include +#include +//??#include "ParametersPlugin_Parameter.h" +//??#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//================================================================================================= +FeaturesPlugin_ParameterLaw::FeaturesPlugin_ParameterLaw() +{ +} + +//================================================================================================= +void FeaturesPlugin_ParameterLaw::initAttributes() +{ + data()->addAttribute(LAW_REFERENCE_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(LAW_DEFINITION_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(VARIABLE_ID(), ModelAPI_AttributeString::typeId()); + + data()->addAttribute(REVERSE_ID(), ModelAPI_AttributeBoolean::typeId()); + + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); +} + +//================================================================================================= +void FeaturesPlugin_ParameterLaw::execute() +{ + // Getting Ref and Def + std::shared_ptr aRef; + std::shared_ptr aDef; + //REFERENCE + AttributeSelectionPtr aRefSelection = selection(LAW_REFERENCE_ID()); + if(!aRefSelection.get()) { + setError("Error: Ref selection is empty."); + return; + } + aRef = std::dynamic_pointer_cast(aRefSelection->value()); + if(!aRef.get()) { + // Probably it is a construction. + aRef = aRefSelection->context()->shape(); + } + if(!aRef.get() || aRef->isNull()) { + setError("Error: Ref shape is null."); + return; + } + //DEFINITION + AttributeSelectionPtr aDefSelection = selection(LAW_DEFINITION_ID()); + if(!aDefSelection.get()) { + setError("Error: Def selection is empty."); + return; + } + aDef = std::dynamic_pointer_cast(aDefSelection->value()); + if(!aDef.get()) { + // Probably it is a construction. + aDef = aDefSelection->context()->shape(); + } + if(!aDef.get() || aDef->isNull()) { + setError("Error: Def shape is null."); + return; + } + + // Flags for reverse path + bool isReverse = boolean(REVERSE_ID())->value(); + + GeomAlgoAPI_ParameterLaw aParameterLawAlgo = GeomAlgoAPI_ParameterLaw(aDef, aRef, isReverse); + int aResultIndex = 0; + + if(!aParameterLawAlgo.isDone()) { + static const std::string aPrismAlgoError = "Error: Param algo failed."; + setError(aPrismAlgoError); + aResultIndex = 0; + //break; + } + // Check if shape is valid + if(!aParameterLawAlgo.shape().get() || aParameterLawAlgo.shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + aResultIndex = 0; + return; + } + if(!aParameterLawAlgo.isValid()) { + std::string aPrismAlgoError = "Error: Resulting shape is not valid."; + setError(aPrismAlgoError); + aResultIndex = 0; + //break; + } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + + loadNamingDS(aParameterLawAlgo, aResultBody); + setResult(aResultBody, aResultIndex); + aResultIndex++; + removeResults(aResultIndex); +} + +void FeaturesPlugin_ParameterLaw::loadNamingDS(GeomAlgoAPI_ParameterLaw& theParameterLawAlgo, + std::shared_ptr theResultBody) +{ + theResultBody->store(theParameterLawAlgo.shape()); + + int aIndex = 0, aTag = 0; + const std::string aName = "Law"; + std::ostringstream aStr; + aStr << aName << "_" << aIndex++; + theResultBody->generated(theParameterLawAlgo.shape(), aStr.str(), aTag++); +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.h b/src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.h new file mode 100644 index 000000000..c6b48951b --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_ParameterLaw.h @@ -0,0 +1,97 @@ +// Copyright + +// File: FeaturesPlugin_ParameterLaw.h + + +#ifndef FeaturesPlugin_ParameterLaw_H_ +#define FeaturesPlugin_ParameterLaw_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +class GeomAPI_Shape; +class ModelAPI_ResultBody; + +/** \class FeaturesPlugin_Pipe + * \ingroup Plugins + * \brief Feature for creation of Pipe from the planar face. + * Pipe creates the lateral faces based on edges of the base face and + * the start and end faces and/or start and end angles. + */ +class FeaturesPlugin_ParameterLaw : public ModelAPI_Feature +{ + public: + /// Pipe kind. + inline static const std::string& ID() + { + static const std::string MY_ParameterLaw_ID("ParameterLaw"); + return MY_ParameterLaw_ID; + } + + /// attribute name of law reference curve + inline static const std::string& LAW_REFERENCE_ID() + { + static const std::string MY_LAW_REFERENCE_ID("law_reference"); + return MY_LAW_REFERENCE_ID; + } + + /// attribute name of law definition curve + inline static const std::string& LAW_DEFINITION_ID() + { + static const std::string MY_LAW_DEFINITION_ID("law_definition"); + return MY_LAW_DEFINITION_ID; + } + + /// attribute name of parameter name + inline static const std::string& VARIABLE_ID() + { + static const std::string MY_VARIABLE_ID("variable"); + return MY_VARIABLE_ID; + } + + /// attribute name of flag of reverse direction + inline static const std::string& REVERSE_ID() + { + static const std::string MY_REVERSE_ID("reverse_direction"); + return MY_REVERSE_ID; + } + + /// attribute name for creation method + inline static const std::string& CREATION_METHOD() + { + static const std::string METHOD_ATTR("CreationMethod"); + return METHOD_ATTR; + } + + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_ParameterLaw::ID(); + return MY_KIND; + } + + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Use plugin manager for features creation. + FeaturesPlugin_ParameterLaw(); + +private: + /// Load Naming data structure of the feature to the document. + void loadNamingDS(GeomAlgoAPI_ParameterLaw& theParameterLawAlgo, + std::shared_ptr theResultBody); +}; +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_PipeApprox.cpp b/src/FeaturesPlugin/FeaturesPlugin_PipeApprox.cpp new file mode 100644 index 000000000..b0804d590 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_PipeApprox.cpp @@ -0,0 +1,314 @@ +// Copyright + +// File: FeaturesPlugin_PipeApprox.cpp + + +#include "FeaturesPlugin_PipeApprox.h" + +#include +#include +#include +#include +#include +#include +//??#include "ParametersPlugin_Parameter.h" +//??#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +namespace patch +{ + template < typename T > std::string to_string( const T& n ) + { + std::ostringstream stm ; + stm << n ; + return stm.str() ; + } +} + +//static ListOfShape makeProfileList(ObjectPtr theProfileObjRef); +static ListOfShape makeProfileList(AttributeSelectionListPtr aFacesSelectionList); +//================================================================================================= +FeaturesPlugin_PipeApprox::FeaturesPlugin_PipeApprox() +{ +} + +//================================================================================================= +void FeaturesPlugin_PipeApprox::initAttributes() +{ + AttributeSelectionListPtr aSelection = + std::dynamic_pointer_cast(data()->addAttribute( + PROFILE_ID(), ModelAPI_AttributeSelectionList::typeId())); + aSelection->setSelectionType("FACE"); + + + data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + //data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(LAW_REFERENCE_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(LAW_DEFINITION_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + +} + +//================================================================================================= +void FeaturesPlugin_PipeApprox::execute() +{ + // Getting creation method. + std::string aCreationMethod = string(CREATION_METHOD())->value(); + + //Getting path + //limit to edge + + std::shared_ptr aPath; + std::shared_ptr anObjRef = selection(PATH_OBJECT_ID()); + + if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) { + aPath = std::shared_ptr(new GeomAPI_Edge(anObjRef->value())); + } else if(anObjRef->context() && anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) { + aPath = std::shared_ptr(new GeomAPI_Edge(anObjRef->context()->shape())); + } + /* + //list of edge + ListOfShape aEdgesList; + AttributeSelectionListPtr aEdgesSelectionList = selectionList(PATH_OBJECT_ID()); + for(int anIndex = 0; anIndex < aEdgesSelectionList->size(); anIndex++) { + AttributeSelectionPtr aEdgeSel = aEdgesSelectionList->value(anIndex); + std::shared_ptr aEdgeShape = aEdgeSel->value(); + if(aEdgeShape.get() && !aEdgeShape->isNull()) { + aEdgesList.push_back(aEdgeShape); + } + } + */ + + //Getting profile + ListOfShape aFacesList; + AttributeSelectionListPtr aFacesSelectionList = selectionList(PROFILE_ID()); + for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { + AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex); + std::shared_ptr aFaceShape = aFaceSel->value(); + if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face. + aFacesList.push_back(aFaceShape); + } else { // This may be the whole sketch result selected, check and get faces. + ResultPtr aContext = aFaceSel->context(); + std::shared_ptr aContextShape = aContext->shape(); + if(!aContextShape.get()) { + static const std::string aContextError = "Error: The selection context is bad."; + setError(aContextError); + return; + } + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(!aConstruction.get()) { + static const std::string aFaceError = "Error: Can not find basis for extrusion."; + setError(aFaceError); + return; + } + int aFacesNum = aConstruction->facesNum(); + for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { + aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + aFacesList.push_back(aFaceShape); + } + } + } + + // Getting Bi-Normal + std::shared_ptr aBiNormal; + if(aCreationMethod == "binormal") { + AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID()); + if(!aBiNormalSelection.get()) { + setError("Error: Bi-Normal selection is empty."); + return; + } + aBiNormal = std::dynamic_pointer_cast(aBiNormalSelection->value()); + if(!aBiNormal.get()) { + // Probably it is a construction. + aBiNormal = aBiNormalSelection->context()->shape(); + } + if(!aBiNormal.get() || aBiNormal->isNull()) { + setError("Error: Bi-Normal shape is null."); + return; + } + } + + // Getting Ref and Def + std::shared_ptr aRef; + std::shared_ptr aDef; + if(aCreationMethod == "with law") { + //REFERENCE + AttributeSelectionPtr aRefSelection = selection(LAW_REFERENCE_ID()); + if(!aRefSelection.get()) { + setError("Error: Ref selection is empty."); + return; + } + aRef = std::dynamic_pointer_cast(aRefSelection->value()); + if(!aRef.get()) { + // Probably it is a construction. + aRef = aRefSelection->context()->shape(); + } + if(!aRef.get() || aRef->isNull()) { + setError("Error: Ref shape is null."); + return; + } + //DEFINITION + AttributeSelectionPtr aDefSelection = selection(LAW_DEFINITION_ID()); + if(!aDefSelection.get()) { + setError("Error: Def selection is empty."); + return; + } + aDef = std::dynamic_pointer_cast(aDefSelection->value()); + if(!aDef.get()) { + // Probably it is a construction. + aDef = aDefSelection->context()->shape(); + } + if(!aDef.get() || aDef->isNull()) { + setError("Error: Def shape is null."); + return; + } + } + + // Generating result for each shell and face. + int aResultIndex = 0; + if(aCreationMethod == "simple" || aCreationMethod == "binormal" + || aCreationMethod == "with law") { + for(ListOfShape::const_iterator anIter = aFacesList.cbegin(); anIter != aFacesList.cend(); anIter++) { + std::shared_ptr aBaseShape = *anIter; + //std::shared_ptr aBaseShape = aFaceShape; + GeomAlgoAPI_PipeApprox aPipeApproxAlgo = GeomAlgoAPI_PipeApprox(); + if(aCreationMethod == "simple"){ + aPipeApproxAlgo = GeomAlgoAPI_PipeApprox(aBaseShape, aPath); + }else if(aCreationMethod == "binormal"){ + aPipeApproxAlgo = GeomAlgoAPI_PipeApprox(aBaseShape, aPath, aBiNormal); + }else if(aCreationMethod == "with law"){ + aPipeApproxAlgo = GeomAlgoAPI_PipeApprox(aBaseShape, aPath, aDef, aRef); + } + + + /* + GeomAlgoAPI_PipeApprox aPipeApproxAlgo = aCreationMethod == "simple" ? GeomAlgoAPI_PipeApprox(aBaseShape, aEdgesList) : + GeomAlgoAPI_PipeApprox(aBaseShape, aEdgesList, aBiNormal); + */ + if(!aPipeApproxAlgo.isDone()) { + static const std::string aPrismAlgoError = "Error: Pipe algorithm failed."; + setError(aPrismAlgoError); + aResultIndex = 0; + //break; + } + // Check if shape is valid + if(!aPipeApproxAlgo.shape().get() || aPipeApproxAlgo.shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + aResultIndex = 0; + //break; + } + if(!aPipeApproxAlgo.isValid()) { + std::string aPrismAlgoError = "Error: Resulting shape is not valid."; + setError(aPrismAlgoError); + aResultIndex = 0; + //break; + } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aPipeApproxAlgo, aResultBody, aBaseShape); + setResult(aResultBody, aResultIndex); + aResultIndex++; + } + } + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_PipeApprox::loadNamingDS(GeomAlgoAPI_PipeApprox& thePipeApproxAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBasis) +{ + //load result + theResultBody->storeGenerated(theBasis, thePipeApproxAlgo.shape()); + + std::shared_ptr aSubShapes = thePipeApproxAlgo.mapOfSubShapes(); + + //Insert lateral face : Face from Edge + const std::string aLatName = "LateralFace"; + const int aLatTag = 1; + theResultBody->loadAndOrientGeneratedShapes(&thePipeApproxAlgo, theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes); + + //Insert to faces + int aToFaceIndex = 1; + const std::string aToName = "ToFace"; + int aToTag = 2; + const ListOfShape& aToFaces = thePipeApproxAlgo.toShapes(); + for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { + std::shared_ptr aToFace = *anIt; + if(aSubShapes->isBound(aToFace)) { + aToFace = aSubShapes->find(aToFace); + } + std::ostringstream aStr; + aStr << aToName << "_" << aToFaceIndex++; + theResultBody->generated(aToFace, aStr.str(), aToTag++); + } + + //Insert from faces + int aFromFaceIndex = 1; + const std::string aFromName = "FromFace"; + int aFromTag = aToTag > 10000 ? aToTag : 10000; + const ListOfShape& aFromFaces = thePipeApproxAlgo.fromShapes(); + for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { + std::shared_ptr aFromFace = *anIt; + if(aSubShapes->isBound(aFromFace)) { + aFromFace = aSubShapes->find(aFromFace); + } + std::ostringstream aStr; + aStr << aFromName << "_" << aFromFaceIndex++; + theResultBody->generated(aFromFace, aStr.str(), aFromTag++); + } +} + + + +//ListOfShape makeProfileList(ObjectPtr theProfileObjRef){ +ListOfShape makeProfileList(AttributeSelectionListPtr aFacesSelectionList){ + ListOfShape aFacesList; + //AttributeSelectionListPtr aFacesSelectionList = theProfileObjRef->data()->selectionList("profile"); + for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { + AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex); + std::shared_ptr aFaceShape = aFaceSel->value(); + if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face. + aFacesList.push_back(aFaceShape); + } else { // This may be the whole sketch result selected, check and get faces. + ResultPtr aContext = aFaceSel->context(); + std::shared_ptr aContextShape = aContext->shape(); + if(!aContextShape.get()) { + static const std::string aContextError = "Error: The selection context is bad."; + return aFacesList; + } + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(!aConstruction.get()) { + static const std::string aFaceError = "Error: Can not find basis for extrusion."; + return aFacesList; + } + int aFacesNum = aConstruction->facesNum(); + for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { + aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + aFacesList.push_back(aFaceShape); + } + } + } + + return aFacesList; +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_PipeApprox.h b/src/FeaturesPlugin/FeaturesPlugin_PipeApprox.h new file mode 100644 index 000000000..b742ae330 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_PipeApprox.h @@ -0,0 +1,105 @@ +// Copyright + +// File: FeaturesPlugin_PipeApprox.h + + +#ifndef FeaturesPlugin_PipeApprox_H_ +#define FeaturesPlugin_PipeApprox_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +class GeomAPI_Shape; +class ModelAPI_ResultBody; + +/** \class FeaturesPlugin_Pipe + * \ingroup Plugins + * \brief Feature for creation of Pipe from the planar face. + * Pipe creates the lateral faces based on edges of the base face and + * the start and end faces and/or start and end angles. + */ +class FeaturesPlugin_PipeApprox : public ModelAPI_Feature +{ + public: + /// Pipe kind. + inline static const std::string& ID() + { + static const std::string MY_PipeApprox_ID("PipeApprox"); + return MY_PipeApprox_ID; + } + + /// Attribute name of references sketch entities list, it should contain a sketch result or + /// a pair a sketch result to sketch face. + inline static const std::string& PROFILE_ID() + { + static const std::string MY_PROFILE_LIST_ID("profile"); + return MY_PROFILE_LIST_ID; + } + + /// Attribute name of an Pipe path. + inline static const std::string& PATH_OBJECT_ID() + { + static const std::string MY_PATH_ID("path_object"); + return MY_PATH_ID; + } + + /// Attribute name of Bi-Normal. + inline static const std::string& BINORMAL_ID() + { + static const std::string MY_BINORMAL_ID("binormal"); + return MY_BINORMAL_ID; + } + + inline static const std::string& LAW_REFERENCE_ID() + { + static const std::string MY_LAW_REFERENCE_ID("law_reference"); + return MY_LAW_REFERENCE_ID; + } + + inline static const std::string& LAW_DEFINITION_ID() + { + static const std::string MY_LAW_DEFINITION_ID("law_definition"); + return MY_LAW_DEFINITION_ID; + } + + /// attribute name for creation method + inline static const std::string& CREATION_METHOD() + { + static const std::string METHOD_ATTR("CreationMethod"); + return METHOD_ATTR; + } + + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_PipeApprox::ID(); + return MY_KIND; + } + + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Use plugin manager for features creation. + FeaturesPlugin_PipeApprox(); + +private: + /// Load Naming data structure of the feature to the document. + void loadNamingDS(GeomAlgoAPI_PipeApprox& thePipeApproxAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBasis); + +}; +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.cpp b/src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.cpp new file mode 100644 index 000000000..a23b9ee78 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.cpp @@ -0,0 +1,460 @@ +// Copyright + +// File: FeaturesPlugin_PipeApproxLaw.cpp + +//TODO: SORT ALL THE INCLUDES +#include "FeaturesPlugin_PipeApproxLaw.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +//??#include "ParametersPlugin_Parameter.h" +//??#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace patch +{ + template < typename T > std::string to_string( const T& n ) + { + std::ostringstream stm ; + stm << n ; + return stm.str() ; + } +} + + +static ListOfShape makeProfileList(AttributeSelectionListPtr aFacesSelectionList); + + +//for splitting string +std::vector &split(const std::string &s, char delim, std::vector &elems) { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; +} + +std::vector split(const std::string &s, char delim) { + std::vector elems; + split(s, delim, elems); + return elems; +} + + +//================================================================================================= +FeaturesPlugin_PipeApproxLaw::FeaturesPlugin_PipeApproxLaw() +{ +} + +//================================================================================================= +void FeaturesPlugin_PipeApproxLaw::initAttributes() +{ + mySelection = + std::dynamic_pointer_cast(data()->addAttribute( + PROFILE_ID(), ModelAPI_AttributeSelectionList::typeId())); + mySelection->setSelectionType("FACE"); + mySelection->setImmutable(false); + + data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId()); + + + myParameter = data()->addAttribute(VARIABLE_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(NBSECT_ID(), ModelAPI_AttributeInteger::typeId()); + data()->addAttribute(REVERSE_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(FRENET_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + +} + +//================================================================================================= +void FeaturesPlugin_PipeApproxLaw::performSketchIteration() +{ + for(int i = 0; i < myNbLaws; i++){ + const std::string & theValue = patch::to_string(myIterationMOI[i][myCPT]); //it -> devient compteur sur le vect + FeaturePtr aIterationParamFeature = ModelAPI_Feature::feature(myVectResultParameterPtr[i]); + aIterationParamFeature->data()->string("expression")->setValue(theValue); + } +} + +//================================================================================================= +void FeaturesPlugin_PipeApproxLaw::getParamLaws(GeomAlgoAPI_ParameterLaw& aParameterLawAlgo) +{ + ObjectPtr aFeatureObj = mySelection->owner(); + DocumentPtr aDocument = aFeatureObj->document(); + + bool haveParam; + + AttributeSelectionListPtr aLawsSelectionList = selectionList(VARIABLE_ID()); + myNbLaws = aLawsSelectionList->size(); + + for(int i = 0; i < myNbLaws; i++){ + AttributeSelectionPtr aFaceSel = aLawsSelectionList->value(i); + ObjectPtr aLawObj = aFaceSel->context(); + FeaturePtr aLawFeature = ModelAPI_Feature::feature(aLawObj); + + //check existence of the laws + haveParam = false; + + //get the param, and the def and ref curves + std::string aParameterName = aLawFeature->data()->string(FeaturesPlugin_ParameterLaw::VARIABLE_ID())->value(); + + int anIndex2 = 0, aSize2 = aDocument->size(ModelAPI_ResultParameter::group()); + ObjectPtr aParamObj = aDocument->object(ModelAPI_ResultParameter::group(), anIndex2); + + while(anIndex2 < aSize2 && aParamObj->data()->name() != aParameterName){ + anIndex2++; + aParamObj = aDocument->object(ModelAPI_ResultParameter::group(), anIndex2); + } + if(aParamObj->data()->name() == aParameterName) + { + ResultParameterPtr aParam = std::dynamic_pointer_cast(aParamObj); + if (aParam.get()){ + FeaturePtr aFeature = ModelAPI_Feature::feature(aParam); + haveParam = (aFeature != myParameter->owner()); + } + } + ResultParameterPtr aParam; + if (haveParam) { + aParam = std::dynamic_pointer_cast(aParamObj); + haveParam = aParam.get() != NULL; + } + if(!haveParam) + { + break; + }else{ + myVectResultParameterPtr.push_back(aParam); + + bool isReverse = + aLawFeature->data()->boolean(FeaturesPlugin_ParameterLaw::REVERSE_ID())->value(); + std::shared_ptr aDef = + aLawFeature->data()->selection(FeaturesPlugin_ParameterLaw::LAW_DEFINITION_ID())->value(); + + std::shared_ptr aRef = + aLawFeature->data()->selection(FeaturesPlugin_ParameterLaw::LAW_REFERENCE_ID())->value(); + + std::vector tempVec = aParameterLawAlgo.getVectorOfScalar(aDef, aRef, isReverse, myNbSections); + myIterationMOI.insert(std::pair>(i, tempVec)); + } + } +} + +//================================================================================================= +bool FeaturesPlugin_PipeApproxLaw::checkParamLaws() +{ + ObjectPtr aFeatureObj = mySelection->owner(); + DocumentPtr aDocument = aFeatureObj->document(); + + bool res; + + AttributeSelectionListPtr aLawsSelectionList = selectionList(VARIABLE_ID()); + myNbLaws = aLawsSelectionList->size(); + + for(int i = 0; i < myNbLaws; i++){ + AttributeSelectionPtr aFaceSel = aLawsSelectionList->value(i); + + ObjectPtr aLawObj = aFaceSel->context(); + FeaturePtr aLawFeature = ModelAPI_Feature::feature(aLawObj); + //check existence of the laws + + res = false; + + std::string aParameterName = aLawFeature->data()->string(FeaturesPlugin_ParameterLaw::VARIABLE_ID())->value(); + + int anIndex2 = 0, aSize2 = aDocument->size(ModelAPI_ResultParameter::group()); + ObjectPtr aParamObj = aDocument->object(ModelAPI_ResultParameter::group(), anIndex2); + + while(anIndex2 < aSize2 && aParamObj->data()->name() != aParameterName){ + anIndex2++; + aParamObj = aDocument->object(ModelAPI_ResultParameter::group(), anIndex2); + } + if(aParamObj->data()->name() == aParameterName) + { + ResultParameterPtr aParam = std::dynamic_pointer_cast(aParamObj); + if (aParam.get()){ + FeaturePtr aFeature = ModelAPI_Feature::feature(aParam); + + res = (aFeature != myParameter->owner()); + } + } + ResultParameterPtr aParam; + + if (res) { + aParam = std::dynamic_pointer_cast(aParamObj); + + res = aParam.get() != NULL; + } + } + return res; +} + +//================================================================================================= +void FeaturesPlugin_PipeApproxLaw::execute() +{ + int cpt = 0; + if (!myIterationMOI.empty()) { // iteration is performed + // do the iteration + // get the updated sketch + + AttributeSelectionPtr aUpdatedShapeSel = myIterationUpdatedFacesSelectionList->value(cpt); + std::shared_ptr aUpdatedShape = aUpdatedShapeSel->value(); + myIterationLOS.push_back(aUpdatedShape); + + myCPT--; + + + if (myCPT >= 0) { + // set new param to update sketch + performSketchIteration(); + return; // the execution will be called again with an updated sketch + } else { + myIterationMOI.clear(); // finish the iteration + } + } + + // Getting creation method. + std::string aCreationMethod = string(CREATION_METHOD())->value(); + + // Flags for reverse path + bool isReverse = boolean(REVERSE_ID())->value(); + + // Flags for min torsion + bool withFrenet = boolean(FRENET_ID())->value(); + + // Getting nb sections. + myNbSections = integer(NBSECT_ID())->value(); + + + // Getting path. + AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID()); + if(!aPathSelection.get()) { + setError("Error: Path selection is empty."); + return; + } + std::shared_ptr aPathShape = std::dynamic_pointer_cast(aPathSelection->value()); + if(!aPathShape.get()) { + // Probaply it is a construction. + aPathShape = aPathSelection->context()->shape(); + } + if(!aPathShape.get() || aPathShape->isNull()) { + setError("Error: Path shape is null."); + return; + } + + //Getting profile + ListOfShape aFacesList; + AttributeSelectionListPtr aFacesSelectionList = selectionList(PROFILE_ID()); + for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { + AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex); + std::shared_ptr aFaceShape = aFaceSel->value(); + if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face. + aFacesList.push_back(aFaceShape); + } else { // This may be the whole sketch result selected, check and get faces. + ResultPtr aContext = aFaceSel->context(); + std::shared_ptr aContextShape = aContext->shape(); + if(!aContextShape.get()) { + static const std::string aContextError = "Error: The selection context is bad."; + setError(aContextError); + return; + } + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(!aConstruction.get()) { + static const std::string aFaceError = "Error: Can not find basis for extrusion."; + setError(aFaceError); + return; + } + int aFacesNum = aConstruction->facesNum(); + for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { + aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + aFacesList.push_back(aFaceShape); + } + } + } + + + // Getting Bi-Normal + + std::shared_ptr aBiNormal; + if(aCreationMethod == "with binormal") { + AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID()); + if(!aBiNormalSelection.get()) { + setError("Error: Bi-Normal selection is empty."); + return; + } + aBiNormal = std::dynamic_pointer_cast(aBiNormalSelection->value()); + if(!aBiNormal.get()) { + // Probably it is a construction. + aBiNormal = aBiNormalSelection->context()->shape(); + } + if(!aBiNormal.get() || aBiNormal->isNull()) { + setError("Error: Bi-Normal shape is null."); + return; + } + } + + // Generating result for each shell and face. + int aResultIndex = 0; + //this is "fake" for loop + //we expect to only treat one face + //think I need the selectionlist to have access to sketch, not sure + for(ListOfShape::const_iterator anIter = aFacesList.cbegin(); anIter != aFacesList.cend(); anIter++) { + std::shared_ptr aBaseShape = *anIter; + GeomAlgoAPI_PipeApprox aPipeApproxLawAlgo = GeomAlgoAPI_PipeApprox(); + GeomAlgoAPI_ParameterLaw aParameterLawAlgo = GeomAlgoAPI_ParameterLaw(); + + ObjectPtr aFeatureObj = mySelection->owner(); + DocumentPtr aDocument = aFeatureObj->document(); + if(checkParamLaws()) + { + if (myIterationLOS.empty()) { // starts the iteration + myCPT = myNbSections - 1; + getParamLaws(aParameterLawAlgo); + myIterationUpdatedFacesSelectionList = aFeatureObj->data()->selectionList(PROFILE_ID()); + // init the iteration by first modification of the sketch + performSketchIteration(); + return; + } else { // perform the algo on already computed contours in the previous iteration + if(aCreationMethod == "simple"){ + aPipeApproxLawAlgo = GeomAlgoAPI_PipeApprox(myIterationLOS, aPathShape, isReverse, myNbSections, withFrenet); + } + if(aCreationMethod == "with binormal"){ + aPipeApproxLawAlgo = GeomAlgoAPI_PipeApprox(myIterationLOS, aPathShape, aBiNormal, isReverse, myNbSections/*, crossSections*/); + } + myIterationLOS.clear(); + myCPT = myNbSections - 1; + } + } + + + if(!aPipeApproxLawAlgo.isDone()) { + static const std::string aPrismAlgoError = "Error: Pipe algorithm failed."; + setError(aPrismAlgoError); + aResultIndex = 0; + //break; + } + // Check if shape is valid + if(!aPipeApproxLawAlgo.shape().get() || aPipeApproxLawAlgo.shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + aResultIndex = 0; + //break; + } + if(!aPipeApproxLawAlgo.isValid()) { + std::string aPrismAlgoError = "Error: Resulting shape is not valid."; + setError(aPrismAlgoError); + aResultIndex = 0; + //break; + } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aPipeApproxLawAlgo, aResultBody, aBaseShape); + setResult(aResultBody, aResultIndex); + aResultIndex++; + + cpt++; + } + + removeResults(aResultIndex); + +} + +//================================================================================================= +void FeaturesPlugin_PipeApproxLaw::loadNamingDS(GeomAlgoAPI_PipeApprox& thePipeApproxLawAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBasis) +{ + //load result + theResultBody->storeGenerated(theBasis, thePipeApproxLawAlgo.shape()); + + std::shared_ptr aSubShapes = thePipeApproxLawAlgo.mapOfSubShapes(); + + //Insert lateral face : Face from Edge + const std::string aLatName = "LateralFace"; + const int aLatTag = 1; + theResultBody->loadAndOrientGeneratedShapes(&thePipeApproxLawAlgo, theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes); + + //Insert to faces + int aToFaceIndex = 1; + const std::string aToName = "ToFace"; + int aToTag = 2; + const ListOfShape& aToFaces = thePipeApproxLawAlgo.toShapes(); + for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { + std::shared_ptr aToFace = *anIt; + if(aSubShapes->isBound(aToFace)) { + aToFace = aSubShapes->find(aToFace); + } + std::ostringstream aStr; + aStr << aToName << "_" << aToFaceIndex++; + theResultBody->generated(aToFace, aStr.str(), aToTag++); + } + + //Insert from faces + int aFromFaceIndex = 1; + const std::string aFromName = "FromFace"; + int aFromTag = aToTag > 10000 ? aToTag : 10000; + const ListOfShape& aFromFaces = thePipeApproxLawAlgo.fromShapes(); + for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { + std::shared_ptr aFromFace = *anIt; + if(aSubShapes->isBound(aFromFace)) { + aFromFace = aSubShapes->find(aFromFace); + } + std::ostringstream aStr; + aStr << aFromName << "_" << aFromFaceIndex++; + theResultBody->generated(aFromFace, aStr.str(), aFromTag++); + } +} + + + +ListOfShape makeProfileList(AttributeSelectionListPtr aFacesSelectionList){ + ListOfShape aFacesList; + for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) { + AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex); + std::shared_ptr aFaceShape = aFaceSel->value(); + if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face. + aFacesList.push_back(aFaceShape); + } else { // This may be the whole sketch result selected, check and get faces. + ResultPtr aContext = aFaceSel->context(); + std::shared_ptr aContextShape = aContext->shape(); + if(!aContextShape.get()) { + static const std::string aContextError = "Error: The selection context is bad."; + return aFacesList; + } + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(!aConstruction.get()) { + static const std::string aFaceError = "Error: Can not find basis for extrusion."; + return aFacesList; + } + int aFacesNum = aConstruction->facesNum(); + for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { + aFaceShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + aFacesList.push_back(aFaceShape); + } + } + } + + return aFacesList; +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.h b/src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.h new file mode 100644 index 000000000..7c575176c --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_PipeApproxLaw.h @@ -0,0 +1,146 @@ +// Copyright + +// File: FeaturesPlugin_PipeApproxLaw.h + + +#ifndef FeaturesPlugin_PipeApproxLaw_H_ +#define FeaturesPlugin_PipeApproxLaw_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +class GeomAPI_Shape; +class ModelAPI_ResultBody; + +/** \class FeaturesPlugin_Pipe + * \ingroup Plugins + * \brief Feature for creation of Pipe from the planar face. + * Pipe creates the lateral faces based on edges of the base face and + * the start and end faces and/or start and end angles. + */ +class FeaturesPlugin_PipeApproxLaw : public ModelAPI_Feature +{ + public: + /// Pipe kind. + inline static const std::string& ID() + { + static const std::string MY_PipeApproxLaw_ID("PipeApproxLaw"); + return MY_PipeApproxLaw_ID; + } + + /// Attribute name of references sketch entities list, it should contain a sketch result or + /// a pair a sketch result to sketch face. + inline static const std::string& PROFILE_ID() + { + static const std::string MY_PROFILE_LIST_ID("profile"); + return MY_PROFILE_LIST_ID; + } + + /// Attribute name of an Pipe path. + inline static const std::string& PATH_OBJECT_ID() + { + static const std::string MY_PATH_ID("path_object"); + return MY_PATH_ID; + } + + /// Attribute name of Bi-Normal. + inline static const std::string& BINORMAL_ID() + { + static const std::string MY_BINORMAL_ID("binormal"); + return MY_BINORMAL_ID; + } + + /// Attribute name of ParmLaws + inline static const std::string& VARIABLE_ID() + { + static const std::string MY_VARIABLE_ID("Parameter_laws"); + return MY_VARIABLE_ID; + } + + /// Attribute name of nb cross-sections + inline static const std::string& NBSECT_ID() + { + static const std::string MY_NBSECT_ID("nb_sect"); + return MY_NBSECT_ID; + } + + /// attribute name of flag of minimizetorsion + inline static const std::string& FRENET_ID() + { + static const std::string MY_FRENET_ID("use_Frenet"); + return MY_FRENET_ID; + } + + /// attribute name of flag of reverse direction + inline static const std::string& REVERSE_ID() + { + static const std::string MY_REVERSE_ID("reverse_direction"); + return MY_REVERSE_ID; + } + + /// attribute name for creation method + inline static const std::string& CREATION_METHOD() + { + static const std::string METHOD_ATTR("CreationMethod"); + return METHOD_ATTR; + } + + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_PipeApproxLaw::ID(); + return MY_KIND; + } + + /// Creates a new part document if needed. + FEATURESPLUGIN_EXPORT virtual void execute(); + + /// Request for initialization of data model of the feature: adding all attributes. + FEATURESPLUGIN_EXPORT virtual void initAttributes(); + + /// Use plugin manager for features creation. + FeaturesPlugin_PipeApproxLaw(); + +private: + /// Load Naming data structure of the feature to the document. + void loadNamingDS(GeomAlgoAPI_PipeApprox& thePipeApproxLawAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBasis); + + /// does the update of sketch that will call "execution" of this feature + void performSketchIteration(); + + bool checkParamLaws(); + void FeaturesPlugin_PipeApproxLaw::getParamLaws(GeomAlgoAPI_ParameterLaw& aParameterLawAlgo); + + AttributeSelectionListPtr mySelection; + AttributePtr myParameter; + + /// fields needed for iteration of updated sketch + std::map> myIterationMOI; ///< empty means iteration is not started + + std::vector myVectResultParameterPtr; + + AttributeSelectionListPtr myIterationUpdatedFacesSelectionList; + ListOfShape myIterationLOS; + + int myCPT; + int myNbLaws; + int myNbSections; +}; +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 54b0021f0..0f210e69b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -21,6 +21,10 @@ #include #include +#include +#include +#include + #include #include @@ -60,6 +64,8 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() new FeaturesPlugin_ValidatorUnionSelection); aFactory->registerValidator("FeaturesPlugin_ValidatorUnionArguments", new FeaturesPlugin_ValidatorUnionArguments); + aFactory->registerValidator("FeaturesPlugin_ValidatorParameterLaw", + new FeaturesPlugin_ValidatorParameterLaw); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -99,6 +105,12 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new FeaturesPlugin_RemoveSubShapes); } else if (theFeatureID == FeaturesPlugin_Union::ID()) { return FeaturePtr(new FeaturesPlugin_Union); + } else if (theFeatureID == FeaturesPlugin_ParameterLaw::ID()) { + return FeaturePtr(new FeaturesPlugin_ParameterLaw); + }else if (theFeatureID == FeaturesPlugin_PipeApproxLaw::ID()) { + return FeaturePtr(new FeaturesPlugin_PipeApproxLaw); + }else if (theFeatureID == FeaturesPlugin_PipeApprox::ID()) { + return FeaturePtr(new FeaturesPlugin_PipeApprox); } // feature of such kind is not found diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index c77f516b6..b0b4cba2d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -782,3 +782,49 @@ bool FeaturesPlugin_ValidatorUnionArguments::isNotObligatory(std::string theFeat { return false; } + +//================================================================================================== +bool FeaturesPlugin_ValidatorParameterLaw::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const +{ + //SEEMS THIS DOES NOTHING SPECIAL!! + bool isLawValid = true; + //if(theArguments.empty()) { + // theError = "Error: Validator parameters is empty."; + // return false; + //} + std::string anAttributeType = theAttribute->attributeType(); + std::string anAttirbuteID = theAttribute->id(); + if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aSelectionListAttr = + std::dynamic_pointer_cast(theAttribute); + // all context objects should be sketch entities + for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize ; i++) { + AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i); + ObjectPtr anObject = aSelectAttr->context(); + if (!anObject.get()) + isLawValid = false; + else { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + isLawValid = true; + } + } + } + if (anAttributeType == ModelAPI_AttributeSelection::typeId()) { + AttributeSelectionPtr aSelectAttr = + std::dynamic_pointer_cast(theAttribute); + ObjectPtr anObject = aSelectAttr->context(); + // a context of the selection attribute is a feature result. It can be a case when the result + // of the feature is null, e.g. the feature is modified and has not been executed yet. + // The validator returns an invalid result here. The case is an extrusion built on a sketch + // feature. A new sketch element creation leads to an empty result. + if (!anObject.get()) + isLawValid = false; + else { + FeaturePtr aFeature = ModelAPI_Feature::feature(anObject); + isLawValid = true; + } + } + return isLawValid; +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h index ce3fe042e..4f853042d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -202,4 +202,15 @@ class FeaturesPlugin_ValidatorUnionArguments: public ModelAPI_FeatureValidator virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); }; +class FeaturesPlugin_ValidatorParameterLaw: public ModelAPI_AttributeValidator +{ +public: + //! \return true if attribute has selection type listed in the parameter arguments. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + Events_InfoMessage& theError) const; +}; #endif diff --git a/src/FeaturesPlugin/parameterlaw_widget.xml b/src/FeaturesPlugin/parameterlaw_widget.xml new file mode 100644 index 000000000..d92e464bd --- /dev/null +++ b/src/FeaturesPlugin/parameterlaw_widget.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/FeaturesPlugin/pipeapprox_widget.xml b/src/FeaturesPlugin/pipeapprox_widget.xml new file mode 100644 index 000000000..58b401fd3 --- /dev/null +++ b/src/FeaturesPlugin/pipeapprox_widget.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FeaturesPlugin/pipeapproxlaw_widget.xml b/src/FeaturesPlugin/pipeapproxlaw_widget.xml new file mode 100644 index 000000000..feb2bd414 --- /dev/null +++ b/src/FeaturesPlugin/pipeapproxlaw_widget.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 6a5cba33d..61ad6ecb0 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -28,6 +28,17 @@ + + + + + + + + + + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GeomAPI.h" +#include "GeomAPI_Edge.h" +#include "GeomAPI_Wire.h" +#include "GeomAPI_Pnt.h" +#include "GeomAPI_Dir.h" +#include "GeomAPI_Ax3.h" +#include "GeomAPI_Curve.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GeomAlgoAPI_Placement.h" +#include +#include "GeomAlgoAPI_MakeShape.h" + +#include +#include +#include +#include +#include + +//#define NB_SECT 50 + +/// \return solid created from face or shell. +static TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape); + +//================================================================================================= +GeomAlgoAPI_ParameterLaw::GeomAlgoAPI_ParameterLaw() +{ +} + +//================================================================================================= +GeomAlgoAPI_ParameterLaw::GeomAlgoAPI_ParameterLaw(std::shared_ptr theDefShape, + std::shared_ptr theRefShape, + bool isReverse) +{ + build(theDefShape, theRefShape, isReverse); +} + +//================================================================================================= +void GeomAlgoAPI_ParameterLaw::build(const std::shared_ptr& theDefShape, + const std::shared_ptr& theRefShape, + const bool isReverse) +{ + if(!theDefShape || !theRefShape) { + return; + } + + // Getting Def + TopoDS_Edge aDefEdge; + if(theDefShape->shapeType() == GeomAPI_Shape::EDGE) { + aDefEdge = TopoDS::Edge(theDefShape->impl()); + } + // Getting Ref + TopoDS_Edge aRefEdge; + if(theRefShape->shapeType() == GeomAPI_Shape::EDGE) { + aRefEdge = TopoDS::Edge(theRefShape->impl()); + } + + + //COMPUTE RESULT + TopoDS_Shape aResult; + + double defFirst, defLast, refFirst, refLast; + Handle(Geom_Curve) aDefCurve = BRep_Tool::Curve(aDefEdge, defFirst, defLast); + if(isReverse) + { + double aTemp = defFirst; + defFirst = defLast; + defLast = aTemp; + } + + //recover Ref line + Handle(Geom_Curve) aRefCurve = BRep_Tool::Curve(aRefEdge, refFirst, refLast); + GeomAdaptor_Curve aRefAdaptorCurve = GeomAdaptor_Curve(aRefCurve); + + gp_Pnt rFP, rLP; + gp_XYZ rF, rL; + aRefCurve->D0(refFirst, rFP); + aRefCurve->D0(refLast, rLP); + rF = rFP.XYZ(); + rL = rLP.XYZ(); + rL.Subtract(rF); + gp_Lin aRefLin = gp_Lin(rFP, rL); + refFirst = aRefAdaptorCurve.FirstParameter(); + refLast = aRefAdaptorCurve.LastParameter(); + + gp_Pnt DF; + aDefCurve->D0(defFirst, DF); + + + //to store edges for the final result + BRepBuilderAPI_MakeEdge mkEdge; + TopTools_ListOfShape aEL; + + //project First Point of the def curve on the ref line + // to get the translation vector + double Tol = 1.0e-10; + Extrema_ExtPElC aProjDF = Extrema_ExtPElC(DF, aRefLin, Tol, refFirst, refLast); + int nbDMin = aProjDF.NbExt(); + nbDMin++; + int k = 1; + while(k < nbDMin && !aProjDF.IsMin(k)) + { + k++; + } + + Extrema_POnCurv DFPOC = aProjDF.Point(k); + gp_Pnt DFP = DFPOC.Value(); + + //get translation vector + // and make the translation transformation + // then do the transformation and recover curve. + gp_Vec aTransVec = rF - DFP.XYZ(); + gp_Trsf aTrans = gp_Trsf(); + aTrans.SetTranslation(aTransVec); + + TopoDS_Edge aTransDefEdge; + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aDefEdge, aTrans, false); + if(aBuilder) { + if(aBuilder->IsDone()) { + aTransDefEdge = TopoDS::Edge(aBuilder->Shape()); + } + } + + aEL.Append(aTransDefEdge); + double tdFirst, tdLast; + Handle(Geom_Curve) aTransDefCurve = BRep_Tool::Curve(aTransDefEdge, tdFirst, tdLast); + if(isReverse) + { + double aTemp = tdFirst; + tdFirst = tdLast; + tdLast = aTemp; + } + + //now project last point of the transDefEdge + // then make the needed edges for final result + gp_Pnt TDF, TDL; + aTransDefCurve->D0(tdLast, TDL); + aTransDefCurve->D0(tdFirst, TDF); + Extrema_ExtPElC aProjDL = Extrema_ExtPElC(TDL, aRefLin, Tol, refFirst, refLast); + nbDMin = aProjDF.NbExt(); + nbDMin++; + k = 1; + while(k < nbDMin && !aProjDF.IsMin(k)) + { + k++; + } + Extrema_POnCurv DLPOC = aProjDL.Point(k); + gp_Pnt DLP = DLPOC.Value(); + + mkEdge = BRepBuilderAPI_MakeEdge(rFP, DLP); + if(mkEdge.IsDone()) + aEL.Append(mkEdge.Edge()); + mkEdge = BRepBuilderAPI_MakeEdge(DLP, TDL); + if(mkEdge.IsDone()) + aEL.Append(mkEdge.Edge()); + mkEdge = BRepBuilderAPI_MakeEdge(TDF, rFP); + if(mkEdge.IsDone()) + aEL.Append(mkEdge.Edge()); + + BRepBuilderAPI_MakeWire mkWire; + mkWire.Add(aEL); + BRepBuilderAPI_MakeFace mkFace; + if(mkWire.IsDone()) + mkFace = BRepBuilderAPI_MakeFace(mkWire.Wire()); + if(mkFace.IsDone()) + aResult = mkFace.Face(); + + // Setting result. + if(aResult.IsNull()) { + return; + } + + + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +} + + + +//================================================================================================= +std::vector GeomAlgoAPI_ParameterLaw::getVectorOfScalar(const std::shared_ptr& theDef, + const std::shared_ptr& theRef, + const bool isReverse, + const int nbSect) +{ + std::vector result; + + // Getting law + // DEF + TopoDS_Edge aDefEdge; + if(theDef->shapeType() == GeomAPI_Shape::EDGE) { + aDefEdge = TopoDS::Edge(theDef->impl()); + } + // REF + TopoDS_Edge aRefEdge; + if(theRef->shapeType() == GeomAPI_Shape::EDGE) { + aRefEdge = TopoDS::Edge(theRef->impl()); + } + + double d, dFirst, dLast, rFirst, rLast; + + //recover Def curve + Handle(Geom_Curve) aDefCurve = BRep_Tool::Curve(aDefEdge, dFirst, dLast); + if(isReverse) + { + //aPathCurve = aPathCurve->Reversed(); + double aTemp = dFirst; + dFirst = dLast; + dLast = aTemp; + } + d = dFirst; + const double dStep = abs(dLast - dFirst) / (nbSect - 1); + + double coeffReverse = 1.0; + if(isReverse) + { + coeffReverse = -1.0; + } + + //recover Ref line + Handle(Geom_Curve) aRefCurve = BRep_Tool::Curve(aRefEdge, rFirst, rLast); + GeomAdaptor_Curve aRefAdaptorCurve = GeomAdaptor_Curve(aRefCurve); + + gp_Pnt rFP, rLP; + gp_XYZ rF, rL; + aRefCurve->D0(rFirst, rFP); + aRefCurve->D0(rLast, rLP); + rF = rFP.XYZ(); + rL = rLP.XYZ(); + rL.Subtract(rF); + gp_Lin aRefLin = gp_Lin(rFP, rL); + rFirst = aRefAdaptorCurve.FirstParameter(); + rLast = aRefAdaptorCurve.LastParameter(); + + gp_Pnt D; + + for (int i = 0; i < nbSect; ++i) + { + //get value for param + //will calculate from law + + aDefCurve->D0(d, D); + double Tol = 1.0e-10; + Extrema_ExtPElC aCalcD = Extrema_ExtPElC(D, aRefLin, Tol, rFirst, rLast); + int nbDMin = aCalcD.NbExt(); + nbDMin++; + int k = 1; + while(k < nbDMin && !aCalcD.IsMin(k)) + { + k++; + } + double ii = aCalcD.SquareDistance(k); + ii = sqrt(ii); + result.push_back(ii); + + d+= (coeffReverse*dStep); + } + + return result; +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.h b/src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.h new file mode 100644 index 000000000..6e9c6d2c7 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ParameterLaw.h @@ -0,0 +1,40 @@ +// Copyright + +// File: GeomAlgoAPI_ParameterLaw.h +// Created: +// Author: + +#ifndef GeomAlgoAPI_ParameterLaw_H_ +#define GeomAlgoAPI_ParameterLaw_H_ + +#include +#include +#include +#include +#include +#include +#include + + +class GeomAlgoAPI_ParameterLaw : public GeomAlgoAPI_MakeSweep +{ +public: + + GEOMALGOAPI_EXPORT GeomAlgoAPI_ParameterLaw(); + + GEOMALGOAPI_EXPORT GeomAlgoAPI_ParameterLaw(std::shared_ptr theDefShape, + std::shared_ptr theRefShape, + bool isReverse); + + GEOMALGOAPI_EXPORT std::vector getVectorOfScalar(const std::shared_ptr& theDef, + const std::shared_ptr& theRef, + const bool isReverse, + const int nbSect); + +private: + /// Builds resulting shape. + void build(const std::shared_ptr& theDef, + const std::shared_ptr& theRef, + const bool isReverse); +}; +#endif \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.cpp new file mode 100644 index 000000000..05d4bcea2 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.cpp @@ -0,0 +1,1107 @@ +// Copyright + +// File: GeomAlgoAPI_PipeApprox.cpp + + +#include "GeomAlgoAPI_PipeApprox.h" + +//trier les include un jour... +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GeomConvert_ApproxCurve.hxx" +#include "Geom_BSplineCurve.hxx" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GeomAPI.h" +#include "GeomAPI_Edge.h" +#include "GeomAPI_Wire.h" +#include "GeomAPI_Pnt.h" +#include "GeomAPI_Dir.h" +#include "GeomAPI_Ax3.h" +#include "GeomAPI_Curve.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "GeomAlgoAPI_Placement.h" +#include +#include "GeomAlgoAPI_MakeShape.h" + +#include +#include +#include +#include +#include + +#include + +//the define are only for the pipe not using ParamLaws +#define THRUSECT +#define NB_SECT 50 + +//based on the GeomAlgoAPI_Revolution + +/// \return solid created from face or shell. +static TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape); + +/// to make wire from a face after transformation, to use in thruSections +static TopoDS_Wire makeWireFromTransf(const TopoDS_Shape &theSourceShape, + gp_Trsf theTrsf); + +//================================================================================================= +// Constructors +//================================================================================================= +//================================================================================================= +GeomAlgoAPI_PipeApprox::GeomAlgoAPI_PipeApprox() +{ +} + +//================================================================================================= +GeomAlgoAPI_PipeApprox::GeomAlgoAPI_PipeApprox(std::shared_ptr theProfileShape, + std::shared_ptr thePathShape) +{ + build(theProfileShape, thePathShape); +} + +//================================================================================================= +GeomAlgoAPI_PipeApprox::GeomAlgoAPI_PipeApprox(std::shared_ptr theProfileShape, + std::shared_ptr thePathShape, + std::shared_ptr theBiNormal) +{ + build(theProfileShape, thePathShape, theBiNormal); +} + +//================================================================================================= +GeomAlgoAPI_PipeApprox::GeomAlgoAPI_PipeApprox(std::shared_ptr theProfileShape, + std::shared_ptr thePathShape, + std::shared_ptr theDef, + std::shared_ptr theRef) +{ + build(theProfileShape, thePathShape, theDef, theRef); +} + + +//================================================================================================= +GeomAlgoAPI_PipeApprox::GeomAlgoAPI_PipeApprox(ListOfShape theProfileShapeList, + std::shared_ptr thePath, + bool isReverse, + int nbSect, + bool withFrenet) +{ + build(theProfileShapeList, thePath, isReverse, nbSect, withFrenet); +} + +//================================================================================================= +GeomAlgoAPI_PipeApprox::GeomAlgoAPI_PipeApprox(ListOfShape theProfileShapeList, + std::shared_ptr thePath, + std::shared_ptr theBinormal, + bool isReverse, + int nbSect) +{ + build(theProfileShapeList, thePath, theBinormal, isReverse, nbSect); +} + + +//================================================================================================= +// BUILD() when doing simple pipe with ThruSect +//================================================================================================= + +//================================================================================================= +void GeomAlgoAPI_PipeApprox::build(const std::shared_ptr& theProfileShape, + const std::shared_ptr& thePathShape) +{ + if(!theProfileShape || !thePathShape) { + return; + } + + // Getting profile. + TopoDS_Face aProfileFace = TopoDS::Face(theProfileShape->impl()); + + // Getting path + const TopoDS_Shape& aPathShape = thePathShape->impl(); + TopoDS_Edge aPathEdge; + if(thePathShape->shapeType() == GeomAPI_Shape::EDGE) { + aPathEdge = TopoDS::Edge(thePathShape->impl()); + } + + //COMPUTE RESULT + TopoDS_Shape aResult; + double u, aFirst, aLast; + + //recover curve + aPathEdge.Oriented(TopAbs_FORWARD ); + Handle(Geom_Curve) aPathCurve = BRep_Tool::Curve(aPathEdge, aFirst, aLast); + + u = aFirst; + const double uStep = (aLast - aFirst) / (NB_SECT - 1); + +#ifdef THRUSECT + const Standard_Boolean isSolid = Standard_True; + const Standard_Boolean isRuled = Standard_False; + const Standard_Real pres3d = 1.0e-02; + + //building thrusection algo) + BRepOffsetAPI_ThruSections* aGenerator = new BRepOffsetAPI_ThruSections(isSolid, isRuled, pres3d); + if(!aGenerator) { + return; + } + aGenerator->SetSmoothing(Standard_True); + aGenerator->SetMaxDegree(5); + aGenerator->CheckCompatibility(Standard_False); +#else + std::shared_ptr aCompoundResult; + std::list > aCompoundResultList; +#endif + + //iterating on sections + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Pnt P; + gp_Vec T, N, Vx; + + aPathCurve->D2(u, P, T, N); + Vx = T ^ N; //Vx should be in the plane of (P,D1,D2) so that (P,D1,Vx) is orthogonal + Vx = Vx ^ T; + + gp_Ax3 gp_Ax3_0(P, T, Vx); + + for (int i = 0; i < NB_SECT; ++i) + { + u += uStep; + aPathCurve->D2(u, P, T, N); + Vx = T ^ N; + Vx = Vx ^ T; + + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + + aWire = makeWireFromTransf(aProfileFace, aTrsf); + + + // Add section to skinner +#ifdef THRUSECT + aGenerator->AddWire(aWire); +#else + std::shared_ptr aForCompoundShape(new GeomAPI_Shape); + aForCompoundShape->setImpl(new TopoDS_Shape(aWire)); + aCompoundResultList.push_back(aForCompoundShape); +#endif + } +#ifdef THRUSECT + aGenerator->Build(); + + if (!aGenerator->IsDone()){ + return; + } + + aResult = aGenerator->Shape(); + + // Setting naming. + // JE SAIS PAS + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aGenerator->FirstShape())); + aToShape->setImpl(new TopoDS_Shape(aGenerator->LastShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + if(aResult.IsNull()) { + return; + } + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +#else + aCompoundResult = GeomAlgoAPI_CompoundBuilder::compound(aCompoundResultList); + this->setShape(aCompoundResult); + this->setDone(true); +#endif +} + +//================================================================================================= +void GeomAlgoAPI_PipeApprox::build(const std::shared_ptr& theProfileShape, + const std::shared_ptr& thePathShape, + const std::shared_ptr& theBiNormal) +{ + if(!theProfileShape || !thePathShape || !theBiNormal) { + return; + } + + // Getting profile. + TopoDS_Face aProfileFace = TopoDS::Face(theProfileShape->impl()); + + // Getting path + + const TopoDS_Shape& aPathShape = thePathShape->impl(); + TopoDS_Edge aPathEdge; + if(thePathShape->shapeType() == GeomAPI_Shape::EDGE) { + aPathEdge = TopoDS::Edge(thePathShape->impl()); + } + + // Getting binormal + + TopoDS_Shape aBiNormalShape = theBiNormal->impl(); + + TopoDS_Edge aBiNormalEdge = TopoDS::Edge(aBiNormalShape); + double aFirst, aLast; + Handle(Geom_Curve) aBiNormalCurve = BRep_Tool::Curve(aBiNormalEdge, aFirst, aLast); + Handle(Geom_Line) aBiNormalLine = Handle(Geom_Line)::DownCast(aBiNormalCurve); + + gp_Dir aBiNormalDir = aBiNormalLine->Lin().Direction(); + + + //COMPUTE RESULT + TopoDS_Shape aResult; + + double u; + //recover curve + aPathEdge.Oriented(TopAbs_FORWARD ); + + Handle(Geom_Curve) aPathCurve = BRep_Tool::Curve(aPathEdge, aFirst, aLast); + + u = aFirst; + const double uStep = (aLast - aFirst) / (NB_SECT - 1); + +#ifdef THRUSECT + const Standard_Boolean isSolid = Standard_True; + const Standard_Boolean isRuled = Standard_False; + const Standard_Real pres3d = 1.0e-02; + + //building thrusection algo) + BRepOffsetAPI_ThruSections* aGenerator = new BRepOffsetAPI_ThruSections(isSolid, isRuled, pres3d); + if(!aGenerator) { + return; + } + aGenerator->SetSmoothing(Standard_True); + aGenerator->SetMaxDegree(5); + aGenerator->CheckCompatibility(Standard_False); +#else + std::shared_ptr aCompoundResult; + std::list > aCompoundResultList; +#endif + + //iterating on sections + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Pnt P; + gp_Vec T, Vx; + + aPathCurve->D1(u, P, T); + //Vx should be in the plane of (P,D1,D2) so that (P,D1,Vx) is orthogonal + //if D2 undefined, replace it with "binormal" + Vx = T ^ aBiNormalDir; + Vx = Vx ^ T; + + gp_Ax3 gp_Ax3_0(P, T, Vx); + + for (int i = 0; i < NB_SECT; ++i) + { + u += uStep; + aPathCurve->D1(u, P, T); + Vx = T ^ aBiNormalDir; + Vx = Vx ^ T; + + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + + aWire = makeWireFromTransf(aProfileFace, aTrsf); + + + // Add section to skinner +#ifdef THRUSECT + aGenerator->AddWire(aWire); +#else + std::shared_ptr aForCompoundShape(new GeomAPI_Shape); + aForCompoundShape->setImpl(new TopoDS_Shape(aWire)); + aCompoundResultList.push_back(aForCompoundShape); +#endif + } +#ifdef THRUSECT + aGenerator->Build(); + + if (!aGenerator->IsDone()){ + return; + } + + aResult = aGenerator->Shape(); + + // Setting naming. + // JE SAIS PAS + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aGenerator->FirstShape())); + aToShape->setImpl(new TopoDS_Shape(aGenerator->LastShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + if(aResult.IsNull()) { + return; + } + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +#else + aCompoundResult = GeomAlgoAPI_CompoundBuilder::compound(aCompoundResultList); + this->setShape(aCompoundResult); + this->setDone(true); +#endif +} + +//================================================================================================= +// BUILD() when using a law directly defined in the feature (pipeapprox) +//================================================================================================= + +//================================================================================================= +void GeomAlgoAPI_PipeApprox::build(const std::shared_ptr& theProfileShape, + const std::shared_ptr& thePathShape, + const std::shared_ptr& theDef, + const std::shared_ptr& theRef) +{ + if(!theProfileShape || !thePathShape || !theDef || !theRef) { + return; + } + + // Getting profile. + TopoDS_Face aProfileFace = TopoDS::Face(theProfileShape->impl()); + + // Getting path + //const TopoDS_Shape& aPathShape = thePathShape->impl(); + TopoDS_Edge aPathEdge; + if(thePathShape->shapeType() == GeomAPI_Shape::EDGE) { + aPathEdge = TopoDS::Edge(thePathShape->impl()); + } + + // Getting law + // DEF + TopoDS_Edge aDefEdge; + if(theDef->shapeType() == GeomAPI_Shape::EDGE) { + aDefEdge = TopoDS::Edge(theDef->impl()); + } + // REF + TopoDS_Edge aRefEdge; + if(theRef->shapeType() == GeomAPI_Shape::EDGE) { + aRefEdge = TopoDS::Edge(theRef->impl()); + } + + //COMPUTE RESULT + TopoDS_Shape aResult; + + double u, aFirst, aLast; + double d, dFirst, dLast, rFirst, rLast; + //recover curve + aPathEdge.Oriented(TopAbs_FORWARD ); + Handle(Geom_Curve) aPathCurve = BRep_Tool::Curve(aPathEdge, aFirst, aLast); + + u = aFirst; + const double uStep = (aLast - aFirst) / (NB_SECT - 1); + + //recover Def curve + Handle(Geom_Curve) aDefCurve = BRep_Tool::Curve(aDefEdge, dFirst, dLast); + d = dFirst; + const double dStep = (dLast - dFirst) / (NB_SECT - 1); + + //recover Ref line + Handle(Geom_Curve) aRefCurve = BRep_Tool::Curve(aRefEdge, rFirst, rLast); + GeomAdaptor_Curve aRefAdaptorCurve = GeomAdaptor_Curve(aRefCurve); + gp_Pnt rFP, rLP; + gp_XYZ rF, rL; + aRefCurve->D0(rFirst, rFP); + aRefCurve->D0(rLast, rLP); + rF = rFP.XYZ(); + rL = rLP.XYZ(); + rL.Subtract(rF); + gp_Lin aRefLin = gp_Lin(rFP, rL); + rFirst = aRefAdaptorCurve.FirstParameter(); + rLast = aRefAdaptorCurve.LastParameter(); + +#ifdef THRUSECT + const Standard_Boolean isSolid = Standard_True; + const Standard_Boolean isRuled = Standard_False; + const Standard_Real pres3d = 1.0e-02; + + //building thrusection algo) + BRepOffsetAPI_ThruSections* aGenerator = new BRepOffsetAPI_ThruSections(isSolid, isRuled, pres3d); + if(!aGenerator) { + return; + } + aGenerator->SetSmoothing(Standard_True); + aGenerator->SetMaxDegree(5); + aGenerator->CheckCompatibility(Standard_False); +#else + std::shared_ptr aCompoundResult; + std::list > aCompoundResultList; +#endif + + //iterating on sections + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Trsf bTrsf = gp_Trsf(); + gp_Pnt P, D, C; + gp_Vec T, N, Vx; + + aPathCurve->D2(u, P, T, N); + //Vx should be in the plane of (P,D1,D2) so that (P,D1,Vx) is orthogonal + Vx = T ^ N; + Vx = Vx ^ T; + + gp_Ax3 gp_Ax3_0(P, T, Vx); + + //get center for scaling + GProp_PGProps aCConstr = GProp_PGProps(); + TopExp_Explorer aVertexExp(aProfileFace, TopAbs_VERTEX); + for (; aVertexExp.More(); aVertexExp.Next()) { + TopoDS_Vertex aVS = TopoDS::Vertex(aVertexExp.Current()); + gp_Pnt aP = BRep_Tool::Pnt(aVS); + aCConstr.AddPoint(aP); + } + C = aCConstr.CentreOfMass(); + + for (int i = 0; i < NB_SECT; ++i) + { + u += uStep; + aPathCurve->D2(u, P, T, N); + Vx = T ^ N; + Vx = Vx ^ T; + + //set scale + //will calculate from law + d+= dStep; + aDefCurve->D0(d, D); + double Tol = 1.0e-10; + Extrema_ExtPElC aCalcD = Extrema_ExtPElC(D, aRefLin, Tol, rFirst, rLast); + int nbDMin = aCalcD.NbExt(); + nbDMin++; + int k = 1; + while(k < nbDMin && !aCalcD.IsMin(k)) + { + k++; + } + double ii = aCalcD.SquareDistance(k); + ii = sqrt(ii); + //for the scale maybe get init "length" to divide ii by it? + + bTrsf.SetScale(C, ii); + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aProfileFace, bTrsf, true); + + TopoDS_Shape aScaledPorfileFace = aBuilder->Shape(); + + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + aWire = makeWireFromTransf(aScaledPorfileFace, aTrsf); + + + // Add section to skinner +#ifdef THRUSECT + aGenerator->AddWire(aWire); +#else + std::shared_ptr aForCompoundShape(new GeomAPI_Shape); + aForCompoundShape->setImpl(new TopoDS_Shape(aWire)); + aCompoundResultList.push_back(aForCompoundShape); +#endif + } +#ifdef THRUSECT + aGenerator->Build(); + + if (!aGenerator->IsDone()){ + return; + } + + aResult = aGenerator->Shape(); + + // Setting naming. + // JE SAIS PAS + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aGenerator->FirstShape())); + aToShape->setImpl(new TopoDS_Shape(aGenerator->LastShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + if(aResult.IsNull()) { + return; + } + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +#else + aCompoundResult = GeomAlgoAPI_CompoundBuilder::compound(aCompoundResultList); + this->setShape(aCompoundResult); + this->setDone(true); +#endif +} + +//================================================================================================= +// BUILD() when using paramLaws +//================================================================================================= + +//================================================================================================= + +void GeomAlgoAPI_PipeApprox::build(const ListOfShape& theProfileShapeList, + const std::shared_ptr& thePathShape, + const bool isReverse, + const int nbSect, + const bool withFrenet) +{ + if(!theProfileShapeList.size() || !thePathShape) { + return; + } + + double coeffReverse = 1.0; + if(isReverse) + { + coeffReverse = -1.0; + } + + //To COMPUTE the RESULT + TopoDS_Shape aResult; + + BRepOffsetAPI_ThruSections* aGenerator; + + const Standard_Boolean isSolid = Standard_True; + const Standard_Boolean isRuled = Standard_False; + const Standard_Real pres3d = 1.0e-02; + + aGenerator = new BRepOffsetAPI_ThruSections(isSolid, isRuled, pres3d); + if(!aGenerator) { + return; + } + aGenerator->SetSmoothing(Standard_True); + aGenerator->SetMaxDegree(5); + aGenerator->CheckCompatibility(Standard_False); + + //used for dump + std::shared_ptr aCompoundResult; + std::shared_ptr aCompoundPointResult; + std::list > aCompoundResultList; + std::list > aCompoundPointList; + + // Getting path + double u, aFirst, aLast, uStep; + TopoDS_Edge aPathEdge; + TopoDS_Wire aPathWire; + Handle(Geom_Curve) aPathCurve; + + if(thePathShape->shapeType() == GeomAPI_Shape::EDGE) { + aPathEdge = TopoDS::Edge(thePathShape->impl()); + //recover curve + + aPathCurve = BRep_Tool::Curve(aPathEdge, aFirst, aLast); + if(isReverse) + { + double aTemp = aFirst; + aFirst = aLast; + aLast = aTemp; + } + + u = aFirst; + uStep = abs(aLast - aFirst) / (nbSect - 1); + + //iterating on sections + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Pnt P; + gp_Vec T, N, Vx; + double Tol = 1.0e-10; + + //Vx should be in the plane of (P,D1,D2) so that (P,D1,Vx) is orthogonal + aPathCurve->D2(u, P, T, N); + if(!withFrenet && (N.X() == 0) && (N.Y() == 0) && (N.Z() == 0)) + { + //no 2nd derivative to help find a normal oriented towards the curvature + //use random orthogonal vecotr to T + N.SetX(-T.Y()); + N.SetY(T.X()); + N.SetZ(0.0); + + Vx = N ^ T; + Vx = T ^ Vx; + + } + else + { + //use standard Frenet + + //need to add error management... + Vx = N ^ T; + Vx = T ^ Vx; + //currently force "crash", which means need for binormal, + } + + gp_Ax3 gp_Ax3_0(P, T, Vx); + + + for(ListOfShape::const_reverse_iterator anIter = theProfileShapeList.crbegin(); anIter != theProfileShapeList.crend(); anIter++) { + const TopoDS_Face aProfile = TopoDS::Face((*anIter)->impl()); + if(withFrenet) + { + //normal frenet frame + aPathCurve->D2(u, P, T, N); + Vx = N ^ T; + Vx = T ^ Vx; + } + else + { + //iterative placement of the frames + //based on http://webhome.cs.uvic.ca/~blob/courses/305/notes/pdf/ref-frames.pdf + //might need to be checked + //process from lines 816-837 is valid (tested and debugged) + //and work based on global transformation from start to actual and not iterative + gp_Vec aux; + aPathCurve->D1(u, P, aux); + if (T.IsParallel(aux, Tol)) + { + if(T.IsOpposite(aux, Tol)) + { + Vx.Reverse(); + } + } + else + { + gp_Vec cross(T); + cross.Cross(aux); + double alpha = T.AngleWithRef(aux, cross); + gp_Ax1 axe(gp::Origin(), cross.XYZ()); + + //have T and Vx for the new frame + Vx.Rotate(axe, alpha); + } + T = aux; + } + + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + aWire = makeWireFromTransf(aProfile, aTrsf); + + + aGenerator->AddWire(aWire); + + //for dump + std::shared_ptr aForCompoundShape(new GeomAPI_Shape); + aForCompoundShape->setImpl(new TopoDS_Shape(aWire)); + aCompoundResultList.push_back(aForCompoundShape); + // + + u += (coeffReverse*uStep); + } + }else if(thePathShape->shapeType() == GeomAPI_Shape::WIRE){ + aPathWire = TopoDS::Wire(thePathShape->impl()); + BRepTools::Write(aPathWire, "C:/Users/occ/Desktop/pathDump.brep"); + + Handle(BRepAdaptor_HCompCurve) aPathCompCurve = new (BRepAdaptor_HCompCurve) (aPathWire); + + Standard_Real aTol = Precision::Confusion(); + GeomAbs_Shape aContinuity = GeomAbs_C2 /*highest supported continuity*/; + Standard_Integer aMaxSeg = 10000, /*max number of spans*/ + aMaxDeg = 9; /*max degree, consistent with settings in Algo*/ + GeomConvert_ApproxCurve anApproxPath (aPathCompCurve, aTol, aContinuity, aMaxSeg, aMaxDeg); + Handle(Geom_BSplineCurve) aBSplinePath = anApproxPath.Curve(); + BRepBuilderAPI_MakeEdge * aBE = new BRepBuilderAPI_MakeEdge(aBSplinePath); + TopoDS_Edge aBSE = aBE->Edge(); + BRepTools::Write(aBSE, "C:/Users/occ/Desktop/pathBspline.brep"); + aFirst = aBSplinePath->FirstParameter(); + aLast = aBSplinePath->LastParameter(); + + if(isReverse) + { + double aTemp = aFirst; + aFirst = aLast; + aLast = aTemp; + } + + u = aFirst; + uStep = abs(aLast - aFirst) / (nbSect - 1); + + //iterating on sections + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Trsf bTrsf = gp_Trsf(); + gp_Pnt P; + gp_Vec T, N, Vx; + gp_Ax1 axe0; + double Tol = 1.0e-10; + + //Vx should be in the plane of (P,D1,D2) so that (P,D1,Vx) is orthogonal + aBSplinePath->D2(u, P, T, N); + + if(!withFrenet && (N.X() == 0) && (N.Y() == 0) && (N.Z() == 0)) + { + //no 2nd derivative to help find a normal oriented towards the curvature + //use random orthogonal vecotr to T + if(T.X() == 0) + { + N.SetX(0.0); + N.SetY(-T.Z()); + N.SetZ(T.Y()); + }else if (T.Y() == 0) + { + N.SetX(-T.Z()); + N.SetY(0.0); + N.SetZ(T.X()); + } + else + { + N.SetX(-T.Y()); + N.SetY(T.X()); + N.SetZ(0.0); + } + //can first derivative be null ? assume not + Vx = N ^ T; + axe0 = gp_Ax1(gp::Origin(), Vx.XYZ()); + Vx = T ^ Vx; + } + else + { + //use standard Frenet + //no checks to force "crash" if withFrenet, which means need for binormal, to add error + Vx = N ^ T; + axe0 = gp_Ax1(gp::Origin(), Vx.XYZ()); + Vx = T ^ Vx; + } + const gp_Ax3 gp_Ax3_0(P, T, Vx); + const gp_Pnt P0(P); + const gp_Vec T0(T); + double alpha = 0.0; + + for(ListOfShape::const_reverse_iterator anIter = theProfileShapeList.crbegin(); anIter != theProfileShapeList.crend(); anIter++) { + const TopoDS_Face aProfile = TopoDS::Face((*anIter)->impl()); + if(withFrenet) + { + //normal frenet frame + aBSplinePath->D2(u, P, T, N); + Vx = N ^ T; + Vx = T ^ Vx; + + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + aWire = makeWireFromTransf(aProfile, aTrsf); + } + else + {//this works better, not iterative anymore but global from initial place to actual + gp_Pnt Paux; + gp_Vec Taux; + aBSplinePath->D1(u, Paux, Taux); + + bTrsf = gp_Trsf(); + if (T0.IsParallel(Taux, Tol)) + { + if(T0.IsOpposite(Taux, Tol)) + { + bTrsf.SetMirror(axe0); + } + } + else + { + gp_Vec cross(Taux); + cross.Cross(T); + double angle = T0.AngleWithRef(Taux, cross); + bTrsf.SetRotation(axe0, angle); + } + + gp_Vec VT(Paux.XYZ() - P0.XYZ()); + bTrsf.SetTranslationPart(VT); + + aWire = makeWireFromTransf(aProfile, bTrsf); + } + + aGenerator->AddWire(aWire); + + //for dump + std::shared_ptr aForCompoundShape(new GeomAPI_Shape); + aForCompoundShape->setImpl(new TopoDS_Shape(aWire)); + aCompoundResultList.push_back(aForCompoundShape); + + //ForDump + BRepBuilderAPI_MakeVertex coucou(P); + std::shared_ptr aForCompoundPoint(new GeomAPI_Shape); + aForCompoundPoint->setImpl(new TopoDS_Shape(coucou.Vertex())); + aCompoundPointList.push_back(aForCompoundPoint); + // + + u += (coeffReverse*uStep); + } + } + + aGenerator->Build(); + + + + aResult = aGenerator->Shape(); + + // Setting naming. + // JE SAIS PAS + + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aGenerator->LastShape())); + aToShape->setImpl(new TopoDS_Shape(aGenerator->FirstShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + if(aResult.IsNull()) { + return; + } + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); + + //dump + aCompoundResult = GeomAlgoAPI_CompoundBuilder::compound(aCompoundResultList); + TopoDS_Compound aComp = TopoDS::Compound(aCompoundResult->impl()); + BRepTools::Write(aComp, "C:/Users/occ/Desktop/forDump.brep"); + + aCompoundPointResult = GeomAlgoAPI_CompoundBuilder::compound(aCompoundPointList); + TopoDS_Compound aComp2 = TopoDS::Compound(aCompoundResult->impl()); + BRepTools::Write(aComp2, "C:/Users/occ/Desktop/forDumpPoint.brep"); +} + + +//================================================================================================= +void GeomAlgoAPI_PipeApprox::build(const ListOfShape& theProfileShapeList, + const std::shared_ptr& thePathShape, + const std::shared_ptr& theBinormal, + const bool isReverse, + const int nbSect) +{ + //METHOD MIGHT NEED TO BE DEBUGGED/MODIFIED BASED ON BUILD WITHOUT BINORMAL + if(!theProfileShapeList.size() || !thePathShape || !theBinormal) { + return; + } + + double coeffReverse = 1.0; + if(isReverse) + { + coeffReverse = -1.0; + } + + //COMPUTE RESULT + TopoDS_Shape aResult; + + BRepOffsetAPI_ThruSections* aGenerator; + + const Standard_Boolean isSolid = Standard_True; + const Standard_Boolean isRuled = Standard_False; + const Standard_Real pres3d = 1.0e-02; + + aGenerator = new BRepOffsetAPI_ThruSections(isSolid, isRuled, pres3d); + if(!aGenerator) { + return; + } + aGenerator->SetSmoothing(Standard_True); + aGenerator->SetMaxDegree(5); + aGenerator->CheckCompatibility(Standard_False); + + + // Getting binormal + TopoDS_Shape aBiNormalShape = theBinormal->impl(); + TopoDS_Edge aBiNormalEdge = TopoDS::Edge(aBiNormalShape); + double aFirst, aLast; + + Handle(Geom_Curve) aBiNormalCurve = BRep_Tool::Curve(aBiNormalEdge, aFirst, aLast); + Handle(Geom_Line) aBiNormalLine = Handle(Geom_Line)::DownCast(aBiNormalCurve); + + gp_Dir aBiNormalDir = aBiNormalLine->Lin().Direction(); + + // Getting path + double u, uStep; + TopoDS_Edge aPathEdge; + TopoDS_Wire aPathWire; + Handle(Geom_Curve) aPathCurve; + + if(thePathShape->shapeType() == GeomAPI_Shape::EDGE) { + aPathEdge = TopoDS::Edge(thePathShape->impl()); + + + //recover curve + + aPathCurve = BRep_Tool::Curve(aPathEdge, aFirst, aLast); + + if(isReverse) + { + double aTemp = aFirst; + aFirst = aLast; + aLast = aTemp; + } + + u = aFirst; + const double uStep = abs(aLast - aFirst) / (nbSect - 1); + + //iterating on sections + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Pnt P; + gp_Vec T, Vx; + + aPathCurve->D1(u, P, T); + //Vx should be in the plane of (P,D1,D2) so that (P,D1,Vx) is orthogonal + //if D2 undefined, replace it with "binormal" + Vx = T ^ aBiNormalDir; + Vx = Vx ^ T; + + gp_Ax3 gp_Ax3_0(P, T, Vx); + + int cpt = nbSect - 1; + for(ListOfShape::const_reverse_iterator anIter = theProfileShapeList.crbegin(); anIter != theProfileShapeList.crend(); anIter++) { + const TopoDS_Face aProfile = TopoDS::Face((*anIter)->impl()); + + aPathCurve->D1(u, P, T); + Vx = T ^ aBiNormalDir; + Vx = Vx ^ T; + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + + aWire = makeWireFromTransf(aProfile, aTrsf); + + + aGenerator->AddWire(aWire); + + u += (coeffReverse*uStep); + cpt--; + } + }else if(thePathShape->shapeType() == GeomAPI_Shape::WIRE) + { + aPathWire = TopoDS::Wire(thePathShape->impl()); + Handle(BRepAdaptor_HCompCurve) aPathCompCurve = new (BRepAdaptor_HCompCurve) (aPathWire); + + Standard_Real aTol = Precision::Confusion(); + GeomAbs_Shape aContinuity = GeomAbs_C2 /*highest supported continuity*/; + Standard_Integer aMaxSeg = 10000, /*max number of spans*/ + aMaxDeg = 9; /*max degree, consistent with settings in Algo*/ + GeomConvert_ApproxCurve anApproxPath (aPathCompCurve, aTol, aContinuity, aMaxSeg, aMaxDeg); + Handle(Geom_BSplineCurve) aBSplinePath = anApproxPath.Curve(); + + aFirst = aBSplinePath->FirstParameter(); + aLast = aBSplinePath->LastParameter(); + + + gp_Ax3 gp_Ax3_0; + + + if(isReverse) + { + double aTemp = aFirst; + aFirst = aLast; + aLast = aTemp; + } + + u = aFirst; + uStep = abs(aLast-aFirst) / (nbSect - 1); + TopoDS_Wire aWire; + gp_Trsf aTrsf = gp_Trsf(); + gp_Pnt P; + gp_Vec T,Vx; + + aPathCurve->D1(u, P, T); + Vx = T ^ aBiNormalDir; + Vx = Vx ^ T; + + gp_Ax3_0 = gp_Ax3(P, T, Vx); + for(ListOfShape::const_reverse_iterator anIter = theProfileShapeList.crbegin(); anIter != theProfileShapeList.crend(); anIter++) { + const TopoDS_Face aProfile = TopoDS::Face((*anIter)->impl()); + + aPathCurve->D1(u, P, T); + Vx = T ^ aBiNormalDir; + Vx = Vx ^ T; + aTrsf.SetDisplacement(gp_Ax3_0, gp_Ax3(P, T, Vx)); + aWire = makeWireFromTransf(aProfile, aTrsf); + + + aGenerator->AddWire(aWire); + + + u += (coeffReverse*uStep); + } + + } + aGenerator->Build(); + + if (!aGenerator->IsDone()){ + return; + } + + aResult = aGenerator->Shape(); + + // Setting naming. + // JE SAIS PAS + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aGenerator->LastShape())); + aToShape->setImpl(new TopoDS_Shape(aGenerator->FirstShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + if(aResult.IsNull()) { + return; + } + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +} + +//================================================================================================= +TopoDS_Wire makeWireFromTransf(const TopoDS_Shape &theSourceShape, + gp_Trsf theTrsf) +{ + TopoDS_Wire aResult; + if(theSourceShape.IsNull()) { + return aResult; + } + + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(theSourceShape, theTrsf, true); + if(!aBuilder) { + return aResult; + } + + if(aBuilder->IsDone() != Standard_True) { + return aResult; + } + + BRepBuilderAPI_MakeWire mkWire; + + TopExp_Explorer aEdgeExp(aBuilder->Shape(), TopAbs_EDGE); + for (; aEdgeExp.More(); aEdgeExp.Next()) { + TopoDS_Edge aES = TopoDS::Edge(aEdgeExp.Current()); + mkWire.Add(aES); + } + aResult = mkWire.Wire(); + + return aResult; +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.h b/src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.h new file mode 100644 index 000000000..8b11c06b3 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_PipeApprox.h @@ -0,0 +1,85 @@ +// Copyright + +// File: GeomAlgoAPI_PipeApprox.h +// Created: +// Author: + +#ifndef GeomAlgoAPI_PipeApprox_H_ +#define GeomAlgoAPI_PipeApprox_H_ + +#include +#include +#include +#include +#include +#include +#include +/// \class GeomAlgoAPI_PipeApprox +/// \ingroup DataAlgo +/// \brief Allows to create the Pipe based on a given face and path. + +class GeomAlgoAPI_PipeApprox : public GeomAlgoAPI_MakeSweep +{ +public: + /// \brief Creates Pipe for the given shape. + /// \param[in] theBaseShape face for Pipe. + /// \param[in] thePath path for Pipe. + GEOMALGOAPI_EXPORT GeomAlgoAPI_PipeApprox(); + + //basic pipe with thrusection algo + GEOMALGOAPI_EXPORT GeomAlgoAPI_PipeApprox(std::shared_ptr theProfileShape, + std::shared_ptr thePathShape); + + GEOMALGOAPI_EXPORT GeomAlgoAPI_PipeApprox(std::shared_ptr theProfileShape, + std::shared_ptr thePathShape, + std::shared_ptr theBiNormal); + + //single law, does a "scaling" + GEOMALGOAPI_EXPORT GeomAlgoAPI_PipeApprox(std::shared_ptr theProfileShape, + std::shared_ptr thePathShape, + std::shared_ptr theDef, + std::shared_ptr theRef); + + + + //WHEN USING LAWS + GEOMALGOAPI_EXPORT GeomAlgoAPI_PipeApprox(ListOfShape theProfileShapeList, + std::shared_ptr thePath, + bool isReverse, + int nbSect, + bool withFrenet); + + GEOMALGOAPI_EXPORT GeomAlgoAPI_PipeApprox(ListOfShape theProfileShapeList, + std::shared_ptr thePath, + std::shared_ptr theBinormal, + bool isReverse, + int nbSect); + +private: + /// Builds resulting shape. + void build(const std::shared_ptr& theProfileShape, + const std::shared_ptr& thePathShape); + + void build(const std::shared_ptr& theProfileShape, + const std::shared_ptr& thePathShape, + const std::shared_ptr& theBiNormal); + // + void build(const std::shared_ptr& theProfileShape, + const std::shared_ptr& thePathShape, + const std::shared_ptr& theDef, + const std::shared_ptr& theRef); + + // + void build(const ListOfShape& theProfileShapeList, + const std::shared_ptr& thePath, + const bool isReverse, + const int nbSect, + const bool withFrenet); + + void build(const ListOfShape& theProfileShapeList, + const std::shared_ptr& thePath, + const std::shared_ptr& theBinormal, + const bool isReverse, + const int nbSect); +}; +#endif \ No newline at end of file diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 1f6c8319f..8de329477 100755 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -400,7 +400,20 @@ bool Model_Update::processFeature(FeaturePtr theFeature) "Feature '%1' is updated in infinitive loop").arg(theFeature->data()->name()).send(); return false; } - myProcessed[theFeature] = aCount + 1; + //TEST FOR SWEEP (EdMei) + if(theFeature->getKind() == "PipeApproxLaw" || theFeature->getKind() == "PipeApprox") + { + std::map, int >::iterator it; + for(it = myProcessed.begin(); it != myProcessed.end(); it++) + { + it->second = 0; + } + } + else + { + myProcessed[theFeature] = aCount + 1; + } + //END TEST FOR SWEEP (EdMei) } // check this feature is not yet checked or processed -- 2.39.2