From 64e9d01b48f8c4e6e22919ebceeed715d613485e Mon Sep 17 00:00:00 2001 From: dbv Date: Wed, 13 May 2015 15:53:56 +0300 Subject: [PATCH] Feature #524: 4.01. Revolution feature (not complete!) Added new feature Revolution; Added algorithm for Rotation; Added new class GeomAPI_Ax1; Added new method to GeomAlgoAPI_ShapeProps::centreOfMass; Added new validator GeomValidators_ZeroOffset (actually it is useful only for Extrusion and Revolution features); Some fixes to GeomAlgoAPI_Prism; --- src/FeaturesPlugin/CMakeLists.txt | 3 + src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 3 + .../FeaturesPlugin_Revolution.cpp | 197 ++++++++++ .../FeaturesPlugin_Revolution.h | 100 +++++ src/FeaturesPlugin/extrusion_widget.xml | 53 +-- src/FeaturesPlugin/plugin-Features.xml | 3 + src/FeaturesPlugin/revolution_widget.xml | 60 +++ src/GeomAPI/CMakeLists.txt | 6 +- src/GeomAPI/GeomAPI_Ax1.cpp | 66 ++++ src/GeomAPI/GeomAPI_Ax1.h | 49 +++ src/GeomAPI/GeomAPI_Face.cpp | 2 +- src/GeomAPI/GeomAPI_Pln.cpp | 6 + src/GeomAPI/GeomAPI_Pln.h | 4 + src/GeomAlgoAPI/CMakeLists.txt | 4 + src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp | 53 ++- src/GeomAlgoAPI/GeomAlgoAPI_Prism.h | 46 +-- src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp | 365 ++++++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h | 114 ++++++ src/GeomAlgoAPI/GeomAlgoAPI_Rotation.cpp | 111 ++++++ src/GeomAlgoAPI/GeomAlgoAPI_Rotation.h | 68 ++++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp | 28 +- src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h | 17 +- src/GeomValidators/CMakeLists.txt | 2 + .../GeomValidators_ZeroOffset.cpp | 66 ++++ .../GeomValidators_ZeroOffset.h | 35 ++ src/Model/Model_AttributeSelection.cpp | 3 +- src/PartSet/PartSet_Module.cpp | 4 + 27 files changed, 1353 insertions(+), 115 deletions(-) create mode 100644 src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_Revolution.h create mode 100644 src/FeaturesPlugin/revolution_widget.xml create mode 100644 src/GeomAPI/GeomAPI_Ax1.cpp create mode 100644 src/GeomAPI/GeomAPI_Ax1.h create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Rotation.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Rotation.h create mode 100644 src/GeomValidators/GeomValidators_ZeroOffset.cpp create mode 100644 src/GeomValidators/GeomValidators_ZeroOffset.h diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index dfce81869..6bd7dcd40 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -7,6 +7,7 @@ SET(PROJECT_HEADERS FeaturesPlugin.h FeaturesPlugin_Plugin.h FeaturesPlugin_Extrusion.h + FeaturesPlugin_Revolution.h FeaturesPlugin_Boolean.h FeaturesPlugin_Group.h FeaturesPlugin_Placement.h @@ -15,6 +16,7 @@ SET(PROJECT_HEADERS SET(PROJECT_SOURCES FeaturesPlugin_Plugin.cpp FeaturesPlugin_Extrusion.cpp + FeaturesPlugin_Revolution.cpp FeaturesPlugin_Boolean.cpp FeaturesPlugin_Group.cpp FeaturesPlugin_Placement.cpp @@ -23,6 +25,7 @@ SET(PROJECT_SOURCES SET(XML_RESOURCES plugin-Features.xml extrusion_widget.xml + revolution_widget.xml boolean_widget.xml group_widget.xml placement_widget.xml diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index 7dd5081f4..c35243e8d 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -28,6 +29,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(string theFeatureID) { if (theFeatureID == FeaturesPlugin_Extrusion::ID()) { return FeaturePtr(new FeaturesPlugin_Extrusion); + } else if (theFeatureID == FeaturesPlugin_Revolution::ID()) { + return FeaturePtr(new FeaturesPlugin_Revolution); } else if (theFeatureID == FeaturesPlugin_Boolean::ID()) { return FeaturePtr(new FeaturesPlugin_Boolean); } else if (theFeatureID == FeaturesPlugin_Group::ID()) { diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp new file mode 100644 index 000000000..304d3748a --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.cpp @@ -0,0 +1,197 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: FeaturesPlugin_Revolution.cpp +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define _LATERAL_TAG 1 +#define _FIRST_TAG 2 +#define _LAST_TAG 3 +#define EDGE 6 + +//================================================================================================= +FeaturesPlugin_Revolution::FeaturesPlugin_Revolution() +{ +} + +//================================================================================================= +void FeaturesPlugin_Revolution::initAttributes() +{ + AttributeSelectionListPtr aSelection = + std::dynamic_pointer_cast(data()->addAttribute( + FeaturesPlugin_Revolution::LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); + // revolution works with faces always + aSelection->setSelectionType("FACE"); + + data()->addAttribute(FeaturesPlugin_Revolution::AXIS_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(FeaturesPlugin_Revolution::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(FeaturesPlugin_Revolution::FROM_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); + + data()->addAttribute(FeaturesPlugin_Revolution::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId()); + data()->addAttribute(FeaturesPlugin_Revolution::TO_ANGLE_ID(), ModelAPI_AttributeDouble::typeId()); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Revolution::FROM_OBJECT_ID()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Revolution::TO_OBJECT_ID()); +} + +//================================================================================================= +void FeaturesPlugin_Revolution::execute() +{ + AttributeSelectionListPtr aFaceRefs = selectionList(FeaturesPlugin_Revolution::LIST_ID()); + + //Getting axe. + std::shared_ptr anAxis; + std::shared_ptr anEdge; + std::shared_ptr anObjRef = selection(FeaturesPlugin_Revolution::AXIS_OBJECT_ID()); + if(anObjRef && anObjRef->value()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->value())); + } + if(anEdge) { + anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), anEdge->line()->direction())); + } + + // Getting bounding planes. + std::shared_ptr aFromShape(new GeomAPI_Shape()); + std::shared_ptr aToShape(new GeomAPI_Shape()); + + anObjRef = selection(FeaturesPlugin_Revolution::FROM_OBJECT_ID()); + if(anObjRef) { + aFromShape = std::dynamic_pointer_cast(anObjRef->value()); + } + anObjRef = selection(FeaturesPlugin_Revolution::TO_OBJECT_ID()); + if(anObjRef) { + aToShape = std::dynamic_pointer_cast(anObjRef->value()); + } + + // Getting angles. + double aFromAngle = real(FeaturesPlugin_Revolution::FROM_ANGLE_ID())->value(); + double aToAngle = real(FeaturesPlugin_Revolution::TO_ANGLE_ID())->value(); + + // for each selected face generate a result + int anIndex = 0, aResultIndex = 0; + for(; anIndex < aFaceRefs->size(); anIndex++) { + std::shared_ptr aFaceRef = aFaceRefs->value(anIndex); + ResultPtr aContextRes = aFaceRef->context(); + std::shared_ptr aContext = aContextRes->shape(); + if (!aContext.get()) { + static const std::string aContextError = "The selection context is bad"; + setError(aContextError); + break; + } + + std::shared_ptr aValueFace = aFaceRef->value(); + int aFacesNum = -1; // this mean that "aFace" is used + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(aContextRes); + if (!aValueFace.get()) { // this may be the whole sketch result selected, check and get faces + if (aConstruction.get()) { + aFacesNum = aConstruction->facesNum(); + } else { + static const std::string aFaceError = "Can not find basis for extrusion"; + setError(aFaceError); + break; + } + } + + for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) { + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + std::shared_ptr aBaseShape; + if (aFacesNum == -1) { + aBaseShape = aValueFace; + } else { + aBaseShape = std::dynamic_pointer_cast(aConstruction->face(aFaceIndex)); + } + + GeomAlgoAPI_Revolution aFeature(aBaseShape, anAxis, aFromShape, aFromAngle, aToShape, aToAngle); + if(!aFeature.isDone()) { + static const std::string aFeatureError = "Revolution algorithm failed"; + setError(aFeatureError); + break; + } + + // Check if shape is valid + if(aFeature.shape()->isNull()) { + static const std::string aShapeError = "Resulting shape is Null"; + setError(aShapeError); + break; + } + if(!aFeature.isValid()) { + std::string aFeatureError = "Warning: resulting shape is not valid"; + setError(aFeatureError); + break; + } + //LoadNamingDS + LoadNamingDS(aFeature, aResultBody, aBaseShape, aContext); + + setResult(aResultBody, aResultIndex); + aResultIndex++; + + if (aFacesNum == -1) + break; + } + } + // remove the rest results if there were produced in the previous pass + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Revolution::LoadNamingDS(GeomAlgoAPI_Revolution& theFeature, + std::shared_ptr theResultBody, + std::shared_ptr theBasis, + std::shared_ptr theContext) +{ + //TODO: Fix naming + theResultBody->store(theFeature.shape()); + return; + + //load result + if(theBasis->isEqual(theContext)) + theResultBody->store(theFeature.shape()); + else + theResultBody->storeGenerated(theContext, theFeature.shape()); + + GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape(); + theFeature.mapOfShapes(*aSubShapes); + + //Insert lateral face : Face from Edge + std::string aLatName = "LateralFace"; + theResultBody->loadAndOrientGeneratedShapes(theFeature.makeShape(), theBasis, EDGE,_LATERAL_TAG, aLatName, *aSubShapes); + + ////Insert first face + //std::string aBotName = "FirstFace"; + //std::shared_ptr aBottomFace = theFeature.firstShape(); + //if(!aBottomFace->isNull()) { + // if(aSubShapes->isBound(aBottomFace)) { + // aBottomFace = aSubShapes->find(aBottomFace); + // } + // theResultBody->generated(aBottomFace, aBotName, _FIRST_TAG); + //} + + ////Insert last face + //std::string aTopName = "LastFace"; + //std::shared_ptr aTopFace = theFeature.lastShape(); + //if (!aTopFace->isNull()) { + // if (aSubShapes->isBound(aTopFace)) { + // aTopFace = aSubShapes->find(aTopFace); + // } + // theResultBody->generated(aTopFace, aTopName, _LAST_TAG); + //} +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Revolution.h b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h new file mode 100644 index 000000000..ffb7ae2a5 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Revolution.h @@ -0,0 +1,100 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: FeaturesPlugin_Revolution.h +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#ifndef FeaturesPlugin_Revolution_H_ +#define FeaturesPlugin_Revolution_H_ + +#include + +#include +#include + +class GeomAPI_Shape; +class ModelAPI_ResultBody; + +/** \class FeaturesPlugin_Revolution + * \ingroup Plugins + * \brief Feature for creation of revolution from the planar face. + * Revolution creates the lateral faces based on edges of the base face and + * the start and end faces and/or start and end angles. + */ +class FeaturesPlugin_Revolution : public ModelAPI_Feature +{ + public: + /// Revolution kind. + inline static const std::string& ID() + { + static const std::string MY_REVOLUTION_ID("Revolution"); + return MY_REVOLUTION_ID; + } + + /// Attribute name of references sketch entities list, it should contain a sketch result or + /// a pair a sketch result to sketch face. + inline static const std::string& LIST_ID() + { + static const std::string MY_GROUP_LIST_ID("base"); + return MY_GROUP_LIST_ID; + } + + /// Attribute name of an object to which the extrusion grows. + inline static const std::string& AXIS_OBJECT_ID() + { + static const std::string MY_TO_OBJECT_ID("axis_object"); + return MY_TO_OBJECT_ID; + } + + /// Attribute name of revolution angle. + inline static const std::string& TO_ANGLE_ID() + { + static const std::string MY_TO_ANGLE_ID("to_angle"); + return MY_TO_ANGLE_ID; + } + + /// Attribute name of revolution angle. + inline static const std::string& FROM_ANGLE_ID() + { + static const std::string MY_FROM_ANGLE_ID("from_angle"); + return MY_FROM_ANGLE_ID; + } + + /// Attribute name of an object to which the revolution grows. + inline static const std::string& TO_OBJECT_ID() + { + static const std::string MY_TO_OBJECT_ID("to_object"); + return MY_TO_OBJECT_ID; + } + + /// Attribute name of tool object. + inline static const std::string& FROM_OBJECT_ID() + { + static const std::string MY_FROM_OBJECT_ID("from_object"); + return MY_FROM_OBJECT_ID; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Revolution::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_Revolution(); + +private: + /// Load Naming data structure of the feature to the document. + void LoadNamingDS(GeomAlgoAPI_Revolution& theFeature, std::shared_ptr theResultBody, + std::shared_ptr theBasis, + std::shared_ptr theContext); +}; + +#endif diff --git a/src/FeaturesPlugin/extrusion_widget.xml b/src/FeaturesPlugin/extrusion_widget.xml index 5783d542c..0160e96d5 100644 --- a/src/FeaturesPlugin/extrusion_widget.xml +++ b/src/FeaturesPlugin/extrusion_widget.xml @@ -48,56 +48,5 @@ - - + diff --git a/src/FeaturesPlugin/plugin-Features.xml b/src/FeaturesPlugin/plugin-Features.xml index 7790b2839..288ae115b 100644 --- a/src/FeaturesPlugin/plugin-Features.xml +++ b/src/FeaturesPlugin/plugin-Features.xml @@ -6,6 +6,9 @@ + + + diff --git a/src/FeaturesPlugin/revolution_widget.xml b/src/FeaturesPlugin/revolution_widget.xml new file mode 100644 index 000000000..55514d392 --- /dev/null +++ b/src/FeaturesPlugin/revolution_widget.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GeomAPI/CMakeLists.txt b/src/GeomAPI/CMakeLists.txt index e1726ca50..2be8c4af2 100644 --- a/src/GeomAPI/CMakeLists.txt +++ b/src/GeomAPI/CMakeLists.txt @@ -29,7 +29,8 @@ SET(PROJECT_HEADERS GeomAPI_DataMapOfShapeShape.h GeomAPI_ICustomPrs.h GeomAPI_Vertex.h - GeomAPI_Ax3.h + GeomAPI_Ax1.h + GeomAPI_Ax3.h ) SET(PROJECT_SOURCES @@ -54,7 +55,8 @@ SET(PROJECT_SOURCES GeomAPI_DataMapOfShapeShape.cpp GeomAPI_Vertex.cpp GeomAPI_ICustomPrs.cpp - GeomAPI_Ax3.cpp + GeomAPI_Ax1.cpp + GeomAPI_Ax3.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAPI/GeomAPI_Ax1.cpp b/src/GeomAPI/GeomAPI_Ax1.cpp new file mode 100644 index 000000000..dcf5a987a --- /dev/null +++ b/src/GeomAPI/GeomAPI_Ax1.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_Ax1.cpp +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#include + +#include + +#define MY_AX1 static_cast(myImpl) + +//================================================================================================= +GeomAPI_Ax1::GeomAPI_Ax1() +: GeomAPI_Interface(new gp_Ax1()) +{ +} + +//================================================================================================= +GeomAPI_Ax1::GeomAPI_Ax1(std::shared_ptr theOrigin, + std::shared_ptr theDir) +: GeomAPI_Interface(new gp_Ax1(theOrigin->impl(), + theDir->impl())) +{ +} + +//================================================================================================= +void GeomAPI_Ax1::setOrigin(const std::shared_ptr& theOrigin) +{ + MY_AX1->SetLocation(theOrigin->impl()); +} + +//================================================================================================= +std::shared_ptr GeomAPI_Ax1::origin() const +{ + gp_Pnt aPnt = MY_AX1->Location(); + return std::shared_ptr(new GeomAPI_Pnt(aPnt.X(),aPnt.Y(),aPnt.Z())); +} + +//================================================================================================= +void GeomAPI_Ax1::setDir(const std::shared_ptr& theDir) +{ + MY_AX1->SetDirection(theDir->impl()); +} + +//================================================================================================= +std::shared_ptr GeomAPI_Ax1::dir() const +{ + gp_Dir aDir = MY_AX1->Direction(); + return std::shared_ptr(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())); +} + +//================================================================================================= +void GeomAPI_Ax1::reverse() +{ + MY_AX1->Reverse(); +} + +//================================================================================================= +std::shared_ptr GeomAPI_Ax1::reversed() +{ + gp_Ax1 anAxis = MY_AX1->Reversed(); + std::shared_ptr aPnt(new GeomAPI_Pnt(anAxis.Location().X(), anAxis.Location().Y(), anAxis.Location().Z())); + std::shared_ptr aDir(new GeomAPI_Dir(anAxis.Direction().X(), anAxis.Direction().Y(), anAxis.Direction().Z())); + return std::shared_ptr(new GeomAPI_Ax1(aPnt, aDir)); +} \ No newline at end of file diff --git a/src/GeomAPI/GeomAPI_Ax1.h b/src/GeomAPI/GeomAPI_Ax1.h new file mode 100644 index 000000000..d65d8e83d --- /dev/null +++ b/src/GeomAPI/GeomAPI_Ax1.h @@ -0,0 +1,49 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_Ax1.h +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#ifndef GEOMAPI_AX1_H_ +#define GEOMAPI_AX1_H_ + +#include +#include +#include + +/** \ingroup DataModel + * \brief The class represents an axis in 3D space. + */ +class GEOMAPI_EXPORT GeomAPI_Ax1 : public GeomAPI_Interface +{ +public: + /// Default constructor. + GeomAPI_Ax1(); + + /** \brief Ñonstructor. + * \param[in] theOrigin point of origin. + * \param[in] theDir direction of axis. + */ + GeomAPI_Ax1(std::shared_ptr theOrigin, + std::shared_ptr theDir); + + /// Sets origin point. + void setOrigin(const std::shared_ptr& theOrigin); + + /// \return the plane origin point. + std::shared_ptr origin() const; + + /// Sets direction vector. + void setDir(const std::shared_ptr& theDir); + + /// \return direction vector. + std::shared_ptr dir() const; + + /// Reverses the unit vector of this axis and assigns the result to this axis. + void reverse(); + + /// \return reversed unit vector of this axis. + std::shared_ptr reversed(); +}; + +#endif diff --git a/src/GeomAPI/GeomAPI_Face.cpp b/src/GeomAPI/GeomAPI_Face.cpp index b9dbd45df..b56959835 100644 --- a/src/GeomAPI/GeomAPI_Face.cpp +++ b/src/GeomAPI/GeomAPI_Face.cpp @@ -66,7 +66,7 @@ bool GeomAPI_Face::isPlanar() const const TopoDS_Shape& aShape = const_cast(this)->impl(); Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape)); GeomLib_IsPlanarSurface isPlanar(aSurf); - return isPlanar.IsPlanar(); + return isPlanar.IsPlanar() == Standard_True; } std::shared_ptr GeomAPI_Face::getPlane() const diff --git a/src/GeomAPI/GeomAPI_Pln.cpp b/src/GeomAPI/GeomAPI_Pln.cpp index 81c5bbc2e..4947170e9 100644 --- a/src/GeomAPI/GeomAPI_Pln.cpp +++ b/src/GeomAPI/GeomAPI_Pln.cpp @@ -5,6 +5,7 @@ // Author: Mikhail PONIKAROV #include +#include #include #include @@ -12,6 +13,11 @@ using namespace std; +GeomAPI_Pln::GeomAPI_Pln(const std::shared_ptr& theAxis) +: GeomAPI_Interface(new gp_Ax3(theAxis->impl())) +{ +} + GeomAPI_Pln::GeomAPI_Pln(const std::shared_ptr& thePoint, const std::shared_ptr& theNormal) : GeomAPI_Interface(new gp_Pln(thePoint->impl(), theNormal->impl())) diff --git a/src/GeomAPI/GeomAPI_Pln.h b/src/GeomAPI/GeomAPI_Pln.h index 8bd9668e7..8d9b6e5c1 100644 --- a/src/GeomAPI/GeomAPI_Pln.h +++ b/src/GeomAPI/GeomAPI_Pln.h @@ -10,6 +10,7 @@ #include #include +class GeomAPI_Ax3; class GeomAPI_Pnt; class GeomAPI_Dir; @@ -21,6 +22,9 @@ class GeomAPI_Dir; class GEOMAPI_EXPORT GeomAPI_Pln : public GeomAPI_Interface { public: + /// Creation of plane by the axis placement + GeomAPI_Pln(const std::shared_ptr& theAxis); + /// Creation of plane by the point and normal GeomAPI_Pln(const std::shared_ptr& thePoint, const std::shared_ptr& theNormal); diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 83a668987..3a5b04d2f 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -15,7 +15,9 @@ SET(PROJECT_HEADERS GeomAlgoAPI_SketchBuilder.h GeomAlgoAPI_Extrusion.h GeomAlgoAPI_Prism.h + GeomAlgoAPI_Revolution.h GeomAlgoAPI_Boolean.h + GeomAlgoAPI_Rotation.h GeomAlgoAPI_MakeShape.h GeomAlgoAPI_ShapeProps.h GeomAlgoAPI_DFLoader.h @@ -37,7 +39,9 @@ SET(PROJECT_SOURCES GeomAlgoAPI_SketchBuilder.cpp GeomAlgoAPI_Extrusion.cpp GeomAlgoAPI_Prism.cpp + GeomAlgoAPI_Revolution.cpp GeomAlgoAPI_Boolean.cpp + GeomAlgoAPI_Rotation.cpp GeomAlgoAPI_MakeShape.cpp GeomAlgoAPI_ShapeProps.cpp GeomAlgoAPI_DFLoader.cpp diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp index f800657de..7d2cf3233 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -// File: GeomAlgoAPI_Prism.h +// File: GeomAlgoAPI_Prism.cpp // Created: 5 May 2015 // Author: Dmitry Bobylev @@ -12,33 +12,35 @@ #include #include #include -#include #include -#include -#include #include #include -#include #include #include +//================================================================================================= GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(std::shared_ptr theBasis, std::shared_ptr theFromShape, std::shared_ptr theToShape) : myFromShape(theFromShape), myToShape(theToShape), + myDone(false), myShape(new GeomAPI_Shape()), myFirst(new GeomAPI_Shape()),myLast(new GeomAPI_Shape()) { build(theBasis); } -//============================================================================ +//================================================================================================= void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis) { + if(!theBasis || !myFromShape || !myToShape || + (myFromShape && myToShape && myFromShape->isEqual(myToShape))) { + return; + } + TopoDS_Face aBasis = TopoDS::Face(theBasis->impl()); - Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( - BRep_Tool::Surface(aBasis)); + Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(aBasis)); if(aPlane.IsNull()) { // non-planar shapes is not supported for extrusion yet return; } @@ -50,20 +52,17 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis) setImpl(aBuilder); TopoDS_Shape aFromShape = myFromShape->impl(); TopoDS_Shape aToShape = myToShape->impl(); - aBuilder->Perform(myFromShape->impl(), myToShape->impl()); - myDone = aBuilder->IsDone(); - if (myDone) { - TopoDS_Shape aResult; - if(aBuilder->Shape().ShapeType() == TopAbs_COMPOUND) { - aResult = GeomAlgoAPI_DFLoader::refineResult(aBuilder->Shape()); - } - else { - aResult = aBuilder->Shape(); - } + aBuilder->Perform(aFromShape, aToShape); + myDone = aBuilder->IsDone() == Standard_True; + if(myDone){ + TopoDS_Shape aResult = aBuilder->Shape(); TopExp_Explorer anExp(aResult, TopAbs_SOLID); if(!anExp.More()) { return; } + if(aResult.ShapeType() == TopAbs_COMPOUND) { + aResult = GeomAlgoAPI_DFLoader::refineResult(aResult); + } // fill data map to keep correct orientation of sub-shapes for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { std::shared_ptr aCurrentShape(new GeomAPI_Shape()); @@ -78,20 +77,20 @@ void GeomAlgoAPI_Prism::build(const std::shared_ptr& theBasis) } } -//============================================================================ +//================================================================================================= const bool GeomAlgoAPI_Prism::isDone() const { return myDone; } -//============================================================================ +//================================================================================================= const bool GeomAlgoAPI_Prism::isValid() const { BRepCheck_Analyzer aChecker(myShape->impl()); return (aChecker.IsValid() == Standard_True); } -//============================================================================ +//================================================================================================= const bool GeomAlgoAPI_Prism::hasVolume() const { bool hasVolume(false); @@ -105,37 +104,37 @@ const bool GeomAlgoAPI_Prism::hasVolume() const return hasVolume; } -//============================================================================ +//================================================================================================= const std::shared_ptr& GeomAlgoAPI_Prism::shape () const { return myShape; } -//============================================================================ +//================================================================================================= const std::shared_ptr& GeomAlgoAPI_Prism::firstShape() { return myFirst; } -//============================================================================ +//================================================================================================= const std::shared_ptr& GeomAlgoAPI_Prism::lastShape() { return myLast; } -//============================================================================ +//================================================================================================= void GeomAlgoAPI_Prism::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const { theMap = myMap; } -//============================================================================ +//================================================================================================= GeomAlgoAPI_MakeShape* GeomAlgoAPI_Prism::makeShape() const { return myMkShape; } -//============================================================================ +//================================================================================================= GeomAlgoAPI_Prism::~GeomAlgoAPI_Prism() { if (myImpl) { diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.h b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.h index a795e90e7..fde00d55d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Prism.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Prism.h @@ -13,55 +13,57 @@ #include #include -/**\class GeomAlgoAPI_Prism - * \ingroup DataAlgo - * \brief Allows to create the prism based on a given face and bounding planes +/** \class GeomAlgoAPI_Prism + * \ingroup DataAlgo + * \brief Allows to create the prism based on a given face and bounding planes. + * \n Note that only planar faces are allowed as bounding faces and resulting + * extrusion will be bounded by the infinite planes taken from the faces. */ - class GeomAlgoAPI_Prism : public GeomAPI_Interface { public: - /* \brief Creates extrusion for the given shape along the normal for this shape - * \param[in] theBasis face or wire to be extruded - * \param[in] theFromShape bottom bounding shape - * \param[in] theToShape top bounding shape - * \return a solid or a face/shell which is obtained from specified one + /** \brief Creates extrusion for the given shape along the normal for this shape. + * \param[in] theBasis face or wire to be extruded; + * \param[in] theFromShape bottom bounding shape; + * \param[in] theToShape top bounding shape; */ - /// Constructor GEOMALGOAPI_EXPORT GeomAlgoAPI_Prism(std::shared_ptr theBasis, std::shared_ptr theFromShape, std::shared_ptr theToShape); - /// Returns True if algorithm succeed + /// \return true if algorithm succeed. GEOMALGOAPI_EXPORT const bool isDone() const; - /// Returns True if resulting shape is valid + /// \return true if resulting shape is valid. GEOMALGOAPI_EXPORT const bool isValid() const; - /// Returns True if resulting shape has volume + /// \return true if resulting shape has volume. GEOMALGOAPI_EXPORT const bool hasVolume() const; - /// Returns result of the Prism algorithm which may be a Solid or a Face + /// \return result of the Prism algorithm. GEOMALGOAPI_EXPORT const std::shared_ptr& shape() const; - /// Returns the first shape + /// \returns the first shape. GEOMALGOAPI_EXPORT const std::shared_ptr& firstShape(); - /// returns last shape + /// \return the last shape. GEOMALGOAPI_EXPORT const std::shared_ptr& lastShape(); - - /// Returns map of sub-shapes of the result. To be used for History keeping + + /// \return 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 + /// \return interface for History processing. GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape() const; - /// Destructor + /// Destructor. GEOMALGOAPI_EXPORT ~GeomAlgoAPI_Prism(); + private: - /// builds resulting shape + /// Builds resulting shape. void build(const std::shared_ptr& theBasis); - /// fields + +private: + /// Fields. std::shared_ptr myFromShape; std::shared_ptr myToShape; bool myDone; diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp new file mode 100644 index 000000000..a608373d7 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp @@ -0,0 +1,365 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Revolution.cpp +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//================================================================================================= +GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr theBasis, + std::shared_ptr theAxis, + std::shared_ptr theFromShape, + double theFromAngle, + std::shared_ptr theToShape, + double theToAngle) +: myAxis(theAxis), + myFromShape(theFromShape), + myFromAngle(theFromAngle), + myToShape(theToShape), + myToAngle(theToAngle), + myDone(false), + myShape(new GeomAPI_Shape()), + myFirst(new GeomAPI_Shape()),myLast(new GeomAPI_Shape()) +{ + build(theBasis); +} + +//================================================================================================= +TopoDS_Face GeomAlgoAPI_Revolution::makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint) +{ + gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ(); + double aSign = aVec * thePlane.Axis().Direction().XYZ(); + if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed()); + + BRepBuilderAPI_MakeFace aMakeFace(thePlane); + TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape()); + + return aResultFace; +} + +//================================================================================================= +TopoDS_Solid GeomAlgoAPI_Revolution::makeSolidFromFace(const TopoDS_Face& theFace) +{ + TopoDS_Shell aShell; + TopoDS_Solid aSolid; + + BRep_Builder aBoundingBuilder; + aBoundingBuilder.MakeShell(aShell); + aBoundingBuilder.Add(aShell, theFace); + aBoundingBuilder.MakeSolid(aSolid); + aBoundingBuilder.Add(aSolid, aShell); + + return aSolid; +} + +//================================================================================================= +TopoDS_Shape GeomAlgoAPI_Revolution::findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint) +{ + TopoDS_Shape aResult = theShape; + + if(theShape.ShapeType() == TopAbs_COMPOUND) { + double aMinDistance = Precision::Infinite(); + double aCurDistance; + GProp_GProps aGProps; + gp_Pnt aCentr; + + for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) { + TopoDS_Shape aValue = anItr.Value(); + BRepGProp::VolumeProperties(aValue, aGProps); + aCentr = aGProps.CentreOfMass(); + aCurDistance = aCentr.Distance(thePoint); + + if(aCurDistance < aMinDistance) { + aMinDistance = aCurDistance; + aResult = aValue; + } + } + } + + return aResult; +} + +//================================================================================================= +void GeomAlgoAPI_Revolution::build(const std::shared_ptr& theBasis) +{ + if(!theBasis || !myAxis || + (((!myFromShape && !myToShape) || (myFromShape && myToShape && myFromShape->isEqual(myToShape))) + && (myFromAngle == 0.0 && myToAngle == 0.0))) { + return; + } + + TopoDS_Face aBasisFace = TopoDS::Face(theBasis->impl()); + GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace)); + if(!isBasisPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution + return; + } + gp_Pln aBasisPln = isBasisPlanar.Plan(); + gp_Ax1 anAxis = myAxis->impl(); + + TopoDS_Shape aResult; + if(!myFromShape && !myToShape) { // Case 1: When only angles was set. + // Rotating base face with the negative value of "from angle". + GeomAlgoAPI_Rotation aRotation(theBasis, myAxis, -myFromAngle); + TopoDS_Shape aRotatedBaseShape = aRotation.shape()->impl(); + + // Making revolution to the angle equal to the sum of "from angle" and "to angle". + double anAngle = myFromAngle + myToAngle; + BRepPrimAPI_MakeRevol aRevolBuilder(aRotatedBaseShape, + anAxis, + anAngle / 180 * M_PI, + Standard_True); + aRevolBuilder.Build(); + if(!aRevolBuilder.IsDone()) { + return; + } + + aResult = aRevolBuilder.Shape(); + } else if(myFromShape && myToShape) { // Case 2: When both bounding planes were set. + // Getting bounding faces. + TopoDS_Face aFromFace = TopoDS::Face(myFromShape->impl()); + TopoDS_Face aToFace = TopoDS::Face(myToShape->impl()); + + // Getting planes from bounding face. + GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace)); + GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace)); + if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution bounding + return; + } + gp_Pln aFromPln = isFromPlanar.Plan(); + gp_Pln aToPln = isToPlanar.Plan(); + + // Orienting bounding planes properly so that the center of mass of the base face stays + // on the result shape after cut. + gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeProps::centreOfMass(theBasis)->impl(); + aFromFace = makeFaceFromPlane(aFromPln, aBasisCentr); + aToFace = makeFaceFromPlane(aToPln, aBasisCentr); + + // Making solids from bounding planes and putting them in compound. + TopoDS_Shape aFromSolid = makeSolidFromFace(aFromFace); + TopoDS_Shape aToSolid = makeSolidFromFace(aToFace); + + // Rotating bounding planes to the specified angle. + gp_Trsf aFromTrsf; + gp_Trsf aToTrsf; + double aFromRotAngle = ((aFromPln.Axis().Direction() * aBasisPln.Axis().Direction()) > 0) ? -myFromAngle : myFromAngle; + double aToRotAngle = ((aToPln.Axis().Direction() * aBasisPln.Axis().Direction()) > 0) ? -myToAngle : myToAngle; + aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI); + aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI); + BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true); + BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true); + aFromSolid = aFromTransform.Shape(); + aToSolid = aToTransform.Shape(); + + // Making revolution to the 360 angle. + BRepPrimAPI_MakeRevol aRevolBuilder(aBasisFace, anAxis, 2 * M_PI, Standard_True); + aRevolBuilder.Build(); + TopoDS_Shape aRevolShape = aRevolBuilder.Shape(); + + // Cutting revolution with from plane. + BRepAlgoAPI_Cut aFromCutBuilder(aRevolShape, aFromSolid); + aFromCutBuilder.Build(); + if(!aFromCutBuilder.IsDone()) { + return; + } + aResult = aFromCutBuilder.Shape(); + + // Cutting revolution with to plane. + BRepAlgoAPI_Cut aToCutBuilder(aResult, aToSolid); + aToCutBuilder.Build(); + if(!aToCutBuilder.IsDone()) { + return; + } + aResult = aToCutBuilder.Shape(); + + // If after cut we got more than one solids then take closest to the center of mass of the base face. + aResult = findClosest(aResult, aBasisCentr); + + } else { //Case 3: When only one bounding plane was set. + // Getting bounding face. + TopoDS_Face aBoundingFace; + bool isFromFaceSet = false; + if(myFromShape) { + aBoundingFace = TopoDS::Face(myFromShape->impl()); + isFromFaceSet = true; + } else if(myToShape) { + aBoundingFace = TopoDS::Face(myToShape->impl()); + } + + // Getting plane from bounding face. + GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace)); + if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding + return; + } + gp_Pln aBoundingPln = isBoundingPlanar.Plan(); + + // Orienting bounding plane properly so that the center of mass of the base face stays + // on the result shape after cut. + gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeProps::centreOfMass(theBasis)->impl(); + aBoundingFace = makeFaceFromPlane(aBoundingPln, aBasisCentr); + + // Making solid from bounding plane. + TopoDS_Shape aBoundingSolid = makeSolidFromFace(aBoundingFace); + + // Rotating bounding plane to the specified angle. + double aBoundingRotAngle = isFromFaceSet ? myFromAngle : myToAngle; + if(aBoundingPln.Axis().IsParallel(aBasisPln.Axis(), Precision::Confusion())) { + if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle; + } else { + double aSign = (aBoundingPln.Axis().Direction() ^ aBasisPln.Axis().Direction()) * + anAxis.Direction(); + if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) { + aBoundingRotAngle = -aBoundingRotAngle; + } + } + gp_Trsf aBoundingTrsf; + aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI); + BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true); + aBoundingSolid = aBoundingTransform.Shape(); + + // Making revolution to the 360 angle. + BRepPrimAPI_MakeRevol aRevolBuilder(aBasisFace, anAxis, 2 * M_PI, Standard_True); + aRevolBuilder.Build(); + TopoDS_Shape aRevolShape = aRevolBuilder.Shape(); + + // Cutting revolution with bounding plane. + BRepAlgoAPI_Cut aFromCutBuilder(aRevolShape, aBoundingSolid); + aFromCutBuilder.Build(); + if(!aFromCutBuilder.IsDone()) { + return; + } + + // Try to cut with base face. If it can not be done then keep result of cut with bounding plane. + aResult = aFromCutBuilder.Shape(); + if(isFromFaceSet) { + aBasisFace.Orientation(TopAbs_REVERSED); + } + + // Making solid from basis face. + TopoDS_Shape aBasisSolid = makeSolidFromFace(aBasisFace); + + // Rotating basis face to the specified angle. + gp_Trsf aBasisTrsf; + double aBasisRotAngle = isFromFaceSet ? myToAngle : -myFromAngle; + aBasisTrsf.SetRotation(anAxis, aBasisRotAngle / 180.0 * M_PI); + BRepBuilderAPI_Transform aBasisTransform(aBasisSolid, aBasisTrsf, true); + aBasisSolid = aBasisTransform.Shape(); + + // Cutting revolution with basis face. + BRepAlgoAPI_Cut aBasisCutBuilder(aResult, aBasisSolid); + aBasisCutBuilder.Build(); + if(aBasisCutBuilder.IsDone()) { + TopoDS_Shape aCutResult = aBasisCutBuilder.Shape(); + TopExp_Explorer anExp(aCutResult, TopAbs_SOLID); + if(anExp.More()) { + aResult = aCutResult; + } + } + + // If after cut we got more than one solids then take closest to the center of mass of the base face. + aResult = findClosest(aResult, aBasisCentr); + } + + TopExp_Explorer anExp(aResult, TopAbs_SOLID); + if(!anExp.More()) { + return; + } + + // fill data map to keep correct orientation of sub-shapes + //for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) { + // std::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->Modified(aFromShape).First())); + //myLast->setImpl(new TopoDS_Shape(aBuilder->Modified(aToShape).First())); + //myMkShape = new GeomAlgoAPI_MakeShape (aBuilder); + myDone = true; + return; +} + +//================================================================================================= +const bool GeomAlgoAPI_Revolution::isDone() const +{ + return myDone; +} + +//================================================================================================= +const bool GeomAlgoAPI_Revolution::isValid() const +{ + BRepCheck_Analyzer aChecker(myShape->impl()); + return (aChecker.IsValid() == Standard_True); +} + +//================================================================================================= +const bool GeomAlgoAPI_Revolution::hasVolume() const +{ + bool hasVolume(false); + if(isValid()) { + const TopoDS_Shape& aRShape = myShape->impl(); + GProp_GProps aGProp; + BRepGProp::VolumeProperties(aRShape, aGProp); + if(aGProp.Mass() > Precision::Confusion()) + hasVolume = true; + } + return hasVolume; +} + +//================================================================================================= +const std::shared_ptr& GeomAlgoAPI_Revolution::shape () const +{ + return myShape; +} + +//================================================================================================= +const std::shared_ptr& GeomAlgoAPI_Revolution::firstShape() +{ + return myFirst; +} + +//================================================================================================= +const std::shared_ptr& GeomAlgoAPI_Revolution::lastShape() +{ + return myLast; +} + +//================================================================================================= +void GeomAlgoAPI_Revolution::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const +{ + theMap = myMap; +} + +//================================================================================================= +GeomAlgoAPI_MakeShape* GeomAlgoAPI_Revolution::makeShape() const +{ + return myMkShape; +} + +//================================================================================================= +GeomAlgoAPI_Revolution::~GeomAlgoAPI_Revolution() +{ + if (myImpl) { + myMap.clear(); + } +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h new file mode 100644 index 000000000..a6df8b5aa --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Revolution.h @@ -0,0 +1,114 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Revolution.h +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#ifndef GeomAlgoAPI_Revolution_H_ +#define GeomAlgoAPI_Revolution_H_ + +#include +#include +#include +#include + +class gp_Pln; +class gp_Pnt; +class TopoDS_Face; +class TopoDS_Shape; +class TopoDS_Solid; + +/** \class GeomAlgoAPI_Revolution + * \ingroup DataAlgo + * \brief Allows to create the revolution based on a given face, angles and bounding planes. + * \n Note that only the planar faces are allowed as bounding faces and resulting + * revolution will be bounded by the infinite planes taken from the faces. + * \n If the bounding plane was specified with the angle then this plane will be rotated around + * the axis to the value of the angle. + * \n Note that algorithm return only one solid object. So in case when after cutting with bounding + * planes algorithm got more than one solid it will return the closest to the center of mass of + * the base face. + */ +class GeomAlgoAPI_Revolution : public GeomAPI_Interface +{ +public: + /** \brief Creates revolution for the given shape + * \param[in] theBasis face for revolution + * \param[in] theFromShape from bounding shape + * \param[in] theFromAngle from angle + * \param[in] theToShape to bounding shape + * \param[in] theToAngle to angle + * \return a solid which is obtained from specified one + */ + GEOMALGOAPI_EXPORT GeomAlgoAPI_Revolution(std::shared_ptr theBasis, + std::shared_ptr theAxis, + std::shared_ptr theFromShape, + double theFromAngle, + std::shared_ptr theToShape, + double theToAngle); + + /// \return true if algorithm succeed. + GEOMALGOAPI_EXPORT const bool isDone() const; + + /// \return true if resulting shape is valid. + GEOMALGOAPI_EXPORT const bool isValid() const; + + /// \return true if resulting shape has volume. + GEOMALGOAPI_EXPORT const bool hasVolume() const; + + /// \return result of the Revolution algorithm. + GEOMALGOAPI_EXPORT const std::shared_ptr& shape() const; + + /// \return the first shape. + GEOMALGOAPI_EXPORT const std::shared_ptr& firstShape(); + + /// \return the last shape. + GEOMALGOAPI_EXPORT const std::shared_ptr& lastShape(); + + /// \return map of sub-shapes of the result. To be used for History keeping. + GEOMALGOAPI_EXPORT void mapOfShapes(GeomAPI_DataMapOfShapeShape& theMap) const; + + /// \return interface for History processing. + GEOMALGOAPI_EXPORT GeomAlgoAPI_MakeShape* makeShape() const; + + /// Destructor. + GEOMALGOAPI_EXPORT ~GeomAlgoAPI_Revolution(); + +private: + /** \brief Constructs infinite face from thePlane, and with axis located on the same side + * of the plane as thePoint. Modifies thePlane axis direction. + * \param[in,out] thePlane plane to construct face. + * \param[in] thePoint point to locate plane axis. + * \return constructed face. + */ + TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint); + + /// \return solid created from face. + TopoDS_Solid makeSolidFromFace(const TopoDS_Face& theFace); + + /** \brief Selects solid from theShape with closest center of mass to thePoint + * \param[in] theShape compound with solids. + * \param[in] thePoint point. + * \return solid. + */ + TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint); + + /// Builds resulting shape. + void build(const std::shared_ptr& theBasis); + +private: + /// Fields. + std::shared_ptr myAxis; + std::shared_ptr myFromShape; + double myFromAngle; + std::shared_ptr myToShape; + double myToAngle; + bool myDone; + std::shared_ptr myShape; + std::shared_ptr myFirst; + std::shared_ptr myLast; + GeomAPI_DataMapOfShapeShape myMap; + GeomAlgoAPI_MakeShape* myMkShape; +}; + +#endif \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Rotation.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Rotation.cpp new file mode 100644 index 000000000..f165e5aa8 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Rotation.cpp @@ -0,0 +1,111 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Rotation.cpp +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#include + +#include + +#include +#include +#include +#include + +//================================================================================================= +GeomAlgoAPI_Rotation::GeomAlgoAPI_Rotation(std::shared_ptr theSourceShape, + std::shared_ptr theAxis, + double theAngle) +: myDone(false), + myShape(new GeomAPI_Shape()) +{ + build(theSourceShape, theAxis, theAngle); +} + +//================================================================================================= +void GeomAlgoAPI_Rotation::build(std::shared_ptr theSourceShape, + std::shared_ptr theAxis, + double theAngle) +{ + if(!theSourceShape || !theAxis) { + return; + } + + const TopoDS_Shape& aSourceShape = theSourceShape->impl(); + const gp_Ax1& anAxis = theAxis->impl(); + + if(aSourceShape.IsNull()) { + return; + } + + gp_Trsf aTrsf; + aTrsf.SetRotation(anAxis, theAngle / 180.0 * M_PI); + + // Transform the shape with copying it. + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, aTrsf, true); + if(!aBuilder) { + return; + } + + setImpl(aBuilder); + myDone = aBuilder->IsDone() == Standard_True; + + if(!myDone) { + return; + } + + TopoDS_Shape aResult = aBuilder->Shape(); + // Fill data map to keep correct orientation of sub-shapes. + for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More(); anExp.Next()) { + std::shared_ptr aCurrentShape(new GeomAPI_Shape()); + aCurrentShape->setImpl(new TopoDS_Shape(anExp.Current())); + myMap.bind(aCurrentShape, aCurrentShape); + } + + myShape->setImpl(new TopoDS_Shape(aResult)); + myMkShape = new GeomAlgoAPI_MakeShape(aBuilder); +} + +//================================================================================================= +const bool GeomAlgoAPI_Rotation::isValid() const +{ + BRepCheck_Analyzer aChecker(myShape->impl()); + return (aChecker.IsValid() == Standard_True); +} + +//================================================================================================= +const bool GeomAlgoAPI_Rotation::hasVolume() const +{ + bool hasVolume(false); + if(isValid() && (GeomAlgoAPI_ShapeProps::volume(myShape) > Precision::Confusion())) { + hasVolume = true; + } + return hasVolume; +} + +//================================================================================================= +const std::shared_ptr& GeomAlgoAPI_Rotation::shape() const +{ + return myShape; +} + +//================================================================================================= +void GeomAlgoAPI_Rotation::mapOfShapes(GeomAPI_DataMapOfShapeShape& theMap) const +{ + theMap = myMap; +} + +//================================================================================================= +GeomAlgoAPI_MakeShape* GeomAlgoAPI_Rotation::makeShape() const +{ + return myMkShape; +} + +//================================================================================================= +GeomAlgoAPI_Rotation::~GeomAlgoAPI_Rotation() +{ + if (myImpl) { + myMap.clear(); + } +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Rotation.h b/src/GeomAlgoAPI/GeomAlgoAPI_Rotation.h new file mode 100644 index 000000000..3f77f2159 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Rotation.h @@ -0,0 +1,68 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Rotation.h +// Created: 12 May 2015 +// Author: Dmitry Bobylev + +#ifndef GeomAlgoAPI_Rotation_H_ +#define GeomAlgoAPI_Rotation_H_ + +#include +#include +#include +#include +#include + +/** \class GeomAlgoAPI_Rotation + * \ingroup DataAlgo + * \brief Creates a copy of the object by rotating it around the axis. + */ +class GeomAlgoAPI_Rotation : public GeomAPI_Interface +{ +public: + /** \brief Creates an object which is obtained from current object by rotating it around the axis. + * \param[in] theSourceShape a shape to be rotated. + * \param[in] theAxis rotation axis. + * \param[in] theAngle rotation angle(in degree). + */ + GEOMALGOAPI_EXPORT GeomAlgoAPI_Rotation(std::shared_ptr theSourceShape, + std::shared_ptr theAxis, + double theAngle); + + /// \return true if algorithm succeed. + GEOMALGOAPI_EXPORT const bool isDone() const + { return myDone; } + + /// \return true if resulting shape is valid. + GEOMALGOAPI_EXPORT const bool isValid() const; + + /// \return true if resulting shape has volume. + GEOMALGOAPI_EXPORT const bool hasVolume() const; + + /// \return result of the Placement algorithm which may be a Solid or a Face. + GEOMALGOAPI_EXPORT const std::shared_ptr& shape() const; + + /// \return 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 virtual ~GeomAlgoAPI_Rotation(); + +private: + /// Builds resulting shape. + void build(std::shared_ptr theSourceShape, + std::shared_ptr theAxis, + double theAngle); + +private: + /// Fields. + bool myDone; + std::shared_ptr myShape; + GeomAPI_DataMapOfShapeShape myMap; + GeomAlgoAPI_MakeShape* myMkShape; +}; + +#endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp index 00ef55c0e..f11155bed 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.cpp @@ -10,11 +10,33 @@ #include #include - +//================================================================================================= double GeomAlgoAPI_ShapeProps::volume(std::shared_ptr theShape) { GProp_GProps aGProps; - TopoDS_Shape aShape = theShape->impl(); + if(!theShape) { + return 0.0; + } + const TopoDS_Shape& aShape = theShape->impl(); + if(aShape.IsNull()) { + return 0.0; + } BRepGProp::VolumeProperties(aShape, aGProps); return aGProps.Mass(); -} \ No newline at end of file +} + +//================================================================================================= +std::shared_ptr GeomAlgoAPI_ShapeProps::centreOfMass(std::shared_ptr theShape) +{ + GProp_GProps aGProps; + if(!theShape) { + return NULL; + } + const TopoDS_Shape& aShape = theShape->impl(); + if(aShape.IsNull()) { + return NULL; + } + BRepGProp::SurfaceProperties(aShape, aGProps); + gp_Pnt aCentre = aGProps.CentreOfMass(); + return std::shared_ptr(new GeomAPI_Pnt(aCentre.X(), aCentre.Y(), aCentre.Z())); +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h index 636b43d85..abc7faa72 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeProps.h @@ -7,19 +7,24 @@ #ifndef GeomAlgoAPI_ShapeProps_H_ #define GeomAlgoAPI_ShapeProps_H_ -/**\class GeomAlgoAPI_ShapeProps - * \ingroup DataAlgo - * \brief Allows to compute different shape props - */ - #include + +#include #include +/** \class GeomAlgoAPI_ShapeProps + * \ingroup DataAlgo + * \brief Allows to compute different shape props. + */ class GEOMALGOAPI_EXPORT GeomAlgoAPI_ShapeProps { public: - /// Returns the total volume of the solids of the current shape + /// \return the total volume of the solids of the current shape or 0.0 if it can be computed. static double volume(std::shared_ptr theShape); + + /// \return the centre of mass of the current shape. The coordinates returned for the center of mass + /// are expressed in the absolute Cartesian coordinate system. + static std::shared_ptr centreOfMass(std::shared_ptr theShape); }; #endif diff --git a/src/GeomValidators/CMakeLists.txt b/src/GeomValidators/CMakeLists.txt index fda2411f4..2c40e8cb8 100644 --- a/src/GeomValidators/CMakeLists.txt +++ b/src/GeomValidators/CMakeLists.txt @@ -9,6 +9,7 @@ SET(PROJECT_HEADERS GeomValidators_Positive.h GeomValidators_ShapeType.h GeomValidators_Tools.h + GeomValidators_ZeroOffset.h ) SET(PROJECT_SOURCES @@ -17,6 +18,7 @@ SET(PROJECT_SOURCES GeomValidators_Positive.cpp GeomValidators_ShapeType.cpp GeomValidators_Tools.cpp + GeomValidators_ZeroOffset.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomValidators/GeomValidators_ZeroOffset.cpp b/src/GeomValidators/GeomValidators_ZeroOffset.cpp new file mode 100644 index 000000000..2aa3cf45a --- /dev/null +++ b/src/GeomValidators/GeomValidators_ZeroOffset.cpp @@ -0,0 +1,66 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomValidators_ZeroOffset.h +// Created: 13 May 2015 +// Author: Dmitry Bobylev + +#include + +#include +#include +#include + +//================================================================================================= +bool GeomValidators_ZeroOffset::isValid(const std::shared_ptr& theFeature, + const std::list& theArguments) const +{ + if(theArguments.size() < 4) { + return false; + } + + std::list::const_iterator anIt = theArguments.begin(), aLast = theArguments.end(); + + std::shared_ptr aFromShape; + std::shared_ptr aToShape; + + std::shared_ptr anAttrSel = theFeature->selection(*anIt); + if(anAttrSel) { + aFromShape = std::dynamic_pointer_cast(anAttrSel->value()); + } + anIt++; + anAttrSel = theFeature->selection(*anIt); + if(anAttrSel) { + aToShape = std::dynamic_pointer_cast(anAttrSel->value()); + } + anIt++; + + double aFromOffset = 0.0; + double aToOffset = 0.0; + + std::shared_ptr anAttrDouble = theFeature->real(*anIt); + if(anAttrDouble) { + aFromOffset = anAttrDouble->value(); + } + anIt++; + anAttrDouble = theFeature->real(*anIt); + if(anAttrDouble) { + aToOffset = anAttrDouble->value(); + } + + if(((!aFromShape && !aToShape) || ((aFromShape && aToShape) && aFromShape->isEqual(aToShape))) + && (aFromOffset == 0.0 && aToOffset == 0.0)) { + return false; + } + + return true; +} + +//================================================================================================= +bool GeomValidators_ZeroOffset::isNotObligatory(std::string theFeature, std::string theAttribute) +{ + if(theAttribute == "from_object" || theAttribute == "to_object") { + return true; + } + + return false; +} diff --git a/src/GeomValidators/GeomValidators_ZeroOffset.h b/src/GeomValidators/GeomValidators_ZeroOffset.h new file mode 100644 index 000000000..b0ce4eb67 --- /dev/null +++ b/src/GeomValidators/GeomValidators_ZeroOffset.h @@ -0,0 +1,35 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomValidators_ZeroOffset.h +// Created: 13 May 2015 +// Author: Dmitry Bobylev + +#ifndef GeomValidators_ZeroOffset_H +#define GeomValidators_ZeroOffset_H + +#include +#include +#include + +/** \class GeomValidators_ZeroOffset + * \ingroup Validators + * \brief Validates that bounding planes not the same or both offsets are not 0 + */ +class GeomValidators_ZeroOffset : public ModelAPI_FeatureValidator +{ +public: + /** \brief Returns true if feature and/or attributes are valid. + * \param[in] theFeature the validated feature. + * \param[in] theArguments the arguments in the configuration file for this validator. + * \n First pair of arguments should be bounding planes id. + * \n Second pair of arguments should be offsets id. + * \returns true if feature is valid. + */ + GEOMVALIDATORS_EXPORT virtual bool isValid(const std::shared_ptr& theFeature, + const std::list& theArguments) const; + + /// \return true if the attribute in feature is not obligatory for the feature execution. + GEOMVALIDATORS_EXPORT virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); +}; + +#endif diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index af2ca8462..4818b3a57 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -174,8 +174,7 @@ bool Model_AttributeSelection::isInitialized() TDF_Label aSelLab = selectionLabel(); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); - if (!aContext.get()) - return false; + return aContext.get(); } if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value return true; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 0927b50ee..e0a753a4b 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -28,6 +28,7 @@ #include #include +#include #include @@ -158,6 +159,9 @@ void PartSet_Module::registerValidators() aFactory->registerValidator("GeomValidators_ConstructionComposite", new GeomValidators_ConstructionComposite); + aFactory->registerValidator("GeomValidators_ZeroOffset", + new GeomValidators_ZeroOffset); + aFactory->registerValidator("PartSet_SketchEntityValidator", new PartSet_SketchEntityValidator); -- 2.30.2