From 393cfb1948498b0adb2d10a25a6cc9e5b7dc7e59 Mon Sep 17 00:00:00 2001 From: szy Date: Thu, 30 Oct 2014 19:17:29 +0300 Subject: [PATCH] 30.10.2014. Redesigned boolean feature. --- src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp | 75 +++++++++--- src/FeaturesPlugin/FeaturesPlugin_Boolean.h | 11 +- .../FeaturesPlugin_Extrusion.cpp | 1 - src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp | 110 +++++++++++++++++- src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h | 62 ++++++++-- src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp | 47 +++----- src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h | 23 ++-- 7 files changed, 252 insertions(+), 77 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp index 3161b31c2..e582019b4 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.cpp @@ -10,9 +10,16 @@ #include #include #include - +#include using namespace std; +#ifdef _DEBUG +#include +#include +#endif +#define FACE 4 +#define _MODIFY_TAG 1 +#define _DELETED_TAG 2 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean() { } @@ -46,25 +53,61 @@ void FeaturesPlugin_Boolean::execute() return; int aType = aTypeAttr->value(); - boost::shared_ptr aObject = this->getShape(FeaturesPlugin_Boolean::OBJECT_ID()); - if (!aObject) + boost::shared_ptr anObject = this->getShape(FeaturesPlugin_Boolean::OBJECT_ID()); + if (!anObject) return; boost::shared_ptr aTool = this->getShape(FeaturesPlugin_Boolean::TOOL_ID()); if (!aTool) return; - boost::shared_ptr aResult = document()->createBody(data()); - switch (aType) { - case BOOL_CUT: - aResult->store(GeomAlgoAPI_Boolean::makeCut(aObject, aTool)); - break; - case BOOL_FUSE: - aResult->store(GeomAlgoAPI_Boolean::makeFuse(aObject, aTool)); - break; - case BOOL_COMMON: - aResult->store(GeomAlgoAPI_Boolean::makeCommon(aObject, aTool)); - break; + boost::shared_ptr aResultBody = document()->createBody(data()); + + GeomAlgoAPI_Boolean* aFeature = new GeomAlgoAPI_Boolean(anObject, aTool, aType); + if(aFeature && !aFeature->isDone()) { + std::string aFeatureError = "Boolean feature: algorithm failed"; + Events_Error::send(aFeatureError, this); + return; } - setResult(aResult); -} \ No newline at end of file + // Check if shape is valid + if (aFeature->shape()->isNull()) { + std::string aShapeError = "Boolean feature: resulting shape is Null"; + Events_Error::send(aShapeError, this); +#ifdef _DEBUG + std::cerr << aShapeError << std::endl; +#endif + return; + } + if(!aFeature->isValid()) { + std::string aFeatureError = "Boolean feature: resulting shape is not valid"; + Events_Error::send(aFeatureError, this); + return; + } + //LoadNamingDS + LoadNamingDS(aFeature, aResultBody, anObject, aTool, aType); + + setResult(aResultBody); +} + +//============================================================================ +void FeaturesPlugin_Boolean::LoadNamingDS(GeomAlgoAPI_Boolean* theFeature, + boost::shared_ptr theResultBody, + boost::shared_ptr theObject, + boost::shared_ptr theTool, + int theType) +{ + + //load result + theResultBody->storeModified(theObject, theFeature->shape()); + + GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape(); + theFeature->mapOfShapes(*aSubShapes); + + // Put in DF modified faces + theResultBody->loadAndOrientModifiedShapes(theFeature->makeShape(), theObject, FACE, _MODIFY_TAG, *aSubShapes); + theResultBody->loadAndOrientModifiedShapes(theFeature->makeShape(), theTool, FACE, _MODIFY_TAG, *aSubShapes); + + //Put in DF deleted faces + theResultBody->loadDeletedShapes(theFeature->makeShape(), theObject, FACE, _DELETED_TAG); + theResultBody->loadDeletedShapes(theFeature->makeShape(), theTool, FACE, _DELETED_TAG); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Boolean.h b/src/FeaturesPlugin/FeaturesPlugin_Boolean.h index 159163565..0fdeb6bae 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Boolean.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Boolean.h @@ -8,6 +8,7 @@ #include "FeaturesPlugin.h" #include #include +#include class FeaturesPlugin_Boolean : public ModelAPI_Feature { @@ -38,8 +39,8 @@ class FeaturesPlugin_Boolean : public ModelAPI_Feature } enum { - BOOL_CUT, BOOL_FUSE, + BOOL_CUT, BOOL_COMMON }; @@ -62,7 +63,13 @@ class FeaturesPlugin_Boolean : public ModelAPI_Feature private: boost::shared_ptr getShape(const std::string& theAttrName); - + + /// Load Naming data structure of the feature to the document + void LoadNamingDS(GeomAlgoAPI_Boolean* theFeature, + boost::shared_ptr theResultBody, + boost::shared_ptr theObject, + boost::shared_ptr theTool, + int theType); }; #endif diff --git a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp index 7316f3c2c..eeafb1db6 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Extrusion.cpp @@ -65,7 +65,6 @@ void FeaturesPlugin_Extrusion::execute() if (data()->boolean(FeaturesPlugin_Extrusion::REVERSE_ID())->value()) aSize = -aSize; - eraseResults(); // to erase the previously stored naming structures boost::shared_ptr aResultBody = document()->createBody(data()); GeomAlgoAPI_Extrusion aFeature(aFace, aSize); if(!aFeature.isDone()) { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp index d56a226aa..e75205a02 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.cpp @@ -7,8 +7,13 @@ #include #include #include +#include +#include +#include - +#define FUSE 0 +#define CUT 1 +#define COMMON 2 boost::shared_ptr GeomAlgoAPI_Boolean::makeCut( boost::shared_ptr theShape, boost::shared_ptr theTool) @@ -57,4 +62,107 @@ boost::shared_ptr GeomAlgoAPI_Boolean::makeCommon( return aResult; } return boost::shared_ptr(); +} + +//============================================================================ +GeomAlgoAPI_Boolean::GeomAlgoAPI_Boolean(boost::shared_ptr theObject, + boost::shared_ptr theTool, + int theType) +: myOperation(theType), myDone(false), myShape(new GeomAPI_Shape()) +{ + build(theObject, theTool); +} + + +//============================================================================ +void GeomAlgoAPI_Boolean::build(boost::shared_ptr theObject, + boost::shared_ptr theTool) +{ + const TopoDS_Shape& anObject = theObject->impl(); + const TopoDS_Shape& aTool = theTool->impl(); + TopoDS_Shape aResult; + switch (myOperation) { + case BOOL_FUSE: + { + BRepAlgoAPI_Fuse* mkFuse = new BRepAlgoAPI_Fuse(anObject, aTool); + if (mkFuse && mkFuse->IsDone()) { + setImpl(mkFuse); + myDone = mkFuse->IsDone() == Standard_True; + myMkShape = new GeomAlgoAPI_MakeShape (mkFuse); + aResult = mkFuse->Shape();//GeomAlgoAPI_DFLoader::refineResult(aFuse->Shape()); + } + } + case BOOL_CUT: + { + BRepAlgoAPI_Cut* mkCut = new BRepAlgoAPI_Cut(anObject, aTool); + if (mkCut && mkCut->IsDone()) { + setImpl(mkCut); + myDone = mkCut->IsDone() == Standard_True; + myMkShape = new GeomAlgoAPI_MakeShape (mkCut); + aResult = mkCut->Shape(); + } + } + case BOOL_COMMON: + { + BRepAlgoAPI_Common* mkCom = new BRepAlgoAPI_Common(anObject, aTool); + if (mkCom && mkCom->IsDone()) { + setImpl(mkCom); + myDone = mkCom->IsDone() == Standard_True; + myMkShape = new GeomAlgoAPI_MakeShape (mkCom); + aResult = mkCom->Shape(); + } + } + } + if(myDone) { + if(aResult.ShapeType() == TopAbs_COMPOUND) + aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); + myShape->setImpl(new TopoDS_Shape(aResult)); + boost::shared_ptr aGeomResult(new GeomAPI_Shape()); + aGeomResult->setImpl(new TopoDS_Shape(aResult)); + + // fill data map to keep correct orientation of sub-shapes + for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { + boost::shared_ptr aCurrentShape(new GeomAPI_Shape()); + aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current())); + myMap.bind(aCurrentShape, aCurrentShape); + } + } +} + + +//============================================================================ +const bool GeomAlgoAPI_Boolean::isDone() const +{return myDone;} + +//============================================================================ +const bool GeomAlgoAPI_Boolean::isValid() const +{ + BRepCheck_Analyzer aChecker(myShape->impl()); + return (aChecker.IsValid() == Standard_True); +} + +//============================================================================ +const boost::shared_ptr& GeomAlgoAPI_Boolean::shape () const +{ + return myShape; +} + +//============================================================================ +void GeomAlgoAPI_Boolean::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const +{ + theMap = myMap; +} + +//============================================================================ +GeomAlgoAPI_MakeShape * GeomAlgoAPI_Boolean::makeShape() const +{ + return myMkShape; +} + +//============================================================================ +GeomAlgoAPI_Boolean::~GeomAlgoAPI_Boolean() +{ + if (myImpl) { + myMap.clear(); + } } \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h b/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h index 6a8f9c657..d095ae137 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Boolean.h @@ -7,13 +7,15 @@ #include #include +#include +#include #include /**\class GeomAlgoAPI_Boolean * \ingroup DataAlgo * \brief Allows to perform of boolean operations */ -class GEOMALGOAPI_EXPORT GeomAlgoAPI_Boolean +class GeomAlgoAPI_Boolean : public GeomAPI_Interface { public: /* \brief Creates cut boolean operation @@ -21,24 +23,68 @@ class GEOMALGOAPI_EXPORT GeomAlgoAPI_Boolean * \param[in] theTool toole shape for boolean * \return a solid as result of operation */ - static boost::shared_ptr makeCut(boost::shared_ptr theShape, - boost::shared_ptr theTool); + GEOMALGOAPI_EXPORT static boost::shared_ptr makeCut( + boost::shared_ptr theShape, + boost::shared_ptr theTool); /* \brief Creates fuse boolean operation * \param[in] theShape the main shape * \param[in] theTool second shape * \return a solid as result of operation */ - static boost::shared_ptr makeFuse(boost::shared_ptr theShape, - boost::shared_ptr theTool); + GEOMALGOAPI_EXPORT static boost::shared_ptr makeFuse( + boost::shared_ptr theShape, + boost::shared_ptr theTool); /* \brief Creates common boolean operation - * \param[in] theShape the main shape + * \param[in] theObject the main shape * \param[in] theTool second shape + * \param[in] theType type of the operation: Fuse, Cut, Common * \return a solid as result of operation */ - static boost::shared_ptr makeCommon(boost::shared_ptr theShape, - boost::shared_ptr theTool); + GEOMALGOAPI_EXPORT static boost::shared_ptr makeCommon( + boost::shared_ptr theObject, + boost::shared_ptr theTool); + + enum { + BOOL_FUSE, + BOOL_CUT, + BOOL_COMMON + }; + /// Constructor + GEOMALGOAPI_EXPORT GeomAlgoAPI_Boolean (boost::shared_ptr theObject, + boost::shared_ptr theTool, + int theType); + + /// Returns True if algorithm succeed + GEOMALGOAPI_EXPORT const bool isDone() const; + + /// Returns True if resulting shape is valid + GEOMALGOAPI_EXPORT const bool isValid() const; + + /// Returns result of the boolean algorithm which may be a Solid or a Face + GEOMALGOAPI_EXPORT const boost::shared_ptr& shape () const; + + /// Returns map of sub-shapes of the result. To be used for History keeping + GEOMALGOAPI_EXPORT void mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const; + + /// Return interface for for History processing + GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape () const; + + ///Destructor + GEOMALGOAPI_EXPORT ~GeomAlgoAPI_Boolean(); + + private: + /// builds resulting shape + void build(boost::shared_ptr theObject, + boost::shared_ptr theTool); + /// fields + double mySize; + bool myDone; + int myOperation; + boost::shared_ptr myShape; + GeomAPI_DataMapOfShapeShape myMap; + GeomAlgoAPI_MakeShape * myMkShape; }; #endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp index 6955ee89a..d8eefb25d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp @@ -38,7 +38,6 @@ void GeomAlgoAPI_Extrusion::build(const boost::shared_ptr& theBas { bool isFirstNorm = true; gp_Dir aShapeNormal; - TopoDS_Face aBasis = TopoDS::Face(theBasis->impl()); Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface(aBasis)); @@ -53,29 +52,24 @@ void GeomAlgoAPI_Extrusion::build(const boost::shared_ptr& theBas if(aBuilder) { setImpl(aBuilder); myDone = aBuilder->IsDone() == Standard_True; - if (myDone) { - BRepCheck_Analyzer aChecker(aBuilder->Shape()); - myDone = aChecker.IsValid() == Standard_True; - } - if(myDone) { + if (myDone) { TopoDS_Shape aResult; if(aBuilder->Shape().ShapeType() == TopAbs_COMPOUND) aResult = GeomAlgoAPI_DFLoader::refineResult(aBuilder->Shape()); else aResult = aBuilder->Shape(); - - for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { - boost::shared_ptr aCurrentShape(new GeomAPI_Shape()); - aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current())); - myMap.bind(aCurrentShape, aCurrentShape); - } - + // fill data map to keep correct orientation of sub-shapes + for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { + boost::shared_ptr aCurrentShape(new GeomAPI_Shape()); + aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current())); + myMap.bind(aCurrentShape, aCurrentShape); + } myShape->setImpl(new TopoDS_Shape(aResult)); myFirst->setImpl(new TopoDS_Shape(aBuilder->FirstShape())); myLast->setImpl(new TopoDS_Shape(aBuilder-> LastShape())); myMkShape = new GeomAlgoAPI_MakeShape (aBuilder); - } - } + } + } } //============================================================================ @@ -85,7 +79,8 @@ const bool GeomAlgoAPI_Extrusion::isDone() const //============================================================================ const bool GeomAlgoAPI_Extrusion::isValid() const { - return myDone; + BRepCheck_Analyzer aChecker(myShape->impl()); + return (aChecker.IsValid() == Standard_True); } //============================================================================ @@ -104,25 +99,10 @@ const bool GeomAlgoAPI_Extrusion::hasVolume() const //============================================================================ const boost::shared_ptr& GeomAlgoAPI_Extrusion::shape () const -{return myShape;} - -//============================================================================ -/*void GeomAlgoAPI_Extrusion::generated( - const boost::shared_ptr theShape, ListOfShape& theHistory) { - theHistory.clear(); - if(myDone) { - const TopTools_ListOfShape& aList = implPtr() - ->Generated(theShape->impl()); - TopTools_ListIteratorOfListOfShape it(aList); - for(;it.More();it.Next()) { - boost::shared_ptr aShape(new GeomAPI_Shape()); - aShape->setImpl(&(it.Value())); - theHistory.push_back(aShape); - } - } + return myShape; } -*/ + //============================================================================ const boost::shared_ptr& GeomAlgoAPI_Extrusion::firstShape() { @@ -152,6 +132,5 @@ GeomAlgoAPI_Extrusion::~GeomAlgoAPI_Extrusion() { if (myImpl) { myMap.clear(); - //delete myImpl; } } \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h b/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h index 7a033a6ae..ead8a8a8d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -17,19 +16,15 @@ * \brief Allows to create the prism based on a given face and a direction */ -class GeomAlgoAPI_Extrusion : public GeomAPI_Interface//GeomAlgoAPI_MakeShape +class GeomAlgoAPI_Extrusion : public GeomAPI_Interface { public: /* \brief Creates extrusion for the given shape along the normal for this shape - * \param[in] theShape face or wire to be extruded + * \param[in] theBasis face or wire to be extruded * \param[in] theSize the length of extrusion (if the value is less than 0, the extrusion in opposite normal) - * \return a solid or a face which is obtained from specified one - - static boost::shared_ptr makeExtrusion(boost::shared_ptr theResult, - boost::shared_ptr theBasis, - boost::shared_ptr theContext, - double theSize); */ + * \return a solid or a face/shell which is obtained from specified one + */ /// Constructor GEOMALGOAPI_EXPORT GeomAlgoAPI_Extrusion (boost::shared_ptr theBasis, double theSize); @@ -45,26 +40,24 @@ class GeomAlgoAPI_Extrusion : public GeomAPI_Interface//GeomAlgoAPI_MakeShape /// Returns result of the Extrusion algorithm which may be a Solid or a Face GEOMALGOAPI_EXPORT const boost::shared_ptr& shape () const; - /// Returns list of shapes generated from theShape - // GEOMALGOAPI_EXPORT void generated(const boost::shared_ptr theShape, - // ListOfShape& theHistory); - /// Returns the first shape GEOMALGOAPI_EXPORT const boost::shared_ptr& firstShape(); /// returns last shape GEOMALGOAPI_EXPORT const boost::shared_ptr& lastShape(); - /// Returns map of sub-shapes of the result + /// Returns map of sub-shapes of the result. To be used for History keeping GEOMALGOAPI_EXPORT void mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const; + /// Return interface for for History processing GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape () const; + /// Destructor GEOMALGOAPI_EXPORT ~GeomAlgoAPI_Extrusion(); private: /// builds resulting shape void build(const boost::shared_ptr& theBasis); - + /// fields double mySize; bool myDone; boost::shared_ptr myShape; -- 2.39.2