From: dbv Date: Fri, 25 Mar 2016 13:00:26 +0000 (+0300) Subject: Pipe feature X-Git-Tag: V_2.3.0~369 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=5315361b0c34c6e603474413024db5485c850d80;p=modules%2Fshaper.git Pipe feature --- diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index bb7ff7c59..8a1001b85 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -14,6 +14,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_Group.h FeaturesPlugin_Intersection.h FeaturesPlugin_Partition.h + FeaturesPlugin_Pipe.h FeaturesPlugin_Placement.h FeaturesPlugin_CompositeBoolean.h FeaturesPlugin_CompositeSketch.h @@ -26,6 +27,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_RevolutionCut.h FeaturesPlugin_RevolutionFuse.h FeaturesPlugin_ValidatorTransform.h + FeaturesPlugin_Validators.h ) SET(PROJECT_SOURCES @@ -38,6 +40,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Group.cpp FeaturesPlugin_Intersection.cpp FeaturesPlugin_Partition.cpp + FeaturesPlugin_Pipe.cpp FeaturesPlugin_Placement.cpp FeaturesPlugin_CompositeBoolean.cpp FeaturesPlugin_CompositeSketch.cpp @@ -50,6 +53,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_RevolutionCut.cpp FeaturesPlugin_RevolutionFuse.cpp FeaturesPlugin_ValidatorTransform.cpp + FeaturesPlugin_Validators.cpp ) SET(XML_RESOURCES @@ -69,6 +73,7 @@ SET(XML_RESOURCES partition_widget.xml placement_widget.xml intersection_widget.xml + pipe_widget.xml ) INCLUDE_DIRECTORIES( diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp index 701017b52..fcbcdc78e 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp @@ -23,6 +23,7 @@ #include #include +#include //================================================================================================= FeaturesPlugin_Boolean::FeaturesPlugin_Boolean() diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp index f3ef628e7..dc0b3a948 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeBoolean.cpp @@ -23,6 +23,7 @@ #include #include +#include #include //================================================================================================= @@ -420,7 +421,7 @@ void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptrtoFaces(); + const ListOfShape& aToFaces = aSweepAlgo->toShapes(); for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { std::shared_ptr aToFace = *anIt; if(aSubShapes->isBound(aToFace)) { @@ -433,7 +434,7 @@ void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptrfromFaces(); + const ListOfShape& aFromFaces = aSweepAlgo->fromShapes(); if (aFromTag < aToTag) aFromTag = aToTag; for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { std::shared_ptr aFromFace = *anIt; diff --git a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp index 3b520ba92..628773d41 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp @@ -185,7 +185,7 @@ void FeaturesPlugin_CompositeSketch::loadNamingDS(std::shared_ptrtoFaces(); + const ListOfShape& aToFaces = aSweepAlgo->toShapes(); for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { std::shared_ptr aToFace = *anIt; if(aDataMap->isBound(aToFace)) { @@ -200,7 +200,7 @@ void FeaturesPlugin_CompositeSketch::loadNamingDS(std::shared_ptr 10000 ? aToTag : 10000; - const ListOfShape& aFromFaces = aSweepAlgo->fromFaces(); + const ListOfShape& aFromFaces = aSweepAlgo->fromShapes(); for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { std::shared_ptr aFromFace = *anIt; if(aDataMap->isBound(aFromFace)) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index bdee88eaf..1a1036a11 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -178,7 +178,7 @@ void FeaturesPlugin_Extrusion::loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo, int aToFaceIndex = 1; const std::string aToName = "ToFace"; int aToTag = 2; - const ListOfShape& aToFaces = thePrismAlgo.toFaces(); + const ListOfShape& aToFaces = thePrismAlgo.toShapes(); for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { std::shared_ptr aToFace = *anIt; if(aSubShapes->isBound(aToFace)) { @@ -193,7 +193,7 @@ void FeaturesPlugin_Extrusion::loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo, int aFromFaceIndex = 1; const std::string aFromName = "FromFace"; int aFromTag = aToTag > 10000 ? aToTag : 10000; - const ListOfShape& aFromFaces = thePrismAlgo.fromFaces(); + const ListOfShape& aFromFaces = thePrismAlgo.fromShapes(); for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { std::shared_ptr aFromFace = *anIt; if(aSubShapes->isBound(aFromFace)) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Pipe.cpp b/src/FeaturesPlugin/FeaturesPlugin_Pipe.cpp new file mode 100644 index 000000000..3e46113b1 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Pipe.cpp @@ -0,0 +1,387 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesPlugin_Pipe.cpp +// Created: 16 March 2016 +// Author: Dmitry Bobylev + +#include "FeaturesPlugin_Pipe.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +//================================================================================================= +FeaturesPlugin_Pipe::FeaturesPlugin_Pipe() +{ +} + +//================================================================================================= +void FeaturesPlugin_Pipe::initAttributes() +{ + data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId()); + + data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); + data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID()); +} + +//================================================================================================= +void FeaturesPlugin_Pipe::execute() +{ + // Getting creation method. + std::string aCreationMethod = string(CREATION_METHOD())->value(); + + // Getting base objects. + ListOfShape aBaseShapesList, aBaseFacesList; + AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID()); + if(!aBaseObjectsSelectionList.get()) { + setError("Error: Could not get base objects selection list."); + return; + } + if(aBaseObjectsSelectionList->size() == 0) { + setError("Error: Base objects list is empty."); + return; + } + for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) { + AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex); + if(!aBaseObjectSelection.get()) { + setError("Error: One of the selected base objects is empty."); + return; + } + std::shared_ptr aBaseShape = aBaseObjectSelection->value(); + if(aBaseShape.get() && !aBaseShape->isNull()) { + aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) : + aBaseShapesList.push_back(aBaseShape); + } else { + // This may be the whole sketch result selected, check and get faces. + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aBaseObjectSelection->context()); + if(!aConstruction.get()) { + setError("Error: One of selected sketches does not have results."); + return; + } + int aFacesNum = aConstruction->facesNum(); + if(aFacesNum == 0) { + // Probably it can be construction. + aBaseShape = aConstruction->shape(); + if(aBaseShape.get() && !aBaseShape->isNull()) { + aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) : + aBaseShapesList.push_back(aBaseShape); + } + } else { + for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) { + std::shared_ptr aBaseFace = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + if(!aBaseFace.get() || aBaseFace->isNull()) { + setError("Error: One of the faces on selected sketch is Null."); + return; + } + aBaseFacesList.push_back(aBaseFace); + } + } + } + } + + // Searching faces with common edges. + if(aCreationMethod == "simple") { + ListOfShape aShells; + ListOfShape aFreeFaces; + std::shared_ptr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList); + GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces); + aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end()); + aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end()); + } else { + aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end()); + } + + // 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 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 locations. + ListOfShape aLocations; + if(aCreationMethod == "locations") { + AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID()); + if(!aLocationsSelectionList.get()) { + setError("Error: Could not get locations selection list."); + return; + } + for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) { + AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex); + if(!aLocationSelection.get()) { + setError("Error: One of the selected location is empty."); + return; + } + std::shared_ptr aLocationShape = aLocationSelection->value(); + if(!aLocationShape.get()) { + // Probably it is a construction. + aLocationShape = aLocationSelection->context()->shape(); + } + if(!aLocationShape.get() || aLocationShape->isNull()) { + setError("Error: One of the selected location shape is null."); + return; + } + aLocations.push_back(aLocationShape); + } + } + + // Generating result for each object. + int aResultIndex = 0; + if(aCreationMethod == "simple" || aCreationMethod == "binormal") { + for(ListOfShape::const_iterator anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) { + std::shared_ptr aBaseShape = *anIter; + + GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod == "simple" ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) : + GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal); + + if(!aPipeAlgo.isDone()) { + setError("Error: Pipe algorithm failed."); + aResultIndex = 0; + break; + } + + // Check if shape is valid + if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) { + setError("Error: Resulting shape is Null."); + aResultIndex = 0; + break; + } + if(!aPipeAlgo.isValid()) { + setError("Error: Resulting shape is not valid."); + aResultIndex = 0; + break; + } + + storeResult(aBaseShape, aPipeAlgo, aResultIndex++); + } + } else if(aCreationMethod == "locations") { + GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape); + + if(!aPipeAlgo.isDone()) { + setError("Error: Pipe algorithm failed."); + removeResults(0); + return; + } + + // Check if shape is valid + if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) { + setError("Error: Resulting shape is Null."); + removeResults(0); + return; + } + if(!aPipeAlgo.isValid()) { + setError("Error: Resulting shape is not valid."); + removeResults(0); + return; + } + + storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++); + } else { + setError("Error: Wrong creation method."); + return; + } + + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr theBaseShape, + GeomAlgoAPI_Pipe& thePipeAlgo, + const int theResultIndex) +{ + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); + + // Store generated shape. + aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape()); + + // Store generated edges/faces. + GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType(); + GeomAPI_Shape::ShapeType aShapeTypeToExplode; + int aGenTag = 1; + std::string aGenName = "Generated_"; + + std::shared_ptr aMapOfSubShapes = thePipeAlgo.mapOfSubShapes(); + switch(aBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplode = GeomAPI_Shape::VERTEX; + aGenName += "Edge"; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + std::shared_ptr aV1, aV2; + GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2); + ListOfShape aV1History, aV2History; + thePipeAlgo.generated(aV1, aV1History); + thePipeAlgo.generated(aV2, aV2History); + aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++); + aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++); + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplode = GeomAPI_Shape::EDGE; + aGenName += "Face"; + break; + } + } + aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get()); + + // Store from shapes. + int aFromTag = aGenTag; + storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.fromShapes(), "From_", aFromTag); + + // Store to shapes. + int aToTag = aFromTag; + storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag); + + setResult(aResultBody, theResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes, + GeomAlgoAPI_Pipe& thePipeAlgo, + const int theResultIndex) +{ + // Create result body. + ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); + + // Store generated shape. + aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape()); + + // Store generated edges/faces. + int aGenTag = 1; + std::shared_ptr aMapOfSubShapes = thePipeAlgo.mapOfSubShapes(); + + for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) { + GeomShapePtr aBaseShape = *anIter; + GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType(); + GeomAPI_Shape::ShapeType aShapeTypeToExplode; + std::string aGenName = "Generated_"; + switch(aBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplode = GeomAPI_Shape::VERTEX; + aGenName += "Edge"; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + std::shared_ptr aV1, aV2; + GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2); + ListOfShape aV1History, aV2History; + thePipeAlgo.generated(aV1, aV1History); + thePipeAlgo.generated(aV2, aV2History); + aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++); + aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++); + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplode = GeomAPI_Shape::EDGE; + aGenName += "Face"; + break; + } + } + aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get()); + } + + // Store from shapes. + int aFromTag = aGenTag; + storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes, thePipeAlgo.fromShapes(), "From", aFromTag); + + // Store to shapes. + int aToTag = aFromTag; + storeShapes(aResultBody, theBaseShapes.back()->shapeType(), aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag); + + + setResult(aResultBody, theResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const std::shared_ptr theMapOfSubShapes, + const ListOfShape& theShapes, + const std::string theName, + int& theTag) +{ + GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE; + std::string aShapeTypeStr = "Face"; + switch(theBaseShapeType) { + case GeomAPI_Shape::VERTEX: { + aShapeTypeToExplore = GeomAPI_Shape::VERTEX; + aShapeTypeStr = "Vertex"; + break; + } + case GeomAPI_Shape::EDGE: + case GeomAPI_Shape::WIRE: { + aShapeTypeToExplore = GeomAPI_Shape::EDGE; + aShapeTypeStr = "Edge"; + break; + } + case GeomAPI_Shape::FACE: + case GeomAPI_Shape::SHELL: { + aShapeTypeToExplore = GeomAPI_Shape::FACE; + aShapeTypeStr = "Face"; + break; + } + } + + // Store shapes. + int aShapeIndex = 1; + std::string aName = theName + aShapeTypeStr; + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { + std::shared_ptr aShape = *anIt; + for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) { + std::shared_ptr aSubShape = anExp.current(); + if(theMapOfSubShapes->isBound(aSubShape)) { + aSubShape = theMapOfSubShapes->find(aSubShape); + } + std::ostringstream aStr; + aStr << aName << "_" << aShapeIndex++; + theResultBody->generated(aSubShape, aStr.str(), theTag++); + } + } +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Pipe.h b/src/FeaturesPlugin/FeaturesPlugin_Pipe.h new file mode 100644 index 000000000..6682f230c --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Pipe.h @@ -0,0 +1,103 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesPlugin_Pipe.h +// Created: 16 March 2016 +// Author: Dmitry Bobylev + +#ifndef FeaturesPlugin_Pipe_H_ +#define FeaturesPlugin_Pipe_H_ + +#include "FeaturesPlugin.h" + +#include + +#include +#include + +/// \class FeaturesPlugin_Pipe +/// \ingroup Plugins +/// \brief Feature for creation of extrusion along a path. +/// Pipe creates extrusion of objects along a path. It produces the following results from objects:\n +/// Vertex -> Edge\n +/// Edge -> Face\n +/// Wire -> Shell\n +/// Face -> Solid +class FeaturesPlugin_Pipe : public ModelAPI_Feature +{ +public: + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_FEATURE_ID("Pipe"); + return MY_FEATURE_ID; + } + + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD() + { + static const std::string MY_CREATION_METHOD("creation_method"); + return MY_CREATION_METHOD; + } + + /// Attribute name of base objects. + inline static const std::string& BASE_OBJECTS_ID() + { + static const std::string MY_BASE_OBJECTS_ID("base_objects"); + return MY_BASE_OBJECTS_ID; + } + + /// Attribute name of path object. + inline static const std::string& PATH_OBJECT_ID() + { + static const std::string MY_PATH_OBJECT_ID("path_object"); + return MY_PATH_OBJECT_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 locations. + inline static const std::string& LOCATIONS_ID() + { + static const std::string MY_LOCATIONS_ID("locations_objects"); + return MY_LOCATIONS_ID; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Pipe::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_Pipe(); + +private: + void storeResult(const std::shared_ptr theBaseShape, + GeomAlgoAPI_Pipe& thePipeAlgo, + const int theResultIndex = 0); + + void storeResult(const ListOfShape& theBaseShapes, + GeomAlgoAPI_Pipe& thePipeAlgo, + const int theResultIndex = 0); + + void storeShapes(ResultBodyPtr theResultBody, + const GeomAPI_Shape::ShapeType theBaseShapeType, + const std::shared_ptr theMapOfSubShapes, + const ListOfShape& theShapes, + const std::string theName, + int& theTag); +}; + +#endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index d40d085ba..432e38850 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include #include +#include #include @@ -35,7 +37,9 @@ FeaturesPlugin_Plugin::FeaturesPlugin_Plugin() SessionPtr aMgr = ModelAPI_Session::get(); ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); aFactory->registerValidator("FeaturesPlugin_ValidatorTransform", - new FeaturesPlugin_ValidatorTransform); + new FeaturesPlugin_ValidatorTransform); + aFactory->registerValidator("FeaturesPlugin_PipeLocationsValidator", + new FeaturesPlugin_PipeLocationsValidator); // register this plugin ModelAPI_Session::get()->registerPlugin(this); @@ -59,6 +63,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) return FeaturePtr(new FeaturesPlugin_Intersection); } else if (theFeatureID == FeaturesPlugin_Partition::ID()) { return FeaturePtr(new FeaturesPlugin_Partition); + } else if (theFeatureID == FeaturesPlugin_Pipe::ID()) { + return FeaturePtr(new FeaturesPlugin_Pipe); } else if (theFeatureID == FeaturesPlugin_Placement::ID()) { return FeaturePtr(new FeaturesPlugin_Placement); } else if (theFeatureID == FeaturesPlugin_ExtrusionCut::ID()) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp index 5a7a34b39..88163729c 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp @@ -194,7 +194,7 @@ void FeaturesPlugin_Revolution::loadNamingDS(GeomAlgoAPI_Revolution& theRevolAlg int aToFaceIndex = 1; const std::string aToName = "ToFace"; int aToTag = 2; - const ListOfShape& aToFaces = theRevolAlgo.toFaces(); + const ListOfShape& aToFaces = theRevolAlgo.toShapes(); for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) { std::shared_ptr aToFace = *anIt; if(aSubShapes->isBound(aToFace)) { @@ -209,7 +209,7 @@ void FeaturesPlugin_Revolution::loadNamingDS(GeomAlgoAPI_Revolution& theRevolAlg int aFromFaceIndex = 1; const std::string aFromName = "FromFace"; int aFromTag = aToTag > 10000 ? aToTag : 10000; - const ListOfShape& aFromFaces = theRevolAlgo.fromFaces(); + const ListOfShape& aFromFaces = theRevolAlgo.fromShapes(); for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) { std::shared_ptr aFromFace = *anIt; if(aSubShapes->isBound(aFromFace)) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp new file mode 100644 index 000000000..40c1197db --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -0,0 +1,65 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesPlugin_Validators.cpp +// Created: 22 March 2016 +// Author: Dmitry Bobylev + +#include "FeaturesPlugin_Validators.h" + +#include +#include +#include + +//================================================================================================= +bool FeaturesPlugin_PipeLocationsValidator::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + std::string& theError) const +{ + static const std::string aCreationMethodID = "creation_method"; + static const std::string aBaseObjectsID = "base_objects"; + static const std::string aLocationsID = "locations_objects"; + + + if(theFeature->getKind() != "Pipe") { + theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator."; + return false; + } + + AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID); + if(!aCreationMethodAttr.get()) { + theError = "Could not get \"" + aCreationMethodID + "\" attribute."; + return false; + } + + if(aCreationMethodAttr->value() != "locations") { + return true; + } + + AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID); + if(!aBaseObjectsSelectionList.get()) { + theError = "Could not get \"" + aBaseObjectsID + "\" attribute."; + return false; + } + + AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID); + if(!aLocationsSelectionList.get()) { + theError = "Could not get \"" + aBaseObjectsID + "\" attribute."; + return false; + } + + if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) { + theError = "Number of locations should be the same as base objects."; + return false; + } + + return true; +} + +//================================================================================================= +bool FeaturesPlugin_PipeLocationsValidator::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + if(theFeature == "Pipe" && theAttribute == "locations") { + return true; + } + return false; +} \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.h b/src/FeaturesPlugin/FeaturesPlugin_Validators.h new file mode 100644 index 000000000..47a12e434 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.h @@ -0,0 +1,30 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D --> + +// File: FeaturesPlugin_Validators.h +// Created: 22 March 2016 +// Author: Dmitry Bobylev + +#ifndef FeaturesPlugin_Validators_H_ +#define FeaturesPlugin_Validators_H_ + +#include + +/// \class FeaturesPlugin_PipeLocationsValidator +/// \ingroup Validators +/// \brief Validator for the pipe locations. +class FeaturesPlugin_PipeLocationsValidator : public ModelAPI_FeatureValidator +{ + public: + //! \return true if number of selected locations the same as number of selected bases, or empty. + //! \param theFeature the checked feature + //! \param theArguments arguments of the feature (not used) + //! \param theError error message + virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments, + std::string& theError) const; + + /// Returns true if the attribute in feature is not obligatory for the feature execution + virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + +#endif diff --git a/src/FeaturesPlugin/pipe_widget.xml b/src/FeaturesPlugin/pipe_widget.xml new file mode 100644 index 000000000..10b07cad8 --- /dev/null +++ b/src/FeaturesPlugin/pipe_widget.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index afe29e462..fe897b2a5 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -30,6 +30,11 @@ + + + + + diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index 17e87d85c..d00fe34db 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -94,6 +94,53 @@ GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeType() const return (ShapeType)aShape.ShapeType(); } +std::string GeomAPI_Shape::shapeTypeStr() const +{ + ShapeType aShapeType = shapeType(); + std::string aShapeTypeStr; + + switch(aShapeType) { + case COMPOUND: { + aShapeTypeStr = "Compound"; + break; + } + case COMPSOLID: { + aShapeTypeStr = "CompSolid"; + break; + } + case SOLID: { + aShapeTypeStr = "Solid"; + break; + } + case SHELL: { + aShapeTypeStr = "Shell"; + break; + } + case FACE: { + aShapeTypeStr = "Face"; + break; + } + case WIRE: { + aShapeTypeStr = "Wire"; + break; + } + case EDGE: { + aShapeTypeStr = "Edge"; + break; + } + case VERTEX: { + aShapeTypeStr = "Vertex"; + break; + } + case SHAPE: { + aShapeTypeStr = "Shape"; + break; + } + } + + return aShapeTypeStr; +} + bool GeomAPI_Shape::computeSize(double& theXmin, double& theYmin, double& theZmin, double& theXmax, double& theYmax, double& theZmax) const { diff --git a/src/GeomAPI/GeomAPI_Shape.h b/src/GeomAPI/GeomAPI_Shape.h index 8f31318d6..37ba2b462 100644 --- a/src/GeomAPI/GeomAPI_Shape.h +++ b/src/GeomAPI/GeomAPI_Shape.h @@ -70,6 +70,10 @@ public: GEOMAPI_EXPORT virtual ShapeType shapeType() const; + /// \return the shape type as string. + GEOMAPI_EXPORT + virtual std::string shapeTypeStr() const; + /// Computes boundary dimensions of the shape /// Returns False if it is not possible GEOMAPI_EXPORT diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 1b3390b16..74f73a9bb 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -35,6 +35,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Partition.h GeomAlgoAPI_PaveFiller.h GeomAlgoAPI_Intersection.h + GeomAlgoAPI_Pipe.h ) SET(PROJECT_SOURCES @@ -66,6 +67,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Partition.cpp GeomAlgoAPI_PaveFiller.cpp GeomAlgoAPI_Intersection.cpp + GeomAlgoAPI_Pipe.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI.i b/src/GeomAlgoAPI/GeomAlgoAPI.i index 2aea45d15..95fddd512 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI.i +++ b/src/GeomAlgoAPI/GeomAlgoAPI.i @@ -41,6 +41,7 @@ %include "GeomAlgoAPI_Transform.h" %include "GeomAlgoAPI_PaveFiller.h" %include "GeomAlgoAPI_Intersection.h" +%include "GeomAlgoAPI_Pipe.h" %typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & { $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr(*$1)), $descriptor(std::shared_ptr *), SWIG_POINTER_OWN | 0 ); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp index 5419c4f15..e7d5165ce 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp @@ -18,7 +18,7 @@ //================================================================================================= GeomAlgoAPI_MakeShape::GeomAlgoAPI_MakeShape() -: myBuilderType(UNKNOWN), +: myBuilderType(Unknown), myDone(false) { } @@ -150,8 +150,8 @@ void GeomAlgoAPI_MakeShape::setShape(const std::shared_ptr theSha myMap.reset(new GeomAPI_DataMapOfShapeShape); } - const TopoDS_Shape& aTopoDSSHape = myShape->impl(); - for(TopExp_Explorer anExp(aTopoDSSHape,TopAbs_FACE); anExp.More(); anExp.Next()) { + const TopoDS_Shape& aTopoDSShape = myShape->impl(); + for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_FACE); anExp.More(); anExp.Next()) { std::shared_ptr aCurrentShape(new GeomAPI_Shape()); aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current())); myMap->bind(aCurrentShape, aCurrentShape); @@ -179,4 +179,17 @@ void GeomAlgoAPI_MakeShape::initialize() { break; } } + + if(myMap.get()) { + myMap->clear(); + } else { + myMap.reset(new GeomAPI_DataMapOfShapeShape); + } + + const TopoDS_Shape& aTopoDSShape = myShape->impl(); + for(TopExp_Explorer anExp(aTopoDSShape,TopAbs_FACE); anExp.More(); anExp.Next()) { + std::shared_ptr aCurrentShape(new GeomAPI_Shape()); + aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current())); + myMap->bind(aCurrentShape, aCurrentShape); + } } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h index acbc9c84f..b5e40ef24 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.h @@ -20,9 +20,9 @@ class GeomAlgoAPI_MakeShape : public GeomAPI_Interface public: /// Builder type enum enum BuilderType { + Unknown, OCCT_BRepBuilderAPI_MakeShape, - OCCT_BOPAlgo_Builder, - UNKNOWN + OCCT_BOPAlgo_Builder }; public: @@ -45,7 +45,7 @@ public: template void initialize(T* theBuilder, const BuilderType theBuilderType = OCCT_BRepBuilderAPI_MakeShape) { setImpl(theBuilder); - myBuilderType = theBuilder; + myBuilderType = theBuilderType; initialize(); } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.cpp index 701a99d14..7a59ae344 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.cpp @@ -7,37 +7,37 @@ #include "GeomAlgoAPI_MakeSweep.h" //================================================================================================= -const ListOfShape& GeomAlgoAPI_MakeSweep::fromFaces() const +const ListOfShape& GeomAlgoAPI_MakeSweep::fromShapes() const { - return myFromFaces; + return myFromShapes; } //================================================================================================= -const ListOfShape& GeomAlgoAPI_MakeSweep::toFaces() const +const ListOfShape& GeomAlgoAPI_MakeSweep::toShapes() const { - return myToFaces; + return myToShapes; } //================================================================================================= -void GeomAlgoAPI_MakeSweep::addFromFace(const std::shared_ptr theFace) +void GeomAlgoAPI_MakeSweep::addFromShape(const std::shared_ptr theFace) { - myFromFaces.push_back(theFace); + myFromShapes.push_back(theFace); } //================================================================================================= -void GeomAlgoAPI_MakeSweep::setFromFaces(const ListOfShape& theListOfFaces) +void GeomAlgoAPI_MakeSweep::setFromShapes(const ListOfShape& theListOfFaces) { - myFromFaces = theListOfFaces; + myFromShapes = theListOfFaces; } //================================================================================================= -void GeomAlgoAPI_MakeSweep::addToFace(const std::shared_ptr theFace) +void GeomAlgoAPI_MakeSweep::addToShape(const std::shared_ptr theFace) { - myToFaces.push_back(theFace); + myToShapes.push_back(theFace); } //================================================================================================= -void GeomAlgoAPI_MakeSweep::setToFaces(const ListOfShape& theListOfFaces) +void GeomAlgoAPI_MakeSweep::setToShapes(const ListOfShape& theListOfFaces) { - myToFaces = theListOfFaces; + myToShapes = theListOfFaces; } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.h b/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.h index d9c5f4ec2..2006c8746 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeSweep.h @@ -26,35 +26,35 @@ class GeomAlgoAPI_MakeSweep : public GeomAlgoAPI_MakeShapeList { public: - /// \returns the list of from faces. - GEOMALGOAPI_EXPORT virtual const ListOfShape& fromFaces() const; + /// \returns the list of from shapes. + GEOMALGOAPI_EXPORT virtual const ListOfShape& fromShapes() const; - /// \return the list of to faces. - GEOMALGOAPI_EXPORT virtual const ListOfShape& toFaces() const; + /// \return the list of to shapes. + GEOMALGOAPI_EXPORT virtual const ListOfShape& toShapes() const; protected: /// Empty constructor. GeomAlgoAPI_MakeSweep() : GeomAlgoAPI_MakeShapeList() {}; - /// \brief Adds a face to list of from faces. - /// \param[in] theFace a face to add. - void addFromFace(const std::shared_ptr theFace); + /// \brief Adds a shape to list of from shape. + /// \param[in] theShape a shape to add. + void addFromShape(const std::shared_ptr theShape); - /// \brief Sets from faces - /// \param[in] theListOfFaces list of from faces. - void setFromFaces(const ListOfShape& theListOfFaces); + /// \brief Sets from shapes + /// \param[in] theListOfShapes list of from shapes. + void setFromShapes(const ListOfShape& theListOfShapes); - /// \brief Adds a face to list of to faces. - /// \param[in] theFace a face to add. - void addToFace(const std::shared_ptr theFace); + /// \brief Adds a face to list of to shape. + /// \param[in] theShape a face to add. + void addToShape(const std::shared_ptr theShape); - /// \brief Sets to faces - /// \param[in] theListOfFaces list of to faces. - void setToFaces(const ListOfShape& theListOfFaces); + /// \brief Sets to shapes + /// \param[in] theListOfShapes list of to shapes. + void setToShapes(const ListOfShape& theListOfShapes); private: - ListOfShape myFromFaces; - ListOfShape myToFaces; + ListOfShape myFromShapes; + ListOfShape myToShapes; }; #endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Pipe.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Pipe.cpp new file mode 100644 index 000000000..7761a5b9d --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Pipe.cpp @@ -0,0 +1,391 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Pipe.cpp +// Created: 16 March 2016 +// Author: Dmitry Bobylev + +#include "GeomAlgoAPI_Pipe.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool getBase(TopoDS_Shape& theBaseOut, + TopAbs_ShapeEnum& theBaseTypeOut, + const std::shared_ptr theBaseShape); +static bool getPath(TopoDS_Wire& thePathOut, + const std::shared_ptr thePathShape); +static bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder); + +//================================================================================================= +GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape) +: /*myIsPipeShellUsed(false),*/ + myBaseShape(theBaseShape), + myPathShape(thePathShape) +{ + build(theBaseShape, thePathShape); +} + +//================================================================================================= +GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape, + const std::shared_ptr theBiNormal) +//: myIsPipeShellUsed(true) +{ + build(theBaseShape, thePathShape, theBiNormal); +} + +//================================================================================================= +GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes, + const ListOfShape& theLocations, + const std::shared_ptr thePathShape) +//: myIsPipeShellUsed(true) +{ + build(theBaseShapes, theLocations, thePathShape); +} + +//================================================================================================= +void GeomAlgoAPI_Pipe::build(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape) +{ + // Getting base shape. + if(!theBaseShape.get()) { + return; + } + TopoDS_Shape aBaseShape = theBaseShape->impl(); + if(aBaseShape.IsNull()) { + return; + } + TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType(); + if(aBaseShapeType != TopAbs_VERTEX && aBaseShapeType != TopAbs_EDGE && + aBaseShapeType != TopAbs_WIRE && aBaseShapeType != TopAbs_FACE && + aBaseShapeType != TopAbs_SHELL) { + return; + } + + // Getting path. + TopoDS_Wire aPathWire; + if(!getPath(aPathWire, thePathShape)) { + return; + } + + // Making pipe. + BRepOffsetAPI_MakePipe* aPipeBuilder = new BRepOffsetAPI_MakePipe(aPathWire, aBaseShape); + if(!aPipeBuilder) { + return; + } + aPipeBuilder->Build(); + + // Checking result. + if(!aPipeBuilder->IsDone() || aPipeBuilder->Shape().IsNull()) { + delete aPipeBuilder; + return; + } + this->initialize(aPipeBuilder); + + // Setting naming. + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape())); + aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + TopoDS_Shape aResultShape = aPipeBuilder->Shape(); + std::shared_ptr aResultGeomShape(new GeomAPI_Shape()); + aResultGeomShape->setImpl(new TopoDS_Shape(aResultShape)); + this->setShape(aResultGeomShape); + this->setDone(true); +} + +//================================================================================================= +void GeomAlgoAPI_Pipe::build(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape, + const std::shared_ptr theBiNormal) +{ + // Getting base shape. + TopoDS_Shape aBaseShape; + TopAbs_ShapeEnum aBaseShapeType; + if(!getBase(aBaseShape, aBaseShapeType, theBaseShape)) { + return; + } + + // Getting path. + TopoDS_Wire aPathWire; + if(!getPath(aPathWire, thePathShape)) { + return; + } + + // Getting Bi-Normal. + if(!theBiNormal.get()) { + return; + } + TopoDS_Shape aBiNormalShape = theBiNormal->impl(); + if(aBiNormalShape.IsNull() || aBiNormalShape.ShapeType() != TopAbs_EDGE) { + return; + } + TopoDS_Edge aBiNormalEdge = TopoDS::Edge(aBiNormalShape); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aBiNormalCurve = BRep_Tool::Curve(aBiNormalEdge, aFirst, aLast); + Handle(Geom_Line) aBiNormalLine = Handle(Geom_Line)::DownCast(aBiNormalCurve); + if(aBiNormalLine.IsNull()) { + return; + } + gp_Dir aBiNormalDir = aBiNormalLine->Lin().Direction(); + + // Making pipe. + BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire); + if(!aPipeBuilder) { + return; + } + aPipeBuilder->Add(aBaseShape); + aPipeBuilder->SetMode(aBiNormalDir); + if(!buildPipe(aPipeBuilder)) { + delete aPipeBuilder; + return; + } + this->initialize(aPipeBuilder); + + // Checking result. + if(aBaseShapeType == TopAbs_FACE) { + if(aPipeBuilder->MakeSolid() == Standard_False) { + return; + } + } + if(aPipeBuilder->Shape().IsNull()) { + return; + } + + // Setting naming. + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape())); + aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + TopoDS_Shape aResultShape = aPipeBuilder->Shape(); + std::shared_ptr aResultGeomShape(new GeomAPI_Shape()); + aResultGeomShape->setImpl(new TopoDS_Shape(aResultShape)); + this->setShape(aResultGeomShape); + this->setDone(true); +} + +//================================================================================================= +void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes, + const ListOfShape& theLocations, + const std::shared_ptr thePathShape) +{ + if(theBaseShapes.empty() || (!theLocations.empty() && theLocations.size() != theBaseShapes.size())) { + return; + } + + bool aHasLocations = false; + if(!theLocations.empty()) { + aHasLocations = true; + } + + // Getting path. + TopoDS_Wire aPathWire; + if(!getPath(aPathWire, thePathShape)) { + return; + } + + // Making pipe. + BRepOffsetAPI_MakePipeShell* aPipeBuilder = new BRepOffsetAPI_MakePipeShell(aPathWire); + if(!aPipeBuilder) { + return; + } + bool anIsSolidNeeded = false; + ListOfShape::const_iterator aBaseIt = theBaseShapes.cbegin(); + ListOfShape::const_iterator aLocIt = theLocations.cbegin(); + while(aBaseIt != theBaseShapes.cend()) { + std::shared_ptr aBase = *aBaseIt; + TopoDS_Shape aBaseShape; + TopAbs_ShapeEnum aBaseShapeType; + if(!getBase(aBaseShape, aBaseShapeType, aBase)) { + delete aPipeBuilder; + return; + } + ++aBaseIt; + if(aBaseShapeType == TopAbs_FACE) { + anIsSolidNeeded = true; + } + + if(aHasLocations) { + std::shared_ptr aLocation = *aLocIt; + if(!aLocation.get() || aLocation->shapeType() != GeomAPI_Shape::VERTEX) { + delete aPipeBuilder; + return; + } + TopoDS_Vertex aLocationVertex = aLocation->impl(); + ++aLocIt; + aPipeBuilder->Add(aBaseShape, aLocationVertex); + } else { + aPipeBuilder->Add(aBaseShape); + } + } + + if(aPipeBuilder->IsReady() == Standard_False) { + delete aPipeBuilder; + return; + } + + if(!buildPipe(aPipeBuilder)) { + delete aPipeBuilder; + return; + } + this->initialize(aPipeBuilder); + + // Checking result. + if(anIsSolidNeeded) { + if(aPipeBuilder->MakeSolid() == Standard_False) { + return; + } + } + if(aPipeBuilder->Shape().IsNull()) { + return; + } + + // Setting naming. + std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); + aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape())); + aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape())); + this->addFromShape(aFromShape); + this->addToShape(aToShape); + + // Setting result. + TopoDS_Shape aResultShape = aPipeBuilder->Shape(); + std::shared_ptr aResultGeomShape(new GeomAPI_Shape()); + aResultGeomShape->setImpl(new TopoDS_Shape(aResultShape)); + this->setShape(aResultGeomShape); + this->setDone(true); +} + +//================================================================================================= +void GeomAlgoAPI_Pipe::generated(const std::shared_ptr theShape, + ListOfShape& theHistory) +{ + GeomAlgoAPI_MakeShape::generated(theShape, theHistory); + + //if(myIsPipeShellUsed) { + // GeomAlgoAPI_MakeShape::generated(theShape, theHistory); + // return; + //} + + //BRepOffsetAPI_MakePipe* aMakePipe = implPtr(); + //const TopoDS_Shape& aProfile = theShape->impl(); + //const TopAbs_ShapeEnum aProfileShapeType = aProfile.ShapeType(); + //if(aProfileShapeType != TopAbs_VERTEX && aProfileShapeType != TopAbs_EDGE) { + // return; + //} + //const TopoDS_Shape& aBaseShape = myBaseShape->impl(); + //TopExp_Explorer anExp(aBaseShape, aProfileShapeType); + //Standard_Boolean ahasShape = Standard_False; + //for(; anExp.More(); anExp.Next()) { + // if(anExp.Current().IsSame(aProfile)) { + // ahasShape = Standard_True; + // break; + // } + //} + //if(!ahasShape) { + // return; + //} + //TopExp_Explorer aShapeExplorer(myPathShape->impl(), TopAbs_EDGE); + //for(; aShapeExplorer.More(); aShapeExplorer.Next ()) { + // const TopoDS_Shape& aSpine = aShapeExplorer.Current(); + // const TopoDS_Shape& aGeneratedShape = aMakePipe->Generated(aSpine, aProfile); + // if(aGeneratedShape.IsNull()) { + // continue; + // } + // std::shared_ptr aShape(new GeomAPI_Shape()); + // aShape->setImpl(new TopoDS_Shape(aGeneratedShape)); + // theHistory.push_back(aShape); + //} +} + +// Auxilary functions: +//================================================================================================= +bool getBase(TopoDS_Shape& theBaseOut, + TopAbs_ShapeEnum& theBaseTypeOut, + const std::shared_ptr theBaseShape) +{ + if(!theBaseShape.get()) { + return false; + } + + theBaseOut = theBaseShape->impl(); + if(theBaseOut.IsNull()) { + return false; + } + theBaseTypeOut = theBaseOut.ShapeType(); + if(theBaseTypeOut == TopAbs_VERTEX) { + // Do nothing. + } else if(theBaseTypeOut == TopAbs_EDGE) { + theBaseOut = BRepBuilderAPI_MakeWire(TopoDS::Edge(theBaseOut)).Shape(); + } else if(theBaseTypeOut == TopAbs_WIRE) { + // Do nothing. + } else if(theBaseTypeOut == TopAbs_FACE) { + TopExp_Explorer anExp(theBaseOut, TopAbs_WIRE); + theBaseOut = anExp.Current(); + } else { + return false; + } + + return true; +} + +//================================================================================================= +bool getPath(TopoDS_Wire& thePathOut, + const std::shared_ptr thePathShape) +{ + if(!thePathShape.get()) { + return false; + } + + TopoDS_Shape aPathShape = thePathShape->impl(); + if(aPathShape.IsNull()) { + return false; + } + TopAbs_ShapeEnum aPathShapeType = aPathShape.ShapeType(); + if(aPathShapeType == TopAbs_EDGE) { + TopoDS_Edge aPathEdge = TopoDS::Edge(aPathShape); + thePathOut = BRepBuilderAPI_MakeWire(aPathEdge).Wire(); + } else if(aPathShapeType == TopAbs_WIRE) { + thePathOut = TopoDS::Wire(aPathShape); + } else { + return false; + } + + return true; +} + +//================================================================================================= +bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder) +{ + thePipeBuilder->Build(); + + Standard_Boolean isDone = thePipeBuilder->IsDone(); + + if (!isDone) { + // Try to use Descrete Trihedron mode. + thePipeBuilder->SetDiscreteMode(); + thePipeBuilder->Build(); + isDone = thePipeBuilder->IsDone(); + } + + return isDone == Standard_True; +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Pipe.h b/src/GeomAlgoAPI/GeomAlgoAPI_Pipe.h new file mode 100644 index 000000000..8814118d1 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Pipe.h @@ -0,0 +1,74 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Pipe.h +// Created: 16 March 2016 +// Author: Dmitry Bobylev + +#ifndef GeomAlgoAPI_Pipe_H_ +#define GeomAlgoAPI_Pipe_H_ + +#include "GeomAlgoAPI.h" + +#include "GeomAlgoAPI_MakeSweep.h" + +#include + +/// \class GeomAlgoAPI_Pipe +/// \ingroup DataAlgo +/// \brief Allows to create extrusion of objects along a path. It produces the following results from objects:\n +/// Vertex -> Edge\n +/// Edge -> Face\n +/// Wire -> Shell\n +/// Face -> Solid +class GeomAlgoAPI_Pipe : public GeomAlgoAPI_MakeSweep +{ +public: + /// \brief Creates extrusion for the given shape along a path. + /// \param[in] theBaseShape base shape(vertex, edge, wire of face). + /// \param[in] thePathShape path shape(edge or wire). + GEOMALGOAPI_EXPORT GeomAlgoAPI_Pipe(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape); + + /// \brief Creates extrusion for the given shape along a path. + /// \param[in] theBaseShape base shape(vertex, edge, wire of face). + /// \param[in] thePathShape path shape(edge or wire). + /// \param[in] theBiNormal edge or wire to preserve the constant angle between the normal vector + /// to the base object and the BiNormal vector. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Pipe(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape, + const std::shared_ptr theBiNormal); + + /// \brief Creates extrusion for the given shape along a path. + /// \param[in] theBaseShapes base shape(vertex, edge, wire of face). + /// \param[in] theLocations vertexes on the path. Should be empty or same size as theBaseShapes. + /// \param[in] thePathShape path shape(edge or wire). + /// to the base object and the BiNormal vector. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes, + const ListOfShape& theLocations, + const std::shared_ptr thePathShape); + + /// \return the list of shapes generated from theShape. + /// \param[in] theShape base shape. + /// \param[out] theHistory generated shapes. + GEOMALGOAPI_EXPORT void generated(const std::shared_ptr theShape, + ListOfShape& theHistory) override; + +private: + void build(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape); + + void build(const std::shared_ptr theBaseShape, + const std::shared_ptr thePathShape, + const std::shared_ptr theBiNormal); + + void build(const ListOfShape& theBaseShapes, + const ListOfShape& theLocations, + const std::shared_ptr thePathShape); + +private: + //bool myIsPipeShellUsed; + std::shared_ptr myBaseShape; + std::shared_ptr myPathShape; +}; + +#endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp index 2e8b00ca7..f0a6690e2 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp @@ -117,8 +117,8 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBaseShape std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); aFromShape->setImpl(new TopoDS_Shape(aPrismBuilder->FirstShape(aFace))); aToShape->setImpl(new TopoDS_Shape(aPrismBuilder->LastShape(aFace))); - this->addFromFace(aFromShape); - this->addToFace(aToShape); + this->addFromShape(aFromShape); + this->addToShape(aToShape); } } else { std::shared_ptr aBoundingFromShape = theFromShape ? theFromShape : aBasePlane; @@ -268,7 +268,7 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBaseShape for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) { std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(anIt.Value())); - this->addToFace(aShape); + this->addToShape(aShape); } aResult = aToCutBuilder->Shape(); @@ -283,7 +283,7 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBaseShape for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) { std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(anIt.Value())); - this->addFromFace(aShape); + this->addFromShape(aShape); } aResult = aFromCutBuilder->Shape(); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp index eec976ee8..cd3198a77 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp @@ -140,8 +140,8 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBase std::shared_ptr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape); aFromShape->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape(aFace))); aToShape->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape(aFace))); - this->addFromFace(aFromShape); - this->addToFace(aToShape); + this->addFromShape(aFromShape); + this->addToShape(aToShape); } } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set. // Making revolution to the 360 angle. @@ -249,12 +249,12 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBase if(aFaceSurface == aFromSurface) { std::shared_ptr aFSHape(new GeomAPI_Shape); aFSHape->setImpl(new TopoDS_Shape(aFaceOnResult)); - this->addFromFace(aFSHape); + this->addFromShape(aFSHape); } if(aFaceSurface == aToSurface) { std::shared_ptr aTSHape(new GeomAPI_Shape); aTSHape->setImpl(new TopoDS_Shape(aFaceOnResult)); - this->addToFace(aTSHape); + this->addToShape(aTSHape); } } } else { //Case 3: When only one bounding plane was set. @@ -324,7 +324,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBase for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) { std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(anIt.Value())); - isFromFaceSet ? this->addFromFace(aShape) : this->addToFace(aShape); + isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape); } // Try to cut with base face. If it can not be done then keep result of cut with bounding plane. @@ -366,7 +366,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBase for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) { std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(anIt.Value())); - isFromFaceSet ? this->addToFace(aShape) : this->addFromFace(aShape); + isFromFaceSet ? this->addToShape(aShape) : this->addFromShape(aShape); } TopExp_Explorer anExp(aResult, TopAbs_SOLID); @@ -408,7 +408,7 @@ void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBase if(aFaceSurface == aBoundingSurface) { std::shared_ptr aShape(new GeomAPI_Shape()); aShape->setImpl(new TopoDS_Shape(aFaceOnResult)); - isFromFaceSet ? this->addFromFace(aShape) : this->addToFace(aShape); + isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape); } } } diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 852163df3..d506c0023 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -24,11 +24,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -298,3 +300,27 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::fitPlaneToBox(const std:: return aResultShape; } + +//================================================================================================= +void GeomAlgoAPI_ShapeTools::findBounds(const std::shared_ptr theShape, + std::shared_ptr& theV1, + std::shared_ptr& theV2) +{ + if(!theShape.get()) { + std::shared_ptr aVertex(new GeomAPI_Vertex); + aVertex->setImpl(new TopoDS_Vertex()); + theV1 = aVertex; + theV2 = aVertex; + return; + } + + const TopoDS_Shape& aShape = theShape->impl(); + TopoDS_Vertex aV1, aV2; + ShapeAnalysis::FindBounds(aShape, aV1, aV2); + + std::shared_ptr aGeomV1(new GeomAPI_Vertex()), aGeomV2(new GeomAPI_Vertex()); + aGeomV1->setImpl(new TopoDS_Vertex(aV1)); + aGeomV2->setImpl(new TopoDS_Vertex(aV2)); + theV1 = aGeomV1; + theV2 = aGeomV2; +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h index d361eb927..8726f670a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h @@ -7,16 +7,15 @@ #ifndef GeomAlgoAPI_ShapeTools_H_ #define GeomAlgoAPI_ShapeTools_H_ -#include +#include "GeomAlgoAPI.h" + #include #include +#include -#include - -/** \class GeomAlgoAPI_ShapeTools - * \ingroup DataAlgo - * \brief Useful tools for working with shapes. - */ +/// \class GeomAlgoAPI_ShapeTools +/// \ingroup DataAlgo +/// \brief Useful tools for working with shapes. class GEOMALGOAPI_EXPORT GeomAlgoAPI_ShapeTools { public: @@ -27,37 +26,42 @@ public: /// are expressed in the absolute Cartesian coordinate system. (This function works only for surfaces). static std::shared_ptr centreOfMass(const std::shared_ptr theShape); - /** \brief Combines faces with common edges to shells, or solids to compsolids. - * \param[in] theCompound compound of shapes. - * \param[in] theType type of combine. - * \param[out] theCombinedShapes resulting shapes. - * \param[out] theFreeShapes shapes that does not have common subshapes. - */ + /// \brief Combines faces with common edges to shells, or solids to compsolids. + /// \param[in] theCompound compound of shapes. + /// \param[in] theType type of combine. + /// \param[out] theCombinedShapes resulting shapes. + /// \param[out] theFreeShapes shapes that does not have common subshapes. static void combineShapes(const std::shared_ptr theCompound, const GeomAPI_Shape::ShapeType theType, ListOfShape& theCombinedShapes, ListOfShape& theFreeShapes); - /** \brief Calculates bounding box for theShapes - * \return list of eight points. - * \param[in] theShapes list of shapes. - * \param[in] theEnlarge enlarges bounding box size. - */ + /// \brief Calculates bounding box for theShapes + /// \return list of eight points. + /// \param[in] theShapes list of shapes. + /// \param[in] theEnlarge enlarges bounding box size. static std::list > getBoundingBox(const ListOfShape& theShapes, const double theEnlarge = 0.0); - /** - * Returns infinite plane received from theFace plane. - */ + /// \return infinite plane received from theFace plane. static std::shared_ptr faceToInfinitePlane(const std::shared_ptr theFace); - /** \brief Enlarges or reduces plane to fit bounding box. - * \return plane that fits to bounding box. - * \param[in] thePlane base plane. - * \param[in] thePoints bounding box points (shoud be eight). - */ + /// \brief Enlarges or reduces plane to fit bounding box. + /// \return plane that fits to bounding box. + /// \param[in] thePlane base plane. + /// \param[in] thePoints bounding box points (shoud be eight). static std::shared_ptr fitPlaneToBox(const std::shared_ptr thePlane, const std::list >& thePoints); + /// \brief Finds the start and end vertices of theShape. theShape can be of the following type:\n + /// Vertex: theV1 and theV2 are the same and equal to theShape;\n + /// Edge : theV1 is start and theV2 is end vertex;\n + /// Wire : theV1 is start vertex of the first edge, theV2 is end vertex of the last edge. If wire + /// contains no edges theV1 and theV2 are nullified.\n + /// If none of the above theV1 and theV2 are nullified. + static void findBounds(const std::shared_ptr theShape, + std::shared_ptr& theV1, + std::shared_ptr& theV2); + }; #endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h index 6c9f54bc7..f82daf66d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h @@ -35,6 +35,7 @@ #include "GeomAlgoAPI_Transform.h" #include "GeomAlgoAPI_PaveFiller.h" #include "GeomAlgoAPI_Intersection.h" + #include "GeomAlgoAPI_Pipe.h" #include #include diff --git a/src/GeomValidators/CMakeLists.txt b/src/GeomValidators/CMakeLists.txt index af20eedc4..c0f6b1cba 100644 --- a/src/GeomValidators/CMakeLists.txt +++ b/src/GeomValidators/CMakeLists.txt @@ -19,6 +19,7 @@ SET(PROJECT_HEADERS GeomValidators_Different.h GeomValidators_BooleanSelection.h GeomValidators_IntersectionSelection.h + GeomValidators_BaseForGeneration.h ) SET(PROJECT_SOURCES @@ -37,6 +38,7 @@ SET(PROJECT_SOURCES GeomValidators_Different.cpp GeomValidators_BooleanSelection.cpp GeomValidators_IntersectionSelection.cpp + GeomValidators_BaseForGeneration.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomValidators/GeomValidators_BaseForGeneration.cpp b/src/GeomValidators/GeomValidators_BaseForGeneration.cpp new file mode 100644 index 000000000..7ef5502a7 --- /dev/null +++ b/src/GeomValidators/GeomValidators_BaseForGeneration.cpp @@ -0,0 +1,123 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomValidators_BaseForGeneration.cpp +// Created: 18 March 2016 +// Author: Dmitry Bobylev + +#include "GeomValidators_BaseForGeneration.h" + +#include +#include + +#include + +//================================================================================================= +bool GeomValidators_BaseForGeneration::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + // Checking attribute. + if(!isValidAttribute(theAttribute, theError)) { + if(theError.empty()) { + theError = "Attribute contains shape with unacceptable type."; + } + return false; + } + + return true; +} + +//================================================================================================= +bool GeomValidators_BaseForGeneration::isValidAttribute(const AttributePtr& theAttribute, + std::string& theError) const +{ + if(!theAttribute.get()) { + theError = "Empty attribute."; + return false; + } + + std::string anAttributeType = theAttribute->attributeType(); + if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) { + AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast(theAttribute); + for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) { + // If at least one attribute is invalid, the result is false. + if(!isValidAttribute(aListAttr->value(anIndex), theError)) { + return false; + } + } + } else if(anAttributeType == ModelAPI_AttributeSelection::typeId()) { + // Getting context. + AttributeSelectionPtr anAttr = std::dynamic_pointer_cast(theAttribute); + ResultPtr aContext = anAttr->context(); + if(!aContext.get()) { + theError = "Attribute have empty context."; + return false; + } + + // Getting feature. + FeaturePtr aFeature = ModelAPI_Feature::feature(aContext); + if(!aFeature.get()) { + theError = "Empty feature."; + return false; + } + + // Checking feature kind. + std::string aFeatureKind = aFeature->getKind(); + if(aFeatureKind == "Axis" || + aFeatureKind == "Plane") { + theError = "Shape from feature \"" + aFeatureKind +"\" is not allowed for selection."; + return false; + } + + GeomShapePtr aShape = anAttr->value(); + GeomShapePtr aContextShape = aContext->shape(); + if(!aShape.get()) { + aShape = aContextShape; + } + if(!aShape.get()) { + theError = "Empty shape selected"; + return false; + } + + if(aFeatureKind == "Sketch") { + if(aShape->isEqual(aContextShape)) { + // Whole sketch selected. Check that it have faces. + ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aContext); + if(aConstruction->facesNum() == 0) { + theError = "Selected sketch does not have faces."; + return false; + } + } else { + // Shape on sketch selected. Check that it is a face. + if(aShape->shapeType() != GeomAPI_Shape::FACE) { + theError = "Selected shape has unacceptable type. Acceptable types are: faces on sketch, \ + whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face."; + return false; + } + } + } else { + if(!aShape->isEqual(aContextShape)) { + // Local selection does not allowed. + theError = "Selected shape is in the local selection. Only global selection is allowed."; + return false; + } else { + // Check that object is a shape with allowed type. + aShape = aContext->shape(); + GeomAPI_Shape::ShapeType aShapeType = aShape->shapeType(); + if(aShapeType != GeomAPI_Shape::VERTEX && + aShapeType != GeomAPI_Shape::EDGE && + aShapeType != GeomAPI_Shape::WIRE && + aShapeType != GeomAPI_Shape::FACE) { + theError = "Selected shape has unacceptable type. Acceptable types are: faces on sketch, \ + whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face."; + return false; + } + } + } + } else { + theError = "Following attribute does not supported: " + anAttributeType + "."; + return false; + } + + return true; +} \ No newline at end of file diff --git a/src/GeomValidators/GeomValidators_BaseForGeneration.h b/src/GeomValidators/GeomValidators_BaseForGeneration.h new file mode 100644 index 000000000..eebff32a2 --- /dev/null +++ b/src/GeomValidators/GeomValidators_BaseForGeneration.h @@ -0,0 +1,35 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomValidators_BaseForGeneration.h +// Created: 18 March 2016 +// Author: Dmitry Bobylev + +#ifndef GeomValidators_BaseForGeneration_H +#define GeomValidators_BaseForGeneration_H + +#include "GeomValidators.h" + +#include + +#include + +/// \ingroup Validators +/// A validator for selection base for generation. Allows to select faces on sketch, +/// whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face. +class GeomValidators_BaseForGeneration : public ModelAPI_AttributeValidator +{ +public: + //! Returns 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. + GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const; + +private: + bool isValidAttribute(const AttributePtr& theAttribute, + std::string& theError) const; +}; + +#endif diff --git a/src/GeomValidators/GeomValidators_BooleanSelection.cpp b/src/GeomValidators/GeomValidators_BooleanSelection.cpp index c4af6a2e4..cc8823fed 100644 --- a/src/GeomValidators/GeomValidators_BooleanSelection.cpp +++ b/src/GeomValidators/GeomValidators_BooleanSelection.cpp @@ -27,27 +27,27 @@ bool GeomValidators_BooleanSelection::isValid(const AttributePtr& theAttribute, theError = "Error: empty attribute selection."; return false; } + ResultPtr aContext = anAttrSelection->context(); + if(!aContext.get()) { + theError = "Error: empty selection context."; + return false; + } + FeaturePtr aFeature = ModelAPI_Feature::feature(aContext); + if(!aFeature.get()) { + theError = "Error: empty feature."; + return false; + } + std::string aFeatureKind = aFeature->getKind(); + if(aFeatureKind == "Sketch" || + aFeatureKind == "Plane" || + aFeatureKind == "Axis") { + theError = "Error: "; + theError += aFeatureKind; + theError += " shape is not allowed for selection."; + return false; + } std::shared_ptr aShape = anAttrSelection->value(); if(!aShape.get()) { - ResultPtr aContext = anAttrSelection->context(); - if(!aContext.get()) { - theError = "Error: empty selection context."; - return false; - } - FeaturePtr aFeature = ModelAPI_Feature::feature(aContext); - if(!aFeature.get()) { - theError = "Error: empty feature."; - return false; - } - std::string aFeatureKind = aFeature->getKind(); - if(aFeatureKind == "Sketch" || - aFeatureKind == "Plane" || - aFeatureKind == "Axis") { - theError = "Error: "; - theError += aFeatureKind; - theError += " shape is not allowed for selection."; - return false; - } aShape = aContext->shape(); } if(!aShape.get()) { diff --git a/src/GeomValidators/GeomValidators_Plugin.cpp b/src/GeomValidators/GeomValidators_Plugin.cpp index 824206f63..3cfe3e6ea 100644 --- a/src/GeomValidators/GeomValidators_Plugin.cpp +++ b/src/GeomValidators/GeomValidators_Plugin.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,7 @@ GeomValidators_Plugin::GeomValidators_Plugin() aFactory->registerValidator("GeomValidators_ZeroOffset", new GeomValidators_ZeroOffset); aFactory->registerValidator("GeomValidators_BooleanSelection", new GeomValidators_BooleanSelection); aFactory->registerValidator("GeomValidators_IntersectionSelection", new GeomValidators_IntersectionSelection); + aFactory->registerValidator("GeomValidators_BaseForGeneration", new GeomValidators_BaseForGeneration); // register this plugin ModelAPI_Session::get()->registerPlugin(this); diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 3ba9a1c50..9b0833a4a 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -182,7 +182,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, std::shared_ptr Model_AttributeSelection::value() { if (myTmpContext.get() || myTmpSubShape.get()) { - return myTmpSubShape; + return myTmpSubShape.get() ? myTmpSubShape : myTmpContext->shape(); } std::shared_ptr aResult; diff --git a/src/Model/Model_BodyBuilder.cpp b/src/Model/Model_BodyBuilder.cpp index 1d3b8a4d5..f84c169b2 100755 --- a/src/Model/Model_BodyBuilder.cpp +++ b/src/Model/Model_BodyBuilder.cpp @@ -307,6 +307,22 @@ void Model_BodyBuilder::generated(const std::shared_ptr& theOldSh builder(theTag)->Generated(anOldShape, aNewShape); if(!theName.empty()) buildName(theTag, theName); + TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType(); + if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) { + TopAbs_ShapeEnum anExplodeShapeType = aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; + const TDF_Label aLabel = builder(theTag)->NamedShape()->Label(); + int aTag = 1; + std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); + for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) { + TDF_Label aChildLabel = aLabel.FindChild(aTag); + TNaming_Builder aBuilder(aChildLabel); + aBuilder.Generated(anOldShape, anExp.Current()); + TCollection_AsciiString aChildName = TCollection_AsciiString((data()->name() + "/" + theName + "_").c_str()) + aTag; + aDoc->addNamingName(aChildLabel, aChildName.ToCString()); + TDataStd_Name::Set(aChildLabel, aChildName.ToCString()); + aTag++; + } + } } @@ -406,7 +422,7 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( { TopoDS_Shape aShapeIn = theShapeIn->impl(); TopTools_MapOfShape aView; - bool isBuilt = theName.empty(); + bool isBuilt = !theName.empty(); TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { const TopoDS_Shape& aRoot = aShapeExplorer.Current (); @@ -417,15 +433,31 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes ( theMS->generated(aRShape, aList); std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); for (; anIt != aLast; anIt++) { - TopoDS_Shape aNewShape = (*anIt)->impl(); + TopoDS_Shape aNewShape = (*anIt)->impl(); if (theSubShapes.isBound(*anIt)) { std::shared_ptr aMapShape(theSubShapes.find(*anIt)); aNewShape.Orientation(aMapShape->impl().Orientation()); } if (!aRoot.IsSame (aNewShape)) { builder(theTag)->Generated(aRoot,aNewShape); - if(!isBuilt) - buildName(theTag, theName); + if(isBuilt) + buildName(theTag, theName); + } + TopAbs_ShapeEnum aGenShapeType = aNewShape.ShapeType(); + if(aGenShapeType == TopAbs_WIRE || aGenShapeType == TopAbs_SHELL) { + TopAbs_ShapeEnum anExplodeShapeType = aGenShapeType == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; + const TDF_Label aLabel = builder(theTag)->NamedShape()->Label(); + int aTag = 1; + std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); + for(TopExp_Explorer anExp(aNewShape, anExplodeShapeType); anExp.More(); anExp.Next()) { + TDF_Label aChildLabel = aLabel.FindChild(aTag); + TNaming_Builder aBuilder(aChildLabel); + aBuilder.Generated(aRoot, anExp.Current()); + TCollection_AsciiString aChildName = TCollection_AsciiString((data()->name() + "/" + theName + "_").c_str()) + aTag; + aDoc->addNamingName(aChildLabel, aChildName.ToCString()); + TDataStd_Name::Set(aChildLabel, aChildName.ToCString()); + aTag++; + } } } } diff --git a/src/PartSet/PartSet_icons.qrc b/src/PartSet/PartSet_icons.qrc index cd7a24570..ff09bfce3 100644 --- a/src/PartSet/PartSet_icons.qrc +++ b/src/PartSet/PartSet_icons.qrc @@ -97,5 +97,9 @@ icons/intersection_point.png icons/intersection.png icons/move_to_end.png + icons/pipe.png + icons/pipe_simple_32x32.png + icons/pipe_binormal_32x32.png + icons/pipe_locations_32x32.png diff --git a/src/PartSet/icons/pipe.png b/src/PartSet/icons/pipe.png new file mode 100644 index 000000000..793874472 Binary files /dev/null and b/src/PartSet/icons/pipe.png differ diff --git a/src/PartSet/icons/pipe_binormal_32x32.png b/src/PartSet/icons/pipe_binormal_32x32.png new file mode 100644 index 000000000..b262ec90a Binary files /dev/null and b/src/PartSet/icons/pipe_binormal_32x32.png differ diff --git a/src/PartSet/icons/pipe_locations_32x32.png b/src/PartSet/icons/pipe_locations_32x32.png new file mode 100644 index 000000000..5e384ce30 Binary files /dev/null and b/src/PartSet/icons/pipe_locations_32x32.png differ diff --git a/src/PartSet/icons/pipe_simple_32x32.png b/src/PartSet/icons/pipe_simple_32x32.png new file mode 100644 index 000000000..793874472 Binary files /dev/null and b/src/PartSet/icons/pipe_simple_32x32.png differ