From 4aa37ed1eb429f7391098b5202922d43e85fcc30 Mon Sep 17 00:00:00 2001 From: dbv Date: Tue, 26 Apr 2016 16:52:00 +0300 Subject: [PATCH] Issue #1369: Added "Create Shell" feature. --- src/BuildPlugin/BuildPlugin_Plugin.cpp | 3 + src/BuildPlugin/BuildPlugin_Shell.cpp | 94 ++++++++++++++++++++++++ src/BuildPlugin/BuildPlugin_Shell.h | 51 +++++++++++++ src/BuildPlugin/BuildPlugin_Wire.cpp | 9 +-- src/BuildPlugin/CMakeLists.txt | 3 + src/BuildPlugin/icons/feature_shell.png | Bin 0 -> 411 bytes src/BuildPlugin/plugin-Build.xml | 7 +- src/BuildPlugin/shell_widget.xml | 11 +++ src/GeomAPI/GeomAPI_Shape.cpp | 21 ++++++ src/GeomAPI/GeomAPI_Shape.h | 5 ++ src/GeomAlgoAPI/CMakeLists.txt | 2 + src/GeomAlgoAPI/GeomAlgoAPI.i | 1 + src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp | 87 ++++++++++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h | 35 +++++++++ src/GeomAlgoAPI/GeomAlgoAPI_swig.h | 3 +- 15 files changed, 321 insertions(+), 11 deletions(-) create mode 100644 src/BuildPlugin/BuildPlugin_Shell.cpp create mode 100644 src/BuildPlugin/BuildPlugin_Shell.h create mode 100644 src/BuildPlugin/icons/feature_shell.png create mode 100644 src/BuildPlugin/shell_widget.xml create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h diff --git a/src/BuildPlugin/BuildPlugin_Plugin.cpp b/src/BuildPlugin/BuildPlugin_Plugin.cpp index f11e4ba6e..d834be91f 100644 --- a/src/BuildPlugin/BuildPlugin_Plugin.cpp +++ b/src/BuildPlugin/BuildPlugin_Plugin.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include // the only created instance of this plugin @@ -46,6 +47,8 @@ FeaturePtr BuildPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new BuildPlugin_Wire()); } else if(theFeatureID == BuildPlugin_Face::ID()) { return FeaturePtr(new BuildPlugin_Face()); + } else if(theFeatureID == BuildPlugin_Shell::ID()) { + return FeaturePtr(new BuildPlugin_Shell()); } // Feature of such kind is not found. diff --git a/src/BuildPlugin/BuildPlugin_Shell.cpp b/src/BuildPlugin/BuildPlugin_Shell.cpp new file mode 100644 index 000000000..bb934a25d --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_Shell.cpp @@ -0,0 +1,94 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: BuildPlugin_Shell.cpp +// Created: 14 April 2016 +// Author: Dmitry Bobylev + +#include "BuildPlugin_Shell.h" + +#include +#include +#include + +#include +#include + +//================================================================================================= +BuildPlugin_Shell::BuildPlugin_Shell() +{ +} + +//================================================================================================= +void BuildPlugin_Shell::initAttributes() +{ + data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId()); +} + +//================================================================================================= +void BuildPlugin_Shell::execute() +{ + // Get base objects list. + AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID()); + + // Collect base shapes. + ListOfShape aShapes; + for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelection = aSelectionList->value(anIndex); + GeomShapePtr aShape = aSelection->value(); + if(!aShape.get()) { + aShape = aSelection->context()->shape(); + } + aShapes.push_back(aShape); + } + + // Sew faces. + GeomAlgoAPI_Sewing aSewingAlgo(aShapes); + + // Check that algo is done. + if(!aSewingAlgo.isDone()) { + setError("Error: " + getKind() + " algorithm failed."); + return; + } + + // Check if shape is not null. + if(!aSewingAlgo.shape().get() || aSewingAlgo.shape()->isNull()) { + setError("Error: Resulting shape is null."); + return; + } + + // Check that resulting shape is valid. + if(!aSewingAlgo.isValid()) { + setError("Error: Resulting shape is not valid."); + return; + } + + // Store result. + GeomShapePtr aResult = aSewingAlgo.shape(); + std::shared_ptr aMapOfShapes = aSewingAlgo.mapOfSubShapes(); + + int anIndex = 0; + for(GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::SHELL); anExp.more(); anExp.next()) { + GeomShapePtr aShell = anExp.current(); + ResultBodyPtr aResultBody = document()->createBody(data(), anIndex); + aResultBody->store(aShell); + for(ListOfShape::const_iterator anIt = aShapes.cbegin(); anIt != aShapes.cend(); ++anIt) { + for(GeomAPI_ShapeExplorer aFaceExp(*anIt, GeomAPI_Shape::FACE); aFaceExp.more(); aFaceExp.next()) { + GeomShapePtr aFace = aFaceExp.current(); + ListOfShape aHistory; + aSewingAlgo.modified(aFace, aHistory); + for(ListOfShape::const_iterator aHistoryIt = aHistory.cbegin(); + aHistoryIt != aHistory.cend(); + ++aHistoryIt) { + if(aShell->isSubShape(*aHistoryIt)) { + aResultBody->loadAndOrientModifiedShapes(&aSewingAlgo, aFace, GeomAPI_Shape::EDGE, + 1, "Modified", *aMapOfShapes.get()); + } + } + } + } + setResult(aResultBody, anIndex); + ++anIndex; + } + + removeResults(anIndex); +} diff --git a/src/BuildPlugin/BuildPlugin_Shell.h b/src/BuildPlugin/BuildPlugin_Shell.h new file mode 100644 index 000000000..be6341597 --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_Shell.h @@ -0,0 +1,51 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: BuildPlugin_Shell.h +// Created: 14 April 2016 +// Author: Dmitry Bobylev + +#ifndef BuildPlugin_Shell_H_ +#define BuildPlugin_Shell_H_ + +#include "BuildPlugin.h" + +#include + +/// \class BuildPlugin_Shell +/// \ingroup Plugins +/// \brief Feature for creation of shell from faces and shells. +class BuildPlugin_Shell: public ModelAPI_Feature +{ +public: + /// Use plugin manager for features creation + BuildPlugin_Shell(); + + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_ID("Shell"); + return MY_ID; + } + + /// 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; + } + + /// \return the kind of a feature. + BUILDPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = BuildPlugin_Shell::ID(); + return MY_KIND; + } + + /// Request for initialization of data model of the feature: adding all attributes. + BUILDPLUGIN_EXPORT virtual void initAttributes(); + + /// Creates a new part document if needed. + BUILDPLUGIN_EXPORT virtual void execute(); +}; + +#endif diff --git a/src/BuildPlugin/BuildPlugin_Wire.cpp b/src/BuildPlugin/BuildPlugin_Wire.cpp index 439b082b0..523c81a03 100644 --- a/src/BuildPlugin/BuildPlugin_Wire.cpp +++ b/src/BuildPlugin/BuildPlugin_Wire.cpp @@ -148,13 +148,6 @@ bool BuildPlugin_Wire::addContour() AttributeSelectionPtr aSelection = *aListIt; std::shared_ptr anEdgeInList(new GeomAPI_Edge(aSelection->value())); - ListOfShape::const_iterator anEdgesIt = anAddedEdges.cbegin(); - for(; anEdgesIt != anAddedEdges.cend(); ++anEdgesIt) { - if(anEdgeInList->isEqual(*anEdgesIt)) { - break; - } - } - ResultConstructionPtr aConstruction = std::dynamic_pointer_cast(aSelection->context()); std::shared_ptr aPlanarEdges = std::dynamic_pointer_cast(aConstruction->shape()); @@ -179,7 +172,7 @@ bool BuildPlugin_Wire::addContour() if(aFoundFace.get()) { for(GeomAPI_ShapeExplorer anExp(aFoundFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) { std::shared_ptr anEdgeOnFace(new GeomAPI_Edge(anExp.current())); - anEdgesIt = anAddedEdges.cbegin(); + ListOfShape::const_iterator anEdgesIt = anAddedEdges.cbegin(); for(; anEdgesIt != anAddedEdges.cend(); ++anEdgesIt) { if(anEdgeOnFace->isEqual(*anEdgesIt)) { break; diff --git a/src/BuildPlugin/CMakeLists.txt b/src/BuildPlugin/CMakeLists.txt index a2ada0459..0a7cda8f9 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -18,6 +18,7 @@ SET(PROJECT_HEADERS BuildPlugin_Edge.h BuildPlugin_Wire.h BuildPlugin_Face.h + BuildPlugin_Shell.h BuildPlugin_Validators.h ) @@ -27,6 +28,7 @@ SET(PROJECT_SOURCES BuildPlugin_Edge.cpp BuildPlugin_Wire.cpp BuildPlugin_Face.cpp + BuildPlugin_Shell.cpp BuildPlugin_Validators.cpp ) @@ -36,6 +38,7 @@ SET(XML_RESOURCES edge_widget.xml wire_widget.xml face_widget.xml + shell_widget.xml ) SET(PROJECT_LIBRARIES diff --git a/src/BuildPlugin/icons/feature_shell.png b/src/BuildPlugin/icons/feature_shell.png new file mode 100644 index 0000000000000000000000000000000000000000..5144ea8d08778c39fa86582d1e8bcb2f67c6416d GIT binary patch literal 411 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;>1s;*b zK=oHan9=rH#7Cf@M2TxeNpOBzNqJ&XDnmhHW?qS2UTTSgiJpO;WsY&39|HrUq^FBx zh=qUhkN^MeT_sj4XiD%ssZ}}>%9NZgc`WU(k?)zmeJ%Af)EF{#B5o-^VU5^4$G>HI zUCFV=N0Hk5^LKsv^8VZG^#zaCUXTAXcjNOj`FmG<`CWAH;ZB9wv(HTCmOFc^{GYkU z=V{sJ|K~AkF=?_q%r%c|GCb38XJvPNMvGeB1W@B9NdB2jip!~FNJb(F@NCq+qzF?ii+mM)`U^FqAL0VulgQ4&R z2C+%J43^R-+Nzsn#0?k?Kkw@9pK-#7L1Jsqfsz9pKI{qM6H*$cxN`*XE3qA5^VrE= z&v?vSV<%Ig9FuxdQi9cw=0t{F3@d?w@bQN|GsDW>-5ut~Z|ML7lEKr}&t;ucLK6T8 CMxEsV literal 0 HcmV?d00001 diff --git a/src/BuildPlugin/plugin-Build.xml b/src/BuildPlugin/plugin-Build.xml index cfa04ecf0..362eb118f 100644 --- a/src/BuildPlugin/plugin-Build.xml +++ b/src/BuildPlugin/plugin-Build.xml @@ -9,12 +9,15 @@ - + - + + + + diff --git a/src/BuildPlugin/shell_widget.xml b/src/BuildPlugin/shell_widget.xml new file mode 100644 index 000000000..fc4bca3c5 --- /dev/null +++ b/src/BuildPlugin/shell_widget.xml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index cba5be5ce..1c97ef8b4 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -250,6 +251,26 @@ std::string GeomAPI_Shape::shapeTypeStr() const return aShapeTypeStr; } +bool GeomAPI_Shape::isSubShape(const std::shared_ptr theShape) const +{ + if(!theShape.get()) { + return false; + } + + const TopoDS_Shape& aShapeToSearch = theShape->impl(); + if(aShapeToSearch.IsNull()) { + return false; + } + + for(TopExp_Explorer anExp(*MY_SHAPE, aShapeToSearch.ShapeType()); anExp.More(); anExp.Next()) { + if(aShapeToSearch.IsEqual(anExp.Current())) { + return true; + } + } + + return false; +} + 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 7adf4da80..1ed86db9c 100644 --- a/src/GeomAPI/GeomAPI_Shape.h +++ b/src/GeomAPI/GeomAPI_Shape.h @@ -78,6 +78,11 @@ public: GEOMAPI_EXPORT virtual std::string shapeTypeStr() const; + /// \return true if passed shape is a sub-shape of this shape. + /// \param theShape shape to search. + GEOMAPI_EXPORT virtual bool isSubShape(const std::shared_ptr theShape) 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 84105385f..e765913a8 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -37,6 +37,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Intersection.h GeomAlgoAPI_Pipe.h GeomAlgoAPI_WireBuilder.h + GeomAlgoAPI_Sewing.h ) SET(PROJECT_SOURCES @@ -70,6 +71,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Intersection.cpp GeomAlgoAPI_Pipe.cpp GeomAlgoAPI_WireBuilder.cpp + GeomAlgoAPI_Sewing.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI.i b/src/GeomAlgoAPI/GeomAlgoAPI.i index 8c9279226..e4efaa2ba 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI.i +++ b/src/GeomAlgoAPI/GeomAlgoAPI.i @@ -43,6 +43,7 @@ %include "GeomAlgoAPI_Intersection.h" %include "GeomAlgoAPI_Pipe.h" %include "GeomAlgoAPI_WireBuilder.h" +%include "GeomAlgoAPI_Sewing.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_Sewing.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp new file mode 100644 index 000000000..4539b0863 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.cpp @@ -0,0 +1,87 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Sewing.cpp +// Created: 25 April 2016 +// Author: Dmitry Bobylev + + +#include "GeomAlgoAPI_Sewing.h" + +#include +#include +#include +#include +#include +#include + +//================================================================================================== +GeomAlgoAPI_Sewing::GeomAlgoAPI_Sewing(const ListOfShape& theShapes) +{ + build(theShapes); +} + +void GeomAlgoAPI_Sewing::build(const ListOfShape& theShapes) +{ + if(theShapes.empty()) { + return; + } + + BRepBuilderAPI_Sewing* aSewingBuilder = new BRepBuilderAPI_Sewing(); + this->setImpl(aSewingBuilder); + + for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) { + const TopoDS_Shape& aShape = (*anIt)->impl(); + aSewingBuilder->Add(aShape); + } + + aSewingBuilder->Perform(); + + TopoDS_Shape aResult = aSewingBuilder->SewedShape(); + BRep_Builder aBuilder; + TopoDS_Compound aResultCompound; + aBuilder.MakeCompound(aResultCompound); + for(TopoDS_Iterator anIt(aResult); anIt.More(); anIt.Next()) { + const TopoDS_Shape aSubShape = anIt.Value(); + if(aSubShape.ShapeType() == TopAbs_SHELL) { + aBuilder.Add(aResultCompound, aSubShape); + } else if (aSubShape.ShapeType() == TopAbs_FACE) { + TopoDS_Shell aShell; + aBuilder.MakeShell(aShell); + aBuilder.Add(aShell, aSubShape); + aBuilder.Add(aResultCompound, aShell); + } + } + TopoDS_Iterator anIt(aResultCompound); + if(anIt.More()) { + aResult = aResultCompound; + } + + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + this->setShape(aShape); + this->setDone(true); +} + +//================================================================================================== +void GeomAlgoAPI_Sewing::modified(const std::shared_ptr theShape, + ListOfShape& theHistory) +{ + static int anIndex = 0; + if(!theShape.get()) { + return; + } + + const TopoDS_Shape& aShape = theShape->impl(); + const BRepBuilderAPI_Sewing& aSewingBuilder = this->impl(); + + TopoDS_Shape aModifiedShape = aSewingBuilder.Modified(aShape); + if(aModifiedShape.IsEqual(aShape)) { + aModifiedShape = aSewingBuilder.ModifiedSubShape(aShape); + } + + for(TopExp_Explorer anExp(aModifiedShape, aShape.ShapeType()); anExp.More(); anExp.Next()) { + GeomShapePtr aGeomShape(new GeomAPI_Shape()); + aGeomShape->setImpl(new TopoDS_Shape(anExp.Current())); + theHistory.push_back(aGeomShape); + } +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h new file mode 100644 index 000000000..aa11b861e --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Sewing.h @@ -0,0 +1,35 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Sewing.h +// Created: 25 April 2016 +// Author: Dmitry Bobylev + +#ifndef GeomAlgoAPI_Sewing_H_ +#define GeomAlgoAPI_Sewing_H_ + +#include "GeomAlgoAPI.h" +#include "GeomAlgoAPI_MakeShape.h" + +#include + +/// \class GeomAlgoAPI_Sewing +/// \ingroup DataAlgo +/// \brief Allows creation of connected topology (shells) from a set of separate topological elements (faces). +class GeomAlgoAPI_Sewing : public GeomAlgoAPI_MakeShape +{ +public: + /// Constructor. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Sewing(const ListOfShape& theShapes); + + /// \return the list of shapes modified from the shape \a theShape. + /// \param[in] theShape base shape. + /// \param[out] theHistory modified shapes. + GEOMALGOAPI_EXPORT virtual void modified(const std::shared_ptr theShape, + ListOfShape& theHistory); + +private: + /// Builds resulting shape. + void build(const ListOfShape& theShapes); +}; + +#endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h index 92327a03d..3cf49122d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h @@ -37,7 +37,8 @@ #include "GeomAlgoAPI_Intersection.h" #include "GeomAlgoAPI_Pipe.h" #include "GeomAlgoAPI_WireBuilder.h" - + #include "GeomAlgoAPI_Sewing.h" + #include #include #include -- 2.39.2