From 9a9079c59a6aaefb49725080f178559415482a19 Mon Sep 17 00:00:00 2001 From: dbv Date: Fri, 29 Apr 2016 20:50:57 +0300 Subject: [PATCH] Issue #1369: Added "SubShapes" feature. --- src/BuildPlugin/BuildPlugin_Plugin.cpp | 5 + src/BuildPlugin/BuildPlugin_SubShapes.cpp | 122 ++++++++++++ src/BuildPlugin/BuildPlugin_SubShapes.h | 62 +++++++ src/BuildPlugin/BuildPlugin_Validators.cpp | 102 +++++++++- src/BuildPlugin/BuildPlugin_Validators.h | 15 ++ src/BuildPlugin/CMakeLists.txt | 3 + src/BuildPlugin/edge_widget.xml | 3 +- src/BuildPlugin/face_widget.xml | 3 +- src/BuildPlugin/plugin-Build.xml | 7 +- src/BuildPlugin/shell_widget.xml | 3 +- src/BuildPlugin/subshapes_widget.xml | 18 ++ src/BuildPlugin/vertex_widget.xml | 3 +- src/BuildPlugin/wire_widget.xml | 3 +- src/GeomAPI/CMakeLists.txt | 4 + src/GeomAPI/GeomAPI.i | 4 + .../GeomAPI_DataMapOfShapeMapOfShapes.cpp | 9 + .../GeomAPI_DataMapOfShapeMapOfShapes.h | 32 ++-- src/GeomAPI/GeomAPI_Edge.cpp | 8 +- src/GeomAPI/GeomAPI_Edge.h | 2 +- src/GeomAPI/GeomAPI_Shape.cpp | 32 ++++ src/GeomAPI/GeomAPI_Shape.h | 19 +- src/GeomAPI/GeomAPI_ShapeIterator.cpp | 62 +++++++ src/GeomAPI/GeomAPI_ShapeIterator.h | 42 +++++ src/GeomAPI/GeomAPI_Wire.cpp | 21 +++ src/GeomAPI/GeomAPI_Wire.h | 23 +++ src/GeomAPI/GeomAPI_swig.h | 2 + src/GeomAlgoAPI/CMakeLists.txt | 2 + src/GeomAlgoAPI/GeomAlgoAPI.i | 1 + src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp | 5 +- src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp | 175 ++++++++++++++++++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h | 47 +++++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp | 80 ++++++++ src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h | 7 + src/GeomAlgoAPI/GeomAlgoAPI_swig.h | 3 +- 34 files changed, 897 insertions(+), 32 deletions(-) create mode 100644 src/BuildPlugin/BuildPlugin_SubShapes.cpp create mode 100644 src/BuildPlugin/BuildPlugin_SubShapes.h create mode 100644 src/BuildPlugin/subshapes_widget.xml create mode 100644 src/GeomAPI/GeomAPI_ShapeIterator.cpp create mode 100644 src/GeomAPI/GeomAPI_ShapeIterator.h create mode 100644 src/GeomAPI/GeomAPI_Wire.cpp create mode 100644 src/GeomAPI/GeomAPI_Wire.h create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h diff --git a/src/BuildPlugin/BuildPlugin_Plugin.cpp b/src/BuildPlugin/BuildPlugin_Plugin.cpp index d834be91f..4a0097948 100644 --- a/src/BuildPlugin/BuildPlugin_Plugin.cpp +++ b/src/BuildPlugin/BuildPlugin_Plugin.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include // the only created instance of this plugin @@ -31,6 +32,8 @@ BuildPlugin_Plugin::BuildPlugin_Plugin() new BuildPlugin_ValidatorBaseForWire()); aFactory->registerValidator("BuildPlugin_ValidatorBaseForFace", new BuildPlugin_ValidatorBaseForFace()); + aFactory->registerValidator("BuildPlugin_ValidatorSubShapesSelection", + new BuildPlugin_ValidatorSubShapesSelection()); // Register this plugin. ModelAPI_Session::get()->registerPlugin(this); @@ -49,6 +52,8 @@ FeaturePtr BuildPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new BuildPlugin_Face()); } else if(theFeatureID == BuildPlugin_Shell::ID()) { return FeaturePtr(new BuildPlugin_Shell()); + } else if(theFeatureID == BuildPlugin_SubShapes::ID()) { + return FeaturePtr(new BuildPlugin_SubShapes()); } // Feature of such kind is not found. diff --git a/src/BuildPlugin/BuildPlugin_SubShapes.cpp b/src/BuildPlugin/BuildPlugin_SubShapes.cpp new file mode 100644 index 000000000..d0e1af594 --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_SubShapes.cpp @@ -0,0 +1,122 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: BuildPlugin_SubShapes.cpp +// Created: 14 April 2016 +// Author: Dmitry Bobylev + +#include "BuildPlugin_SubShapes.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +//================================================================================================== +BuildPlugin_SubShapes::BuildPlugin_SubShapes() +{ +} + +//================================================================================================== +void BuildPlugin_SubShapes::initAttributes() +{ + data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(SUB_SHAPES_ID(), ModelAPI_AttributeSelectionList::typeId()); + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SUB_SHAPES_ID()); +} + +void BuildPlugin_SubShapes::attributeChanged(const std::string& theID) +{ + ModelAPI_Feature::attributeChanged(theID); + + if(theID == BASE_SHAPE_ID()) { + AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID()); + AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUB_SHAPES_ID()); + if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) { + return; + } + ResultPtr aContext = aShapeAttrSelection->context(); + + aSubShapesAttrList->clear(); + + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + return; + } + GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType(); + for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) { + GeomShapePtr aSubShape = anIt.current(); + if(aBaseShapeType == GeomAPI_Shape::WIRE) { + for(GeomAPI_ShapeIterator aSubIt(aSubShape); aSubIt.more(); aSubIt.next()) { + GeomShapePtr aSubOfSubShape = aSubIt.current(); + if(aSubOfSubShape->orientation() == GeomAPI_Shape::INTERNAL) { + aSubShapesAttrList->append(aContext, aSubOfSubShape); + } + } + } else if(aBaseShapeType == GeomAPI_Shape::FACE) { + if(aSubShape->shapeType() != GeomAPI_Shape::WIRE) { + aSubShapesAttrList->append(aContext, aSubShape); + } else if(aSubShape->orientation() == GeomAPI_Shape::INTERNAL) { + if(aSubShape->shapeType() == GeomAPI_Shape::WIRE) { + for(GeomAPI_ShapeIterator aWireIt(aSubShape); aWireIt.more(); aWireIt.next()) { + aSubShapesAttrList->append(aContext, aWireIt.current()); + } + } + } + } + } + } +} + +//================================================================================================== +void BuildPlugin_SubShapes::execute() +{ + // Get base shape and sub-shapes list. + AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID()); + AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUB_SHAPES_ID()); + if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) { + return; + } + + // Get base shape without internal shapes. + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + return; + } + GeomAlgoAPI_ShapeBuilder aBuilder; + aBuilder.removeInternal(aBaseShape); + GeomShapePtr aResultShape = aBuilder.shape(); + + // Get list of shapes. + ListOfShape aShapesToAdd; + for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) { + AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex); + aShapesToAdd.push_back(anAttrSelectionInList->value()); + } + + // Copy sub-shapes from list to new shape. + if(!aShapesToAdd.empty()) { + aBuilder.add(aResultShape, aShapesToAdd); + aResultShape = aBuilder.shape(); + } + + // Store result. + ResultBodyPtr aResultBody = document()->createBody(data()); + aResultBody->storeModified(aBaseShape, aResultShape); + aResultBody->loadAndOrientModifiedShapes(&aBuilder, aBaseShape, GeomAPI_Shape::EDGE, 1, + "Modified_Edge", *aBuilder.mapOfSubShapes().get()); + for(ListOfShape::const_iterator anIt = aShapesToAdd.cbegin(); anIt != aShapesToAdd.cend(); ++anIt) { + GeomAPI_Shape::ShapeType aShType = (*anIt)->shapeType(); + aResultBody->loadAndOrientModifiedShapes(&aBuilder, *anIt, aShType, 1, + aShType == GeomAPI_Shape::VERTEX ? "Modified_Vertex" : "Modified_Edge", + *aBuilder.mapOfSubShapes().get()); + } + setResult(aResultBody); +} diff --git a/src/BuildPlugin/BuildPlugin_SubShapes.h b/src/BuildPlugin/BuildPlugin_SubShapes.h new file mode 100644 index 000000000..8910f0c0f --- /dev/null +++ b/src/BuildPlugin/BuildPlugin_SubShapes.h @@ -0,0 +1,62 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: BuildPlugin_SubShapes.h +// Created: 14 April 2016 +// Author: Dmitry Bobylev + +#ifndef BuildPlugin_SubShapes_H_ +#define BuildPlugin_SubShapes_H_ + +#include "BuildPlugin.h" + +#include + +/// \class BuildPlugin_SubShapes +/// \ingroup Plugins +/// \brief Feature for adding or removing sub-shapes from shape. +class BuildPlugin_SubShapes: public ModelAPI_Feature +{ +public: + /// Use plugin manager for features creation + BuildPlugin_SubShapes(); + + /// Feature kind. + inline static const std::string& ID() + { + static const std::string MY_ID("SubShapes"); + return MY_ID; + } + + /// Attribute name of base shape. + inline static const std::string& BASE_SHAPE_ID() + { + static const std::string MY_BASE_SHAPE_ID("base_shape"); + return MY_BASE_SHAPE_ID; + } + + /// Attribute name of sub-shapes. + inline static const std::string& SUB_SHAPES_ID() + { + static const std::string MY_SUB_SHAPES_ID("sub_shapes"); + return MY_SUB_SHAPES_ID; + } + + /// \return the kind of a feature. + BUILDPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = BuildPlugin_SubShapes::ID(); + return MY_KIND; + } + + /// Request for initialization of data model of the feature: adding all attributes. + BUILDPLUGIN_EXPORT virtual void initAttributes(); + + /// Called on change of any argument-attribute of this object. + /// \param[in] theID identifier of changed attribute. + BUILDPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID); + + /// Creates a new part document if needed. + BUILDPLUGIN_EXPORT virtual void execute(); +}; + +#endif diff --git a/src/BuildPlugin/BuildPlugin_Validators.cpp b/src/BuildPlugin/BuildPlugin_Validators.cpp index dfdd20d39..cde7cf95b 100644 --- a/src/BuildPlugin/BuildPlugin_Validators.cpp +++ b/src/BuildPlugin/BuildPlugin_Validators.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -30,11 +31,13 @@ bool BuildPlugin_ValidatorBaseForBuild::isValid(const AttributePtr& theAttribute { // Get base objects list. if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) { - Events_Error::send("Error: BuildPlugin_ValidatorBaseForBuild does not support attribute type \"" + theAttribute->attributeType() - + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + "\" supported."); + Events_Error::send("Error: BuildPlugin_ValidatorBaseForBuild does not support attribute type \"" + + theAttribute->attributeType() + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + + "\" supported."); return false; } - AttributeSelectionListPtr aSelectionList = std::dynamic_pointer_cast(theAttribute); + AttributeSelectionListPtr aSelectionList = + std::dynamic_pointer_cast(theAttribute); if(!aSelectionList.get()) { theError = "Could not get selection list."; return false; @@ -109,7 +112,8 @@ bool BuildPlugin_ValidatorBaseForWire::isValid(const std::shared_ptrselectionList(theArguments.front()); @@ -153,7 +157,8 @@ bool BuildPlugin_ValidatorBaseForFace::isValid(const std::shared_ptrselectionList(theArguments.front()); @@ -218,3 +223,90 @@ bool BuildPlugin_ValidatorBaseForFace::isNotObligatory(std::string theFeature, s { return false; } + +//================================================================================================= +bool BuildPlugin_ValidatorSubShapesSelection::isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const +{ + if(theArguments.size() != 2) { + Events_Error::send("Error: BuildPlugin_ValidatorSubShapesSelection should be used only with " + "2 parameters (ID of base shape; Sketch feature id)."); + return false; + } + + // Get base objects list. + if(theAttribute->attributeType() != ModelAPI_AttributeSelectionList::typeId()) { + Events_Error::send("Error: BuildPlugin_ValidatorSubShapesSelection does not support attribute type \"" + + theAttribute->attributeType() + "\"\n Only \"" + ModelAPI_AttributeSelectionList::typeId() + + "\" supported."); + return false; + } + AttributeSelectionListPtr aSelectionList = + std::dynamic_pointer_cast(theAttribute); + if(!aSelectionList.get()) { + theError = "Could not get selection list."; + return false; + } + + // Get base shape. + FeaturePtr aFeature = ModelAPI_Feature::feature(theAttribute->owner()); + AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(theArguments.front()); + + if(!aShapeAttrSelection.get()) { + theError = "Base shape is empty."; + return false; + } + + ResultPtr aBaseContext = aShapeAttrSelection->context(); + + GeomShapePtr aBaseShape = aShapeAttrSelection->value(); + if(!aBaseShape.get()) { + theError = "Base shape is empty."; + return false; + } + + // If selected shape is wire allow to select only vertices. If face - allow vertices and edges. + std::set anAllowedTypes; + switch(aBaseShape->shapeType()) { + case GeomAPI_Shape::FACE: anAllowedTypes.insert(GeomAPI_Shape::EDGE); + case GeomAPI_Shape::WIRE: anAllowedTypes.insert(GeomAPI_Shape::VERTEX); + default: break; + } + + // Check selected shapes. + GeomValidators_FeatureKind aFeatureKindValidator; + std::list anArguments; + anArguments.push_back(theArguments.back()); + for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) { + AttributeSelectionPtr aSelectionAttrInList = aSelectionList->value(anIndex); + if(!aSelectionAttrInList.get()) { + theError = "Empty attribute in list."; + return false; + } + // If context not same check that it is a selection on Sketch. + if(aBaseContext != aSelectionAttrInList->context()) { + if(!aFeatureKindValidator.isValid(aSelectionAttrInList, anArguments, theError)) { + return false; + } + } + + // Check shape type. + GeomShapePtr aShapeInList = aSelectionAttrInList->value(); + if(!aShapeInList.get()) { + aShapeInList = aSelectionAttrInList->context()->shape(); + } + if(anAllowedTypes.find(aShapeInList->shapeType()) == anAllowedTypes.cend()) { + theError = "Selected shape has unacceptable type."; + return false; + } + + // Check that shape inside wire or face. + if(!GeomAlgoAPI_ShapeTools::isSubShapeInShape(aShapeInList, aBaseShape)) { + theError = "Selected shape is not inside base face."; + return false; + } + } + + return true; +} diff --git a/src/BuildPlugin/BuildPlugin_Validators.h b/src/BuildPlugin/BuildPlugin_Validators.h index 1f2091efe..2bd253f9d 100644 --- a/src/BuildPlugin/BuildPlugin_Validators.h +++ b/src/BuildPlugin/BuildPlugin_Validators.h @@ -64,4 +64,19 @@ public: virtual bool isNotObligatory(std::string theFeature, std::string theAttribute); }; +/// \class BuildPlugin_ValidatorSubShapesSelection +/// \ingroup Validators +/// \brief A validator for selection sub-shapes for SubShape feature. +class BuildPlugin_ValidatorSubShapesSelection: public ModelAPI_AttributeValidator +{ +public: + //! Returns true if attribute is ok. + //! \param[in] theAttribute the checked attribute. + //! \param[in] theArguments arguments of the attribute. + //! \param[out] theError error message. + virtual bool isValid(const AttributePtr& theAttribute, + const std::list& theArguments, + std::string& theError) const; +}; + #endif diff --git a/src/BuildPlugin/CMakeLists.txt b/src/BuildPlugin/CMakeLists.txt index 0a7cda8f9..8c3b62d88 100644 --- a/src/BuildPlugin/CMakeLists.txt +++ b/src/BuildPlugin/CMakeLists.txt @@ -19,6 +19,7 @@ SET(PROJECT_HEADERS BuildPlugin_Wire.h BuildPlugin_Face.h BuildPlugin_Shell.h + BuildPlugin_SubShapes.h BuildPlugin_Validators.h ) @@ -29,6 +30,7 @@ SET(PROJECT_SOURCES BuildPlugin_Wire.cpp BuildPlugin_Face.cpp BuildPlugin_Shell.cpp + BuildPlugin_SubShapes.cpp BuildPlugin_Validators.cpp ) @@ -39,6 +41,7 @@ SET(XML_RESOURCES wire_widget.xml face_widget.xml shell_widget.xml + subshapes_widget.xml ) SET(PROJECT_LIBRARIES diff --git a/src/BuildPlugin/edge_widget.xml b/src/BuildPlugin/edge_widget.xml index bacb83e55..6890eae4d 100644 --- a/src/BuildPlugin/edge_widget.xml +++ b/src/BuildPlugin/edge_widget.xml @@ -4,7 +4,8 @@ + type_choice="edges objects" + concealment="true"> diff --git a/src/BuildPlugin/face_widget.xml b/src/BuildPlugin/face_widget.xml index a019054bd..49ea6b4cc 100644 --- a/src/BuildPlugin/face_widget.xml +++ b/src/BuildPlugin/face_widget.xml @@ -4,7 +4,8 @@ + type_choice="edges objects" + concealment="true"> diff --git a/src/BuildPlugin/plugin-Build.xml b/src/BuildPlugin/plugin-Build.xml index 362eb118f..f66be99e8 100644 --- a/src/BuildPlugin/plugin-Build.xml +++ b/src/BuildPlugin/plugin-Build.xml @@ -2,7 +2,7 @@ - + @@ -19,5 +19,10 @@ + + + + + diff --git a/src/BuildPlugin/shell_widget.xml b/src/BuildPlugin/shell_widget.xml index 00defb939..45e2a716e 100644 --- a/src/BuildPlugin/shell_widget.xml +++ b/src/BuildPlugin/shell_widget.xml @@ -4,7 +4,8 @@ + type_choice="objects" + concealment="true"> diff --git a/src/BuildPlugin/subshapes_widget.xml b/src/BuildPlugin/subshapes_widget.xml new file mode 100644 index 000000000..767d01595 --- /dev/null +++ b/src/BuildPlugin/subshapes_widget.xml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/src/BuildPlugin/vertex_widget.xml b/src/BuildPlugin/vertex_widget.xml index cbf5ae8e4..372da411c 100644 --- a/src/BuildPlugin/vertex_widget.xml +++ b/src/BuildPlugin/vertex_widget.xml @@ -4,7 +4,8 @@ + type_choice="vertices objects" + concealment="true"> diff --git a/src/BuildPlugin/wire_widget.xml b/src/BuildPlugin/wire_widget.xml index cae74e9a3..e2c99d561 100644 --- a/src/BuildPlugin/wire_widget.xml +++ b/src/BuildPlugin/wire_widget.xml @@ -4,7 +4,8 @@ + type_choice="edges objects" + concealment="true"> impl(); + if(MY_MAP->IsBound(aKey)) { + MY_MAP->ChangeFind(aKey).Clear(); + } for(ListOfShape::const_iterator anIt = theItems.cbegin(); anIt != theItems.cend(); anIt++) { const TopoDS_Shape& anItem = (*anIt)->impl(); if(MY_MAP->IsBound(aKey)) { @@ -85,6 +88,12 @@ bool GeomAPI_DataMapOfShapeMapOfShapes::unBind(const std::shared_ptrUnBind(aKey) == Standard_True; } +//================================================================================================= +void GeomAPI_DataMapOfShapeMapOfShapes::clear() +{ + return MY_MAP->Clear(); +} + //================================================================================================= int GeomAPI_DataMapOfShapeMapOfShapes::size() const { diff --git a/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h b/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h index 5dd4dbd4d..1d2c55911 100644 --- a/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h +++ b/src/GeomAPI/GeomAPI_DataMapOfShapeMapOfShapes.h @@ -7,33 +7,30 @@ #ifndef GeomAPI_DataMapOfShapeMapOfShapes_H_ #define GeomAPI_DataMapOfShapeMapOfShapes_H_ -#include +#include "GeomAPI_Interface.h" -#include +#include "GeomAPI_Shape.h" -/**\class GeomAPI_DataMapOfShapeMapOfShapes - * \ingroup DataModel - * \brief DataMap of Shape - Map of Shapes defined by TopoDS_Shapes - */ +/// \class GeomAPI_DataMapOfShapeMapOfShapes +/// \ingroup DataModel +/// \brief DataMap of Shape - Map of Shapes defined by TopoDS_Shapes class GeomAPI_DataMapOfShapeMapOfShapes : public GeomAPI_Interface { public: /// Constructor.Creates empty map. GEOMAPI_EXPORT GeomAPI_DataMapOfShapeMapOfShapes(); - /** \brief Binds list of shapes to the key shape. - \param[in] theKey key shape. - \param[in] theItems list of shapes. If shapes have duplications in list only one will be stored. - \returns true if items bound successfully. - */ + /// \brief Binds list of shapes to the key shape. + /// \param[in] theKey key shape. + /// \param[in] theItems list of shapes. If shapes have duplications in list only one will be stored. + /// \returns true if items bound successfully. GEOMAPI_EXPORT bool bind(const std::shared_ptr theKey, const ListOfShape& theItems); - /** \brief Adds item to the map bounded to the key. - \param[in] theKey key shape. - \param[in] theItem item shape. - \returns true if item bounded successfully. False if it is already bound. - */ + /// \brief Adds item to the map bounded to the key. + /// \param[in] theKey key shape. + /// \param[in] theItem item shape. + /// \returns true if item bounded successfully. False if it is already bound. GEOMAPI_EXPORT bool add(const std::shared_ptr theKey, const std::shared_ptr theItem); @@ -47,6 +44,9 @@ public: /// Undinds shapes from theKey. GEOMAPI_EXPORT bool unBind(const std::shared_ptr theKey); + /// Clears map. + GEOMAPI_EXPORT void clear(); + /// \return size of map. GEOMAPI_EXPORT int size() const; }; diff --git a/src/GeomAPI/GeomAPI_Edge.cpp b/src/GeomAPI/GeomAPI_Edge.cpp index 63761a031..594829f8c 100644 --- a/src/GeomAPI/GeomAPI_Edge.cpp +++ b/src/GeomAPI/GeomAPI_Edge.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -23,8 +24,13 @@ #include GeomAPI_Edge::GeomAPI_Edge() - : GeomAPI_Shape() { + TopoDS_Edge* anEdge = new TopoDS_Edge; + + BRep_Builder aBuilder; + aBuilder.MakeEdge(*anEdge); + + setImpl(anEdge); } GeomAPI_Edge::GeomAPI_Edge(const std::shared_ptr& theShape) diff --git a/src/GeomAPI/GeomAPI_Edge.h b/src/GeomAPI/GeomAPI_Edge.h index d0d5ca2e8..e4dfcf2a8 100644 --- a/src/GeomAPI/GeomAPI_Edge.h +++ b/src/GeomAPI/GeomAPI_Edge.h @@ -22,7 +22,7 @@ class GeomAPI_Lin; class GeomAPI_Edge : public GeomAPI_Shape { public: - /// Creation of empty (null) shape + /// Makes an undefined Edge (no geometry). GEOMAPI_EXPORT GeomAPI_Edge(); diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index 3b85b2dcf..0ee2a087c 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -36,6 +36,13 @@ GeomAPI_Shape::GeomAPI_Shape() { } +std::shared_ptr GeomAPI_Shape::emptyCopied() const +{ + GeomShapePtr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(MY_SHAPE->EmptyCopied())); + return aShape; +} + bool GeomAPI_Shape::isNull() const { return MY_SHAPE->IsNull() == Standard_True; @@ -314,6 +321,31 @@ std::string GeomAPI_Shape::shapeTypeStr() const return aShapeTypeStr; } +GeomAPI_Shape::Orientation GeomAPI_Shape::orientation() const +{ + TopAbs_Orientation anOrientation = MY_SHAPE->Orientation(); + + switch(anOrientation) { + case TopAbs_FORWARD: return FORWARD; + case TopAbs_REVERSED: return REVERSED; + case TopAbs_INTERNAL: return INTERNAL; + case TopAbs_EXTERNAL: return EXTERNAL; + default: return FORWARD; + } +} + +void GeomAPI_Shape::setOrientation(const GeomAPI_Shape::Orientation theOrientation) +{ + TopAbs_Orientation anOrientation = MY_SHAPE->Orientation(); + + switch(theOrientation) { + case FORWARD: MY_SHAPE->Orientation(TopAbs_FORWARD); break; + case REVERSED: MY_SHAPE->Orientation(TopAbs_REVERSED); break; + case INTERNAL: MY_SHAPE->Orientation(TopAbs_INTERNAL); break; + case EXTERNAL: MY_SHAPE->Orientation(TopAbs_EXTERNAL); break; + } +} + bool GeomAPI_Shape::isSubShape(const std::shared_ptr theShape) const { if(!theShape.get()) { diff --git a/src/GeomAPI/GeomAPI_Shape.h b/src/GeomAPI/GeomAPI_Shape.h index 098245119..9d2b8b278 100644 --- a/src/GeomAPI/GeomAPI_Shape.h +++ b/src/GeomAPI/GeomAPI_Shape.h @@ -25,11 +25,23 @@ public: SHAPE }; + /// Shape orientation + enum Orientation { + FORWARD, + REVERSED, + INTERNAL, + EXTERNAL + }; + public: /// Creation of empty (null) shape GEOMAPI_EXPORT GeomAPI_Shape(); + /// \return a new Shape with the same Orientation and Location and a new TShape with the same + /// geometry and no sub-shapes. + GEOMAPI_EXPORT std::shared_ptr emptyCopied() const; + /// Returns true if the underlied shape is null GEOMAPI_EXPORT bool isNull() const; @@ -82,11 +94,16 @@ public: GEOMAPI_EXPORT virtual std::string shapeTypeStr() const; + /// \return the shape orientation. + GEOMAPI_EXPORT virtual Orientation orientation() const; + + /// Sets the shape orientation. + GEOMAPI_EXPORT virtual void setOrientation(const Orientation theOrientation); + /// \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/GeomAPI/GeomAPI_ShapeIterator.cpp b/src/GeomAPI/GeomAPI_ShapeIterator.cpp new file mode 100644 index 000000000..6b63f2049 --- /dev/null +++ b/src/GeomAPI/GeomAPI_ShapeIterator.cpp @@ -0,0 +1,62 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_ShapeIterator.cpp +// Created: 27 April 2016 +// Author: Dmitry Bobylev + +#include "GeomAPI_ShapeIterator.h" + +#include +#include + +#define MY_ITERATOR implPtr() + +//================================================================================================== +GeomAPI_ShapeIterator::GeomAPI_ShapeIterator() +: GeomAPI_Interface(new TopoDS_Iterator()) +{ +} + +//================================================================================================== +GeomAPI_ShapeIterator::GeomAPI_ShapeIterator(const std::shared_ptr theShape) +: GeomAPI_Interface(new TopoDS_Iterator()) +{ + init(theShape); +} + +//================================================================================================== +void GeomAPI_ShapeIterator::init(const std::shared_ptr theShape) +{ + if(!theShape.get()) { + return; + } + MY_ITERATOR->Initialize(theShape->impl()); +} + +//================================================================================================== +bool GeomAPI_ShapeIterator::more() const +{ + return MY_ITERATOR->More() == Standard_True; +} + +//================================================================================================== +void GeomAPI_ShapeIterator::next() +{ + try { + MY_ITERATOR->Next(); + } catch (Standard_NoMoreObject) { + } +} + +//================================================================================================== +std::shared_ptr GeomAPI_ShapeIterator::current() +{ + try { + const TopoDS_Shape& aShape = MY_ITERATOR->Value(); + std::shared_ptr aGeomShape(new GeomAPI_Shape()); + aGeomShape->setImpl(new TopoDS_Shape(aShape)); + return aGeomShape; + } catch (Standard_NoMoreObject) { + return std::shared_ptr(); + } +} diff --git a/src/GeomAPI/GeomAPI_ShapeIterator.h b/src/GeomAPI/GeomAPI_ShapeIterator.h new file mode 100644 index 000000000..098f1710e --- /dev/null +++ b/src/GeomAPI/GeomAPI_ShapeIterator.h @@ -0,0 +1,42 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_ShapeIterator.h +// Created: 27 April 2016 +// Author: Dmitry Bobylev + +#ifndef GeomAPI_ShapeIterator_H_ +#define GeomAPI_ShapeIterator_H_ + +#include "GeomAPI.h" +#include "GeomAPI_Shape.h" + +/// \class GeomAPI_ShapeIterator +/// \ingroup DataModel +/// \brief Iterates on the underlying shape underlying a given GeomAPI_Shape object, providing access +/// to its component sub-shapes. Each component shape is returned as a GeomAPI_Shape with +/// an orientation, and a compound of the original values and the relative values. +class GeomAPI_ShapeIterator : public GeomAPI_Interface +{ +public: + /// Default constructor. Creates an empty iterator, becomes usefull after Init. + GEOMAPI_EXPORT GeomAPI_ShapeIterator(); + + /// \brief Creates an iterator on theShape sub-shapes. + /// \param[in] theShape shape to iterate. + GEOMAPI_EXPORT GeomAPI_ShapeIterator(const std::shared_ptr theShape); + + /// \brief Initializes this iterator with theShape. + /// \param[in] theShape shape to iterate. + GEOMAPI_EXPORT void init(const std::shared_ptr theShape); + + /// \return true if there is another sub-shape in the shape which this iterator is scanning. + GEOMAPI_EXPORT bool more() const; + + /// Moves on to the next sub-shape in the shape which this iterator is scanning. + GEOMAPI_EXPORT void next(); + + /// \return the current sub-shape in the shape which this iterator is scanning. + GEOMAPI_EXPORT std::shared_ptr current(); +}; + +#endif \ No newline at end of file diff --git a/src/GeomAPI/GeomAPI_Wire.cpp b/src/GeomAPI/GeomAPI_Wire.cpp new file mode 100644 index 000000000..e5eb9d410 --- /dev/null +++ b/src/GeomAPI/GeomAPI_Wire.cpp @@ -0,0 +1,21 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_Wire.cpp +// Created: 28 April 2016 +// Author: Dmitry Bobylev + +#include "GeomAPI_Wire.h" + +#include +#include + +//================================================================================================== +GeomAPI_Wire::GeomAPI_Wire() +{ + TopoDS_Wire* aWire = new TopoDS_Wire(); + + BRep_Builder aBuilder; + aBuilder.MakeWire(*aWire); + + this->setImpl(aWire); +} diff --git a/src/GeomAPI/GeomAPI_Wire.h b/src/GeomAPI/GeomAPI_Wire.h new file mode 100644 index 000000000..2c1160857 --- /dev/null +++ b/src/GeomAPI/GeomAPI_Wire.h @@ -0,0 +1,23 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAPI_Wire.h +// Created: 28 April 2016 +// Author: Dmitry Bobylev + +#ifndef GeomAPI_Wire_H_ +#define GeomAPI_Wire_H_ + +#include "GeomAPI_Shape.h" + +/// \class GeomAPI_Wire +/// \ingroup DataModel +/// \brief Interface to the wire object +class GeomAPI_Wire: public GeomAPI_Shape +{ +public: + /// Makes an undefined Wire. + GEOMAPI_EXPORT GeomAPI_Wire(); +}; + +#endif + diff --git a/src/GeomAPI/GeomAPI_swig.h b/src/GeomAPI/GeomAPI_swig.h index 0dd57e6cd..2c8e0e449 100644 --- a/src/GeomAPI/GeomAPI_swig.h +++ b/src/GeomAPI/GeomAPI_swig.h @@ -32,10 +32,12 @@ #include "GeomAPI_Pnt2d.h" #include "GeomAPI_Shape.h" #include "GeomAPI_ShapeExplorer.h" + #include "GeomAPI_ShapeIterator.h" #include "GeomAPI_Vertex.h" #include "GeomAPI_XY.h" #include "GeomAPI_XYZ.h" #include "GeomAPI_Trsf.h" + #include "GeomAPI_Wire.h" #include #include diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index e765913a8..bdc7a8d58 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -38,6 +38,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_Pipe.h GeomAlgoAPI_WireBuilder.h GeomAlgoAPI_Sewing.h + GeomAlgoAPI_ShapeBuilder.h ) SET(PROJECT_SOURCES @@ -72,6 +73,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_Pipe.cpp GeomAlgoAPI_WireBuilder.cpp GeomAlgoAPI_Sewing.cpp + GeomAlgoAPI_ShapeBuilder.cpp ) SET(PROJECT_LIBRARIES diff --git a/src/GeomAlgoAPI/GeomAlgoAPI.i b/src/GeomAlgoAPI/GeomAlgoAPI.i index e4efaa2ba..cd79ade66 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI.i +++ b/src/GeomAlgoAPI/GeomAlgoAPI.i @@ -44,6 +44,7 @@ %include "GeomAlgoAPI_Pipe.h" %include "GeomAlgoAPI_WireBuilder.h" %include "GeomAlgoAPI_Sewing.h" +%include "GeomAlgoAPI_ShapeBuilder.h" %typemap(out) std::list< std::shared_ptr< GeomAPI_Shape > >::value_type & { $result = SWIG_NewPointerObj(SWIG_as_voidptr(new std::shared_ptr(*$1)), $descriptor(std::shared_ptr *), SWIG_POINTER_OWN | 0 ); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp index e7d5165ce..2397dafbf 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_MakeShape.cpp @@ -91,7 +91,10 @@ void GeomAlgoAPI_MakeShape::modified(const std::shared_ptr theSha TopTools_ListOfShape aList; if(myBuilderType == OCCT_BRepBuilderAPI_MakeShape) { BRepBuilderAPI_MakeShape* aMakeShape = implPtr(); - aList = aMakeShape->Modified(theShape->impl()); + try { + aList = aMakeShape->Modified(theShape->impl()); + } catch(Standard_NoSuchObject) { + } } else if(myBuilderType == OCCT_BOPAlgo_Builder) { BOPAlgo_Builder* aBOPBuilder = implPtr(); aList = aBOPBuilder->Modified(theShape->impl()); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp new file mode 100644 index 000000000..eea9ae912 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.cpp @@ -0,0 +1,175 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_ShapeBuilder.cpp +// Created: 27 April 2016 +// Author: Dmitry Bobylev + +#include "GeomAlgoAPI_ShapeBuilder.h" + +#include "GeomAlgoAPI_MakeShapeCustom.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//================================================================================================== +void GeomAlgoAPI_ShapeBuilder::add(std::shared_ptr theShape, + const std::shared_ptr theShapeToAdd) +{ + if(!theShape.get() || !theShapeToAdd.get()) { + return; + } + + TopoDS_Shape* aShape = theShape->implPtr(); + const TopoDS_Shape& aShapeToAdd = theShapeToAdd->impl(); + + BRep_Builder aBuilder; + aBuilder.Add(*aShape, aShapeToAdd); +} + + +//================================================================================================== +void GeomAlgoAPI_ShapeBuilder::remove(std::shared_ptr theShape, + const std::shared_ptr theShapeToRemove) +{ + if(!theShape.get() || !theShapeToRemove.get()) { + return; + } + + TopoDS_Shape* aShape = theShape->implPtr(); + const TopoDS_Shape& aShapeToRemove = theShapeToRemove->impl(); + + BRep_Builder aBuilder; + aBuilder.Remove(*aShape, aShapeToRemove); +} + +//================================================================================================== +GeomAlgoAPI_ShapeBuilder::GeomAlgoAPI_ShapeBuilder() +{ +} + +//================================================================================================== +void GeomAlgoAPI_ShapeBuilder::removeInternal(const std::shared_ptr theShape) +{ + GeomShapePtr aResultShape = theShape->emptyCopied(); + GeomAPI_Shape::ShapeType aBaseShapeType = theShape->shapeType(); + std::shared_ptr aMakeShapeCustom(new GeomAlgoAPI_MakeShapeCustom()); + for(GeomAPI_ShapeIterator anIter(theShape); anIter.more(); anIter.next()) { + GeomShapePtr aSubShape = anIter.current(); + if(aBaseShapeType == GeomAPI_Shape::WIRE) { + GeomShapePtr aSubShapeCopy = aSubShape->emptyCopied(); + aMakeShapeCustom->addModified(aSubShape, aSubShapeCopy); + for(GeomAPI_ShapeIterator aSubIter(aSubShape); aSubIter.more(); aSubIter.next()) { + GeomShapePtr aSubOfSubShape = aSubIter.current(); + if(aSubOfSubShape->orientation() != GeomAPI_Shape::INTERNAL) { + GeomAlgoAPI_ShapeBuilder::add(aSubShapeCopy, aSubOfSubShape); + } + } + GeomAlgoAPI_ShapeBuilder::add(aResultShape, aSubShapeCopy); + } else if(aBaseShapeType == GeomAPI_Shape::FACE) { + if(aSubShape->shapeType() == GeomAPI_Shape::WIRE + && aSubShape->orientation() != GeomAPI_Shape::INTERNAL) { + GeomAlgoAPI_ShapeBuilder::add(aResultShape, aSubShape); + } + } + } + + this->appendAlgo(aMakeShapeCustom); + + setShape(aResultShape); + setDone(true); +} + +//================================================================================================== +void GeomAlgoAPI_ShapeBuilder::add(const std::shared_ptr theShape, + const ListOfShape& theShapesToAdd) +{ + // Get base shape. + if(!theShape.get()) { + return; + } + const TopoDS_Shape& aBaseShape = theShape->impl(); + TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType(); + + // Copy base shape. + BRepBuilderAPI_Copy* aCopyBuilder = new BRepBuilderAPI_Copy(aBaseShape, Standard_False); + this->appendAlgo(std::shared_ptr(new GeomAlgoAPI_MakeShape(aCopyBuilder))); + if(!aCopyBuilder->IsDone()) { + return; + } + TopoDS_Shape aResultShape = aCopyBuilder->Shape(); + + // Copy sub-shapes from list to new shape. + BRep_Builder aBuilder; + std::shared_ptr aMakeShapeCustom(new GeomAlgoAPI_MakeShapeCustom()); + for(ListOfShape::const_iterator anIt = theShapesToAdd.cbegin(); anIt != theShapesToAdd.cend(); ++anIt) { + TopoDS_Shape aShapeToAdd = (*anIt)->impl(); + for(TopExp_Explorer aResExp(aResultShape, TopAbs_VERTEX); aResExp.More(); aResExp.Next()) { + const TopoDS_Vertex& aVertexInRes = TopoDS::Vertex(aResExp.Current()); + const gp_Pnt aPntInRes = BRep_Tool::Pnt(aVertexInRes); + for(TopExp_Explorer anAddExp(aShapeToAdd, TopAbs_VERTEX); anAddExp.More(); anAddExp.Next()) { + const TopoDS_Vertex& aVertexInAdd = TopoDS::Vertex(anAddExp.Current()); + const gp_Pnt aPntInAdd = BRep_Tool::Pnt(aVertexInAdd); + if(aPntInRes.Distance(aPntInAdd) < Precision::Confusion()) { + BRepTools_ReShape aReShape; + TopoDS_Shape aVertexInResMod = aVertexInRes; + aVertexInResMod.Orientation(aVertexInAdd.Orientation()); + aReShape.Replace(aVertexInAdd, aVertexInResMod); + TopoDS_Shape aModShape = aReShape.Apply(aShapeToAdd); + + GeomShapePtr aGeomBaseShape(new GeomAPI_Shape()); + GeomShapePtr aGeomModShape(new GeomAPI_Shape()); + aGeomBaseShape->setImpl(new TopoDS_Shape(aShapeToAdd)); + aGeomModShape->setImpl(new TopoDS_Shape(aModShape)); + aMakeShapeCustom->addModified(aGeomBaseShape, aGeomModShape); + aShapeToAdd = aModShape; + } + } + } + TopAbs_ShapeEnum aShapeToAddType = aShapeToAdd.ShapeType(); + if(aBaseShapeType == TopAbs_WIRE) { + if(aShapeToAddType == TopAbs_VERTEX) { + // Find on which edge vertex is lie and add to this edge. + for(TopExp_Explorer aResultExp(aResultShape, TopAbs_EDGE); aResultExp.More(); aResultExp.Next()) { + TopoDS_Shape anEdge = aResultExp.Current(); + BRepExtrema_DistShapeShape aDist(anEdge, aShapeToAdd); + aDist.Perform(); + if(aDist.IsDone() && aDist.Value() <= Precision::Confusion()) { + aShapeToAdd.Orientation(TopAbs_INTERNAL); + Standard_Boolean aFreeFlag = anEdge.Free(); + anEdge.Free(Standard_True); + aBuilder.Add(anEdge, aShapeToAdd); + anEdge.Free(aFreeFlag); + break; + } + } + } + } else if(aBaseShapeType == GeomAPI_Shape::FACE) { + if(aShapeToAddType == GeomAPI_Shape::EDGE) { + aShapeToAdd.Orientation(TopAbs_INTERNAL); + TopoDS_Wire aWire; + aBuilder.MakeWire(aWire); + aBuilder.Add(aWire, aShapeToAdd); + aShapeToAdd = aWire; + aShapeToAdd.Orientation(TopAbs_INTERNAL); + } + aBuilder.Add(aResultShape, aShapeToAdd); + } + } + this->appendAlgo(aMakeShapeCustom); + + // Set result. + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResultShape)); + setShape(aShape); + setDone(true); +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h new file mode 100644 index 000000000..55ecaa3c5 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeBuilder.h @@ -0,0 +1,47 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_ShapeBuilder.h +// Created: 27 April 2016 +// Author: Dmitry Bobylev + +#ifndef GeomAlgoAPI_ShapeBuilder_H_ +#define GeomAlgoAPI_ShapeBuilder_H_ + +#include "GeomAlgoAPI.h" +#include "GeomAlgoAPI_MakeShapeList.h" + +#include + +/// \class GeomAlgoAPI_ShapeBuilder +/// \ingroup DataAlgo +/// \brief Allows to add or remove subshapes from a shape. +class GeomAlgoAPI_ShapeBuilder: public GeomAlgoAPI_MakeShapeList +{ + public: + /// \brief Adds theShapeToAdd in theShape. + /// \param[in] theShape shape to modify. + /// \param[in] theShapeToAdd shape which will be added. + GEOMALGOAPI_EXPORT static void add(std::shared_ptr theShape, + const std::shared_ptr theShapeToAdd); + + /// \brief Removes theShapeToRemove in theShape. + /// \param[in] theShape shape to modify. + /// \param[in] theShapeToRemove shape which will be removed. + GEOMALGOAPI_EXPORT static void remove(std::shared_ptr theShape, + const std::shared_ptr theShapeToRemove); + + /// Creates empty builder. + GEOMALGOAPI_EXPORT GeomAlgoAPI_ShapeBuilder(); + + /// \brief Store new shape as result of removing internal shapes from theShape. + /// \param[in] theShape base shape. + GEOMALGOAPI_EXPORT void removeInternal(const std::shared_ptr theShape); + + /// \brief Store new shape as result of adding theShapesToAdd to theShape. + /// \param[in] theShape base shape. + /// \param[in] theShapesToAdd shapes which will be added. + GEOMALGOAPI_EXPORT void add(const std::shared_ptr theShape, + const ListOfShape& theShapesToAdd); +}; + +#endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp index 47d05e566..4ce4640ef 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp @@ -16,21 +16,30 @@ #include #include #include +#include #include #include #include +#include #include +#include #include +#include +#include +#include +#include #include #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -398,3 +407,74 @@ std::shared_ptr GeomAlgoAPI_ShapeTools::findPlane(const ListOfShape return aPln; } + +//================================================================================================= +bool GeomAlgoAPI_ShapeTools::isSubShapeInShape(const std::shared_ptr theSubShape, + const std::shared_ptr theBaseShape) +{ + if(!theSubShape.get() || !theBaseShape.get()) { + return false; + } + + const TopoDS_Shape& aSubShape = theSubShape->impl(); + const TopoDS_Shape& aBaseShape = theBaseShape->impl(); + + if(aSubShape.ShapeType() == TopAbs_VERTEX) { + // If sub-shape is a vertex check distance to shape. If it is <= Precision::Confusion() then OK. + BRepExtrema_DistShapeShape aDist(aBaseShape, aSubShape); + aDist.Perform(); + if(!aDist.IsDone() || aDist.Value() > Precision::Confusion()) { + return false; + } + } else if (aSubShape.ShapeType() == TopAbs_EDGE) { + if(aBaseShape.ShapeType() == TopAbs_FACE) { + // Check that edge is on face surface. + TopoDS_Face aFace = TopoDS::Face(aBaseShape); + TopoDS_Edge anEdge = TopoDS::Edge(aSubShape); + BRepLib_CheckCurveOnSurface aCheck(anEdge, aFace); + aCheck.Perform(); + if(!aCheck.IsDone() || aCheck.MaxDistance() > Precision::Confusion()) { + return false; + } + + // Check intersections. + TopoDS_Vertex aV1, aV2; + ShapeAnalysis::FindBounds(anEdge, aV1, aV2); + gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1); + gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2); + for(TopExp_Explorer anExp(aBaseShape, TopAbs_EDGE); anExp.More(); anExp.Next()) { + const TopoDS_Shape& anEdgeOnFace = anExp.Current(); + BRepExtrema_DistShapeShape aDist(anEdgeOnFace, anEdge); + aDist.Perform(); + if(aDist.IsDone() && aDist.Value() <= Precision::Confusion()) { + // Edge intersect face bound. Check that it is not on edge begin or end. + for(Standard_Integer anIndex = 1; anIndex <= aDist.NbSolution(); ++anIndex) { + gp_Pnt aPntOnSubShape = aDist.PointOnShape2(anIndex); + if(aPntOnSubShape.Distance(aPnt1) > Precision::Confusion() + && aPntOnSubShape.Distance(aPnt2) > Precision::Confusion()) { + return false; + } + } + } + } + + // No intersections found. Edge is inside or outside face. Check it. + BRepAdaptor_Curve aCurveAdaptor(anEdge); + gp_Pnt aPointToCheck = aCurveAdaptor.Value((aCurveAdaptor.FirstParameter() + aCurveAdaptor.LastParameter()) / 2.0); + Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace); + ShapeAnalysis_Surface aSAS(aSurface); + gp_Pnt2d aPointOnFace = aSAS.ValueOfUV(aPointToCheck, Precision::Confusion()); + BRepTopAdaptor_FClass2d aFClass2d(aFace, Precision::Confusion()); + if(aFClass2d.Perform(aPointOnFace) == TopAbs_OUT) { + return false; + } + + } else { + return false; + } + } else { + return false; + } + + return true; +} diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h index 07d6704ab..3fdee67c5 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.h @@ -78,6 +78,13 @@ public: /// \param[in] theShapes shapes to find plane. /// \return plane where all shapes lie or empty ptr if they not planar. static std::shared_ptr findPlane(const ListOfShape& theShapes); + + /// \brief Checks that vertex/edge is inside face or vertext inside wire. + /// \param[in] theSubShape shape that should be inside. + /// \param[in] theBaseShape base shape. + /// \return true if edge inside the face. + static bool isSubShapeInShape(const std::shared_ptr theSubShape, + const std::shared_ptr theBaseShape); }; #endif diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h index 3cf49122d..2eb6c3f91 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h @@ -38,7 +38,8 @@ #include "GeomAlgoAPI_Pipe.h" #include "GeomAlgoAPI_WireBuilder.h" #include "GeomAlgoAPI_Sewing.h" - + #include "GeomAlgoAPI_ShapeBuilder.h" + #include #include #include -- 2.39.2