From d0dbe40e44426cbcf24cce1e09a2e860f59b126f Mon Sep 17 00:00:00 2001 From: Clarisse Genrault Date: Wed, 4 Jan 2017 12:26:57 +0100 Subject: [PATCH] Adding the "Symmetry" feature. --- src/FeaturesAPI/CMakeLists.txt | 5 +- src/FeaturesAPI/FeaturesAPI.i | 2 + src/FeaturesAPI/FeaturesAPI_Symmetry.cpp | 119 ++++++ src/FeaturesAPI/FeaturesAPI_Symmetry.h | 84 ++++ src/FeaturesAPI/FeaturesAPI_swig.h | 1 + src/FeaturesAPI/Test/APIParam_Symmetry.py | 47 +++ src/FeaturesPlugin/CMakeLists.txt | 3 + src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp | 3 + .../FeaturesPlugin_Symmetry.cpp | 360 ++++++++++++++++++ src/FeaturesPlugin/FeaturesPlugin_Symmetry.h | 117 ++++++ src/FeaturesPlugin/icons/point.png | Bin 0 -> 486 bytes src/FeaturesPlugin/icons/symmetry.png | Bin 0 -> 429 bytes .../icons/symmetry_axis_32x32.png | Bin 0 -> 586 bytes .../icons/symmetry_plane_32x32.png | Bin 0 -> 727 bytes .../icons/symmetry_point_32x32.png | Bin 0 -> 434 bytes src/FeaturesPlugin/plugin-Features.xml | 3 + src/FeaturesPlugin/symmetry_widget.xml | 60 +++ src/GeomAPI/GeomAPI_Trsf.cpp | 22 +- src/GeomAPI/GeomAPI_Trsf.h | 16 + src/GeomAlgoAPI/CMakeLists.txt | 3 + src/GeomAlgoAPI/GeomAlgoAPI.i | 2 + src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp | 72 +++- src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.h | 16 + src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.cpp | 137 +++++++ src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.h | 66 ++++ src/GeomAlgoAPI/GeomAlgoAPI_swig.h | 1 + src/GeomAlgoAPI/Test/TestAPI_Symmetry.py | 48 +++ src/PythonAPI/model/features/__init__.py | 2 +- 28 files changed, 1181 insertions(+), 8 deletions(-) create mode 100644 src/FeaturesAPI/FeaturesAPI_Symmetry.cpp create mode 100644 src/FeaturesAPI/FeaturesAPI_Symmetry.h create mode 100644 src/FeaturesAPI/Test/APIParam_Symmetry.py create mode 100644 src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp create mode 100644 src/FeaturesPlugin/FeaturesPlugin_Symmetry.h create mode 100755 src/FeaturesPlugin/icons/point.png create mode 100644 src/FeaturesPlugin/icons/symmetry.png create mode 100644 src/FeaturesPlugin/icons/symmetry_axis_32x32.png create mode 100644 src/FeaturesPlugin/icons/symmetry_plane_32x32.png create mode 100644 src/FeaturesPlugin/icons/symmetry_point_32x32.png create mode 100644 src/FeaturesPlugin/symmetry_widget.xml create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.cpp create mode 100644 src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.h create mode 100644 src/GeomAlgoAPI/Test/TestAPI_Symmetry.py diff --git a/src/FeaturesAPI/CMakeLists.txt b/src/FeaturesAPI/CMakeLists.txt index 155141244..e10949900 100644 --- a/src/FeaturesAPI/CMakeLists.txt +++ b/src/FeaturesAPI/CMakeLists.txt @@ -17,6 +17,7 @@ SET(PROJECT_HEADERS FeaturesAPI_Revolution.h FeaturesAPI_RevolutionBoolean.h FeaturesAPI_Rotation.h + FeaturesAPI_Symmetry.h FeaturesAPI_Translation.h FeaturesAPI_Union.h ) @@ -34,6 +35,7 @@ SET(PROJECT_SOURCES FeaturesAPI_Revolution.cpp FeaturesAPI_RevolutionBoolean.cpp FeaturesAPI_Rotation.cpp + FeaturesAPI_Symmetry.cpp FeaturesAPI_Translation.cpp FeaturesAPI_Union.cpp ) @@ -92,4 +94,5 @@ INSTALL(TARGETS _FeaturesAPI DESTINATION ${SHAPER_INSTALL_SWIG}) INSTALL(TARGETS FeaturesAPI DESTINATION ${SHAPER_INSTALL_BIN}) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/FeaturesAPI.py DESTINATION ${SHAPER_INSTALL_SWIG}) -ADD_UNIT_TESTS(APIParam_Translation.py) \ No newline at end of file +ADD_UNIT_TESTS(APIParam_Symmetry.py + APIParam_Translation.py) \ No newline at end of file diff --git a/src/FeaturesAPI/FeaturesAPI.i b/src/FeaturesAPI/FeaturesAPI.i index 7a8a55628..68817ec5f 100644 --- a/src/FeaturesAPI/FeaturesAPI.i +++ b/src/FeaturesAPI/FeaturesAPI.i @@ -35,6 +35,7 @@ %shared_ptr(FeaturesAPI_RevolutionCut) %shared_ptr(FeaturesAPI_RevolutionFuse) %shared_ptr(FeaturesAPI_Rotation) +%shared_ptr(FeaturesAPI_Symmetry) %shared_ptr(FeaturesAPI_Translation) %shared_ptr(FeaturesAPI_Union) @@ -51,5 +52,6 @@ %include "FeaturesAPI_Revolution.h" %include "FeaturesAPI_RevolutionBoolean.h" %include "FeaturesAPI_Rotation.h" +%include "FeaturesAPI_Symmetry.h" %include "FeaturesAPI_Translation.h" %include "FeaturesAPI_Union.h" diff --git a/src/FeaturesAPI/FeaturesAPI_Symmetry.cpp b/src/FeaturesAPI/FeaturesAPI_Symmetry.cpp new file mode 100644 index 000000000..24a41f3f1 --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Symmetry.cpp @@ -0,0 +1,119 @@ +// Copyright (C) 2014-2016 CEA/DEN, EDF R&D --> + +// File: FeaturesAPI_Symmetry.cpp +// Created: 07 Dec 2016 +// Author: Clarisse Genrault (CEA) + +#include "FeaturesAPI_Symmetry.h" + +#include +#include + +//================================================================================================== +FeaturesAPI_Symmetry::FeaturesAPI_Symmetry( + const std::shared_ptr& theFeature) +: ModelHighAPI_Interface(theFeature) +{ + initialize(); +} + +//================================================================================================== +FeaturesAPI_Symmetry::FeaturesAPI_Symmetry(const std::shared_ptr& theFeature, + const std::list& theMainObjects, + const ModelHighAPI_Selection& theObject) +: ModelHighAPI_Interface(theFeature) +{ + if(initialize()) { + fillAttribute(theMainObjects, mymainObjects); + GeomAPI_Shape::ShapeType aType = getShapeType(theObject); + if(aType == GeomAPI_Shape::VERTEX) { + setPoint(theObject); + } else if(aType == GeomAPI_Shape::EDGE) { + setAxis(theObject); + } else if(aType == GeomAPI_Shape::FACE) { + setPlane(theObject); + } + } +} + +//================================================================================================== +FeaturesAPI_Symmetry::~FeaturesAPI_Symmetry() +{ + +} + +//================================================================================================== +void FeaturesAPI_Symmetry::setMainObjects( + const std::list& theMainObjects) +{ + fillAttribute(theMainObjects, mainObjects()); + + execute(); +} + +//================================================================================================== +void FeaturesAPI_Symmetry::setPoint(const ModelHighAPI_Selection& thePointObject) +{ + fillAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD_BY_POINT(), creationMethod()); + fillAttribute(thePointObject, pointObject()); + + execute(); +} + +//================================================================================================== +void FeaturesAPI_Symmetry::setAxis(const ModelHighAPI_Selection& theAxisObject) +{ + fillAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD_BY_AXIS(), creationMethod()); + fillAttribute(theAxisObject, axisObject()); + + execute(); +} + +//================================================================================================== +void FeaturesAPI_Symmetry::setPlane(const ModelHighAPI_Selection& thePlaneObject) +{ + fillAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD_BY_PLANE(), creationMethod()); + fillAttribute(thePlaneObject, planeObject()); + + execute(); +} + +//================================================================================================== +void FeaturesAPI_Symmetry::dump(ModelHighAPI_Dumper& theDumper) const +{ + std::cout << "DUMP SYMMETRY" << std::endl; + FeaturePtr aBase = feature(); + const std::string& aDocName = theDumper.name(aBase->document()); + + AttributeSelectionListPtr anAttrObjects = + aBase->selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID()); + theDumper << aBase << " = model.addSymmetry(" << aDocName << ", " << anAttrObjects; + + std::string aCreationMethod = + aBase->string(FeaturesPlugin_Symmetry::CREATION_METHOD())->value(); + + if (aCreationMethod == FeaturesPlugin_Symmetry::CREATION_METHOD_BY_POINT()) { + AttributeSelectionPtr anAttrPoint = + aBase->selection(FeaturesPlugin_Symmetry::POINT_OBJECT_ID()); + theDumper << ", " << anAttrPoint; + } else if (aCreationMethod == FeaturesPlugin_Symmetry::CREATION_METHOD_BY_AXIS()) { + AttributeSelectionPtr anAttrAxis = + aBase->selection(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID()); + theDumper << ", " << anAttrAxis; + } else if (aCreationMethod == FeaturesPlugin_Symmetry::CREATION_METHOD_BY_PLANE()) { + AttributeSelectionPtr anAttrPlane = + aBase->selection(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID()); + theDumper << ", " << anAttrPlane; + } + + theDumper << ")" << std::endl; +} + +//================================================================================================== +SymmetryPtr addSymmetry(const std::shared_ptr& thePart, + const std::list& theMainObjects, + const ModelHighAPI_Selection& theObject) +{ + std::shared_ptr aFeature = thePart->addFeature(FeaturesAPI_Symmetry::ID()); + return SymmetryPtr(new FeaturesAPI_Symmetry(aFeature, theMainObjects, theObject)); +} diff --git a/src/FeaturesAPI/FeaturesAPI_Symmetry.h b/src/FeaturesAPI/FeaturesAPI_Symmetry.h new file mode 100644 index 000000000..7b0bf31ce --- /dev/null +++ b/src/FeaturesAPI/FeaturesAPI_Symmetry.h @@ -0,0 +1,84 @@ +// Copyright (C) 2014-2016 CEA/DEN, EDF R&D --> + +// File: FeaturesAPI_Symmetry.h +// Created: 07 Dec 2016 +// Author: Clarisse Genrault (CEA) + +#ifndef FEATURESAPI_SYMMETRY_H_ +#define FEATURESAPI_SYMMETRY_H_ + +#include "FeaturesAPI.h" + +#include + +#include +#include + +class ModelHighAPI_Double; +class ModelHighAPI_Dumper; +class ModelHighAPI_Selection; + +/// \class FeaturesAPI_Symmetry +/// \ingroup CPPHighAPI +/// \brief Interface for Symmetry feature. +class FeaturesAPI_Symmetry: public ModelHighAPI_Interface +{ +public: + /// Constructor without values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Symmetry(const std::shared_ptr& theFeature); + + /// Constructor with values. + FEATURESAPI_EXPORT + explicit FeaturesAPI_Symmetry(const std::shared_ptr& theFeature, + const std::list& theMainObjects, + const ModelHighAPI_Selection& theObject); + + /// Destructor. + FEATURESAPI_EXPORT + virtual ~FeaturesAPI_Symmetry(); + + INTERFACE_5(FeaturesPlugin_Symmetry::ID(), + creationMethod, FeaturesPlugin_Symmetry::CREATION_METHOD(), + ModelAPI_AttributeString, /** Creation method */, + mainObjects, FeaturesPlugin_Symmetry::OBJECTS_LIST_ID(), + ModelAPI_AttributeSelectionList, /** Main objects */, + pointObject, FeaturesPlugin_Symmetry::POINT_OBJECT_ID(), + ModelAPI_AttributeSelection, /** Point object */, + axisObject, FeaturesPlugin_Symmetry::AXIS_OBJECT_ID(), + ModelAPI_AttributeSelection, /** Axis object */, + planeObject, FeaturesPlugin_Symmetry::PLANE_OBJECT_ID(), + ModelAPI_AttributeSelection, /** Plane object */) + + /// Set main objects. + FEATURESAPI_EXPORT + void setMainObjects(const std::list& theMainObjects); + + /// Modify CreationMethod, point_object attribute of the feature. + FEATURESAPI_EXPORT + void setPoint(const ModelHighAPI_Selection& thePointObject); + + /// Modify CreationMethod, axis_object attribute of the feature. + FEATURESAPI_EXPORT + void setAxis(const ModelHighAPI_Selection& theAxisObject); + + /// Modify CreationMethod, plane_object attribute of the feature. + FEATURESAPI_EXPORT + void setPlane(const ModelHighAPI_Selection& thePlaneObject); + + /// Dump wrapped feature + FEATURESAPI_EXPORT + virtual void dump(ModelHighAPI_Dumper& theDumper) const; +}; + +/// Pointer on Symmetry object. +typedef std::shared_ptr SymmetryPtr; + +/// \ingroup CPPHighAPI +/// \brief Create Symmetry feature. +FEATURESAPI_EXPORT +SymmetryPtr addSymmetry(const std::shared_ptr& thePart, + const std::list& theMainObjects, + const ModelHighAPI_Selection& theObject); + +#endif // FEATURESAPI_SYMMETRY_H_ diff --git a/src/FeaturesAPI/FeaturesAPI_swig.h b/src/FeaturesAPI/FeaturesAPI_swig.h index 6e25cbad6..cb100d4c4 100644 --- a/src/FeaturesAPI/FeaturesAPI_swig.h +++ b/src/FeaturesAPI/FeaturesAPI_swig.h @@ -22,6 +22,7 @@ #include "FeaturesAPI_Revolution.h" #include "FeaturesAPI_RevolutionBoolean.h" #include "FeaturesAPI_Rotation.h" + #include "FeaturesAPI_Symmetry.h" #include "FeaturesAPI_Translation.h" #include "FeaturesAPI_Union.h" diff --git a/src/FeaturesAPI/Test/APIParam_Symmetry.py b/src/FeaturesAPI/Test/APIParam_Symmetry.py new file mode 100644 index 000000000..0f785465d --- /dev/null +++ b/src/FeaturesAPI/Test/APIParam_Symmetry.py @@ -0,0 +1,47 @@ +""" +Test case for Translation feature. +Written on High API. +""" +from ModelAPI import * +from GeomAPI import * + +import model + +# Get session +aSession = ModelAPI_Session.get() + +# Create a part +aDocument = aSession.activeDocument() +aSession.startOperation() +model.addPart(aDocument) +aDocument = aSession.activeDocument() +aSession.finishOperation() + +# Create a box + +aSession.startOperation() +aBox1 = model.addBox(aDocument, 10, 10, 10) +aBox2 = model.addBox(aDocument, 10, 10, 10) +aBox3 = model.addBox(aDocument, 10, 10, 10) + +# Perform a symmetry by a point +aSession.startOperation() +aPoint = model.addPoint(aDocument, 0, 0, 0).result() +aSymmetry1 = model.addSymmetry(aDocument, [model.selection("SOLID", "Box_1_1")], aPoint).result() +aSession.finishOperation() +assert (aSymmetry1 is not None) + +# Perform a symmetry by an axis +aSession.startOperation() +anAxis = model.addAxis(aDocument, 10, 0, 0).result() +aSymmetry2 = model.addSymmetry(aDocument, [model.selection("SOLID", "Box_2_1")], anAxis).result() +aSession.finishOperation() +assert (aSymmetry2 is not None) + +# Perform a symmetry by a plane +aSession.startOperation() +aPoint1 = model.addPoint(aDocument, 0, 0, 0).result() +aPoint2 = model.addPoint(aDocument, 10, 10, 0).result() +aSymmetry3 = model.addSymmetry(aDocument, [model.selection("SOLID", "Box_3_1")], model.selection("FACE", "Box_3_1/Top")).result() +aSession.finishOperation() +assert (aSymmetry3 is not None) \ No newline at end of file diff --git a/src/FeaturesPlugin/CMakeLists.txt b/src/FeaturesPlugin/CMakeLists.txt index 637f3b578..52b30210d 100644 --- a/src/FeaturesPlugin/CMakeLists.txt +++ b/src/FeaturesPlugin/CMakeLists.txt @@ -29,6 +29,7 @@ SET(PROJECT_HEADERS FeaturesPlugin_Validators.h FeaturesPlugin_RemoveSubShapes.h FeaturesPlugin_Tools.h + FeaturesPlugin_Symmetry.h ) SET(PROJECT_SOURCES @@ -56,6 +57,7 @@ SET(PROJECT_SOURCES FeaturesPlugin_Validators.cpp FeaturesPlugin_RemoveSubShapes.cpp FeaturesPlugin_Tools.cpp + FeaturesPlugin_Symmetry.cpp ) SET(XML_RESOURCES @@ -76,6 +78,7 @@ SET(XML_RESOURCES pipe_widget.xml remove_subshapes_widget.xml union_widget.xml + symmetry_widget.xml ) SET(TEXT_RESOURCES diff --git a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp index a602a866f..89f735cf1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Plugin.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -99,6 +100,8 @@ FeaturePtr FeaturesPlugin_Plugin::createFeature(std::string theFeatureID) return FeaturePtr(new FeaturesPlugin_RemoveSubShapes); } else if (theFeatureID == FeaturesPlugin_Union::ID()) { return FeaturePtr(new FeaturesPlugin_Union); + } else if (theFeatureID == FeaturesPlugin_Symmetry::ID()) { + return FeaturePtr(new FeaturesPlugin_Symmetry); } // feature of such kind is not found diff --git a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp new file mode 100644 index 000000000..e38bff2e8 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp @@ -0,0 +1,360 @@ +// Copyright (C) 2014-2016 CEA/DEN, EDF R&D + +// File: FeaturesPlugin_Symmetry.cpp +// Created: 30 Nov 2016 +// Author: Clarisse Genrault (CEA) + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include + +//================================================================================================= +FeaturesPlugin_Symmetry::FeaturesPlugin_Symmetry() +{ +} + +//================================================================================================= +void FeaturesPlugin_Symmetry::initAttributes() +{ + data()->addAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD(), + ModelAPI_AttributeString::typeId()); + + AttributeSelectionListPtr aSelection = + std::dynamic_pointer_cast(data()->addAttribute( + FeaturesPlugin_Symmetry::OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId())); + + data()->addAttribute(FeaturesPlugin_Symmetry::POINT_OBJECT_ID(), + ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID(), + ModelAPI_AttributeSelection::typeId()); + + data()->addAttribute(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID(), + ModelAPI_AttributeSelection::typeId()); +} + +//================================================================================================= +void FeaturesPlugin_Symmetry::execute() +{ + AttributeStringPtr aMethodTypeAttr = string(FeaturesPlugin_Symmetry::CREATION_METHOD()); + std::string aMethodType = aMethodTypeAttr->value(); + + if (aMethodType == CREATION_METHOD_BY_POINT()) { + performSymmetryByPoint(); + } + + if (aMethodType == CREATION_METHOD_BY_AXIS()) { + performSymmetryByAxis(); + } + + if (aMethodType == CREATION_METHOD_BY_PLANE()) { + performSymmetryByPlane(); + } +} + +//================================================================================================= +void FeaturesPlugin_Symmetry::performSymmetryByPoint() +{ + // Getting objects. + ListOfShape anObjects; + std::list aContextes; + AttributeSelectionListPtr anObjectsSelList = + selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID()); + if (anObjectsSelList->size() == 0) { + return; + } + for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { + std::shared_ptr anObjectAttr = + anObjectsSelList->value(anObjectsIndex); + std::shared_ptr anObject = anObjectAttr->value(); + if(!anObject.get()) { // may be for not-activated parts + eraseResults(); + return; + } + anObjects.push_back(anObject); + aContextes.push_back(anObjectAttr->context()); + } + + //Getting point. + std::shared_ptr aPoint; + std::shared_ptr anObjRef = + selection(FeaturesPlugin_Symmetry::POINT_OBJECT_ID()); + if (anObjRef.get() != NULL) { + GeomShapePtr aShape1 = anObjRef->value(); + if (!aShape1.get()) { + aShape1 = anObjRef->context()->shape(); + } + if (aShape1) { + aPoint = GeomAlgoAPI_PointBuilder::point(aShape1); + } + } + + // Moving each object. + int aResultIndex = 0; + std::list::iterator aContext = aContextes.begin(); + for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); + anObjectsIt++, aContext++) { + std::shared_ptr aBaseShape = *anObjectsIt; + bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group(); + + // Setting result. + if (isPart) { + std::shared_ptr aTrsf(new GeomAPI_Trsf()); + aTrsf->setSymmetry(aPoint); + ResultPartPtr anOrigin = std::dynamic_pointer_cast(*aContext); + ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex); + aResultPart->setTrsf(*aContext, aTrsf); + setResult(aResultPart, aResultIndex); + } else { + GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, aPoint); + + if (!aSymmetryAlgo.check()) { + setError(aSymmetryAlgo.getError()); + return; + } + + aSymmetryAlgo.build(); + + // Checking that the algorithm worked properly. + if(!aSymmetryAlgo.isDone()) { + static const std::string aFeatureError = "Error: Symmetry algorithm failed."; + setError(aFeatureError); + break; + } + if(aSymmetryAlgo.shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + break; + } + if(!aSymmetryAlgo.isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + break; + } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aSymmetryAlgo, aResultBody, aBaseShape); + setResult(aResultBody, aResultIndex); + } + aResultIndex++; + } + + // Remove the rest results if there were produced in the previous pass. + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Symmetry::performSymmetryByAxis() +{ + // Getting objects. + ListOfShape anObjects; + std::list aContextes; + AttributeSelectionListPtr anObjectsSelList = + selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID()); + if (anObjectsSelList->size() == 0) { + return; + } + for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { + std::shared_ptr anObjectAttr = + anObjectsSelList->value(anObjectsIndex); + std::shared_ptr anObject = anObjectAttr->value(); + if(!anObject.get()) { // may be for not-activated parts + eraseResults(); + return; + } + anObjects.push_back(anObject); + aContextes.push_back(anObjectAttr->context()); + } + + //Getting axis. + std::shared_ptr anAxis; + std::shared_ptr anEdge; + std::shared_ptr anObjRef = + selection(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID()); + if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->value())); + } else if (anObjRef && !anObjRef->value() && anObjRef->context() && + anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) { + anEdge = std::shared_ptr(new GeomAPI_Edge(anObjRef->context()->shape())); + } + if(anEdge) { + anAxis = std::shared_ptr(new GeomAPI_Ax1(anEdge->line()->location(), + anEdge->line()->direction())); + } + + // Moving each object. + int aResultIndex = 0; + std::list::iterator aContext = aContextes.begin(); + for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); + anObjectsIt++, aContext++) { + std::shared_ptr aBaseShape = *anObjectsIt; + bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group(); + + // Setting result. + if (isPart) { + std::shared_ptr aTrsf(new GeomAPI_Trsf()); + aTrsf->setSymmetry(anAxis); + ResultPartPtr anOrigin = std::dynamic_pointer_cast(*aContext); + ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex); + aResultPart->setTrsf(*aContext, aTrsf); + setResult(aResultPart, aResultIndex); + } else { + GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, anAxis); + + if (!aSymmetryAlgo.check()) { + setError(aSymmetryAlgo.getError()); + return; + } + + aSymmetryAlgo.build(); + + // Checking that the algorithm worked properly. + if(!aSymmetryAlgo.isDone()) { + static const std::string aFeatureError = "Error: Symmetry algorithm failed."; + setError(aFeatureError); + break; + } + if(aSymmetryAlgo.shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + break; + } + if(!aSymmetryAlgo.isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + break; + } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aSymmetryAlgo, aResultBody, aBaseShape); + setResult(aResultBody, aResultIndex); + } + aResultIndex++; + } + + // Remove the rest results if there were produced in the previous pass. + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Symmetry::performSymmetryByPlane() +{ + // Getting objects. + ListOfShape anObjects; + std::list aContextes; + AttributeSelectionListPtr anObjectsSelList = + selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID()); + if (anObjectsSelList->size() == 0) { + return; + } + for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) { + std::shared_ptr anObjectAttr = + anObjectsSelList->value(anObjectsIndex); + std::shared_ptr anObject = anObjectAttr->value(); + if(!anObject.get()) { // may be for not-activated parts + eraseResults(); + return; + } + anObjects.push_back(anObject); + aContextes.push_back(anObjectAttr->context()); + } + + //Getting axis. + std::shared_ptr aPlane; + std::shared_ptr aPln; + std::shared_ptr anObjRef = + selection(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID()); + if(anObjRef && anObjRef->value() && anObjRef->value()->isFace()) { + aPln = std::shared_ptr(new GeomAPI_Face(anObjRef->value()))->getPlane(); + } + else if (anObjRef && !anObjRef->value() && anObjRef->context() && + anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) { + aPln = + std::shared_ptr(new GeomAPI_Face(anObjRef->context()->shape()))->getPlane(); + } + if(aPln) { + aPlane = std::shared_ptr(new GeomAPI_Ax2(aPln->location(), + aPln->direction())); + } + + // Moving each object. + int aResultIndex = 0; + std::list::iterator aContext = aContextes.begin(); + for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); + anObjectsIt++, aContext++) { + std::shared_ptr aBaseShape = *anObjectsIt; + bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group(); + + // Setting result. + if (isPart) { + std::shared_ptr aTrsf(new GeomAPI_Trsf()); + aTrsf->setSymmetry(aPlane); + ResultPartPtr anOrigin = std::dynamic_pointer_cast(*aContext); + ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex); + aResultPart->setTrsf(*aContext, aTrsf); + setResult(aResultPart, aResultIndex); + } else { + GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, aPlane); + + if (!aSymmetryAlgo.check()) { + setError(aSymmetryAlgo.getError()); + return; + } + + aSymmetryAlgo.build(); + + // Checking that the algorithm worked properly. + if(!aSymmetryAlgo.isDone()) { + static const std::string aFeatureError = "Error: Symmetry algorithm failed."; + setError(aFeatureError); + break; + } + if(aSymmetryAlgo.shape()->isNull()) { + static const std::string aShapeError = "Error: Resulting shape is Null."; + setError(aShapeError); + break; + } + if(!aSymmetryAlgo.isValid()) { + std::string aFeatureError = "Error: Resulting shape is not valid."; + setError(aFeatureError); + break; + } + + ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); + loadNamingDS(aSymmetryAlgo, aResultBody, aBaseShape); + setResult(aResultBody, aResultIndex); + } + aResultIndex++; + } + + // Remove the rest results if there were produced in the previous pass. + removeResults(aResultIndex); +} + +//================================================================================================= +void FeaturesPlugin_Symmetry::loadNamingDS(GeomAlgoAPI_Symmetry& theSymmetryAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBaseShape) +{ + // Store and name the result. + theResultBody->storeModified(theBaseShape, theSymmetryAlgo.shape()); + + // Name the faces + std::shared_ptr aSubShapes = theSymmetryAlgo.mapOfSubShapes(); + int aReflectedTag = 1; + std::string aReflectedName = "Symmetried"; + theResultBody->loadAndOrientModifiedShapes(&theSymmetryAlgo, + theBaseShape, GeomAPI_Shape::FACE, + aReflectedTag, aReflectedName, *aSubShapes.get()); +} diff --git a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h new file mode 100644 index 000000000..988f58339 --- /dev/null +++ b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h @@ -0,0 +1,117 @@ +// Copyright (C) 2014-2016 CEA/DEN, EDF R&D + +// File: FeaturesPlugin_Symmetry.h +// Created: 30 Nov 2016 +// Author: Clarisse Genrault (CEA) + +#ifndef FEATURESPLUGIN_SYMMETRY_H_ +#define FEATURESPLUGIN_SYMMETRY_H_ + +#include + +#include + +#include + +/** \class FeaturesPlugin_Symmetry + * \ingroup Plugins + * \brief Feature that performs reflection with respect to a point, axis, or plane. + */ +class FeaturesPlugin_Symmetry : public ModelAPI_Feature +{ + public: + /// Symmetry kind. + inline static const std::string& ID() + { + static const std::string MY_SYMMETRY("Symmetry"); + return MY_SYMMETRY; + } + + /// Attribute name for creation method. + inline static const std::string& CREATION_METHOD() + { + static const std::string MY_CREATION_METHOD_ID("CreationMethod"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name for creation method "ByAxisAndDistance". + inline static const std::string& CREATION_METHOD_BY_POINT() + { + static const std::string MY_CREATION_METHOD_ID("ByPoint"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name for creation method "ByDimensions". + inline static const std::string& CREATION_METHOD_BY_AXIS() + { + static const std::string MY_CREATION_METHOD_ID("ByAxis"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name for creation method "ByTwoPoints". + inline static const std::string& CREATION_METHOD_BY_PLANE() + { + static const std::string MY_CREATION_METHOD_ID("ByPlane"); + return MY_CREATION_METHOD_ID; + } + + /// Attribute name of referenced objects. + inline static const std::string& OBJECTS_LIST_ID() + { + static const std::string MY_OBJECTS_LIST_ID("main_objects"); + return MY_OBJECTS_LIST_ID; + } + + /// Attribute name of a point. + inline static const std::string& POINT_OBJECT_ID() + { + static const std::string MY_POINT_OBJECT_ID("point_object"); + return MY_POINT_OBJECT_ID; + } + + /// Attribute name of an axis. + inline static const std::string& AXIS_OBJECT_ID() + { + static const std::string MY_AXIS_OBJECT_ID("axis_object"); + return MY_AXIS_OBJECT_ID; + } + + /// Attribute name of a plane. + inline static const std::string& PLANE_OBJECT_ID() + { + static const std::string MY_PLANE_OBJECT_ID("plane_object"); + return MY_PLANE_OBJECT_ID; + } + + /// \return the kind of a feature. + FEATURESPLUGIN_EXPORT virtual const std::string& getKind() + { + static std::string MY_KIND = FeaturesPlugin_Symmetry::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_Symmetry(); + +private: + ///Perform symmetry with respect to a point. + void performSymmetryByPoint(); + + ///Perform symmetry with respect to an axis. + void performSymmetryByAxis(); + + ///Perform symmetry with respect to a plane. + void performSymmetryByPlane(); + + void loadNamingDS(GeomAlgoAPI_Symmetry& theSymmetryAlgo, + std::shared_ptr theResultBody, + std::shared_ptr theBaseShape); +}; + +#endif // FEATURESPLUGIN_SYMMETRY_H_ diff --git a/src/FeaturesPlugin/icons/point.png b/src/FeaturesPlugin/icons/point.png new file mode 100755 index 0000000000000000000000000000000000000000..96149ebf38492cc735949b52e2f0233e28cb8a6d GIT binary patch literal 486 zcmV@P)r|oM}L_)mw{R1YGm^+A96WV99nutv- zVj-INF|ZiKU@_R5#v)C-86+kN|AOEdbV9YhW8gJaRg${NH=KL#Ip6)xmrF_LBtjjr z|3e_sDj9b(NstQ+>cTU_+`22|uA6(=?17V-UI9!`tk$>o5-Cqnx_y4*Rn+39gbTlz zJN!bBR6hwf?Z(~AYJlyr^l`%VHUb=X(+AGz!w)3Fk zSiPQ;@{#~Ras<$zlk&PhZeU(StdUTkfFuFQ7}`d%jbuZJ0*D2eAq_N7RTq#XfH6Ng zyziItGkz&QBj_C9Nq{S`3Lsuv3VfPy6hFIM`pJVRs_O=3uQB)S8x!N+mJG@d{nobq zSe>WQO_%9AeF~Seq;Bqt`Q5ex0N}XO69Q&Q)dYk<3I;p(rQCUQZ%cuCk)(dvwzdL) ciH?`)9SSJ2sp2ZYhyVZp07*qoM6N<$f=AuWpa1{> literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/icons/symmetry.png b/src/FeaturesPlugin/icons/symmetry.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc73b21c6ba777e2d34bf1ca02e7faa26641739 GIT binary patch literal 429 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4k`yBP298+q#7n`U5;QrZj_SVMt8yu&)sy?k$RqIdnx^`;A&Xl5t zf6^k`%2Z!`=V)r^iw`gSeCF0Rg)Rf0mp{z4J{_$69n9joU3x=($%GeAw(nCu2H;v;RnV;-kb;tI{n)MYEpWM;$@#E1J z{uCF=@a5?1b`FDgJ0dSL1$;D%h?BVU?Z+FDxwB6#oh7Z`WGq%&93y`GZ*E%4jf!XW z0^!}$DqOXtlbq~TtyK?hTlmv#&y8zlyFzB1lMz-pn;w%WBB>Z>Cd%CNQeq$Dftmi7 U-Je~30SsCOPgg&ebxsLQ0Np~YJOBUy literal 0 HcmV?d00001 diff --git a/src/FeaturesPlugin/icons/symmetry_axis_32x32.png b/src/FeaturesPlugin/icons/symmetry_axis_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..3873378cfd45d391dfbafbf13340e11b39d41d8b GIT binary patch literal 586 zcmV-Q0=4~#P)Hap~B@En|y{0DYZ zD8&@Am@J_w6qU9$9C+CeS_p3iW@5Z}+{&F)$K<5V^n_uv}+39F3I%P#B0k(>T zIUwR>(viT<%ODw_uV_z@!V0hsycKW(p2QPLV8J)_X3%0M1`UMJGhhdpH!Uzs_|O_A z{1Z?HE=>yzeAR*^@R{~uEaT2c0hzIV=Kn8Tpe`T+&b@~#tSFQe=1gl?&}O+HRe<_h z-pjn(4RdV=GIeeVcb8IU%^%pgzr&NOxov@-uh2ixlHaiQYr7TTm(LILI6^_@edSHh zUD+xY767p@1Wj1T%*;Gm>|-lDKxW*+#~v~dI~fz*?@mTlE1mNZ>||=8I~S4i`RQ@F zyO5zEBQ>XS^ukKGiK(Eeu8V#)GFt!>jw7h*mZY){`)L2Tkeg0%*NgB3UrptR|7rwFJ0~5 zo*nzCL>517X!`&**@=nWZnNOAf%N2@ID4ng4FJ^}5a1>@<-xkaF*e8;lv zLf?hK7Cbhfy~yg7z)2ttB0MmxHyDI?%t^rqo2f%3se%7C}#ON_Wh8nqTi7}jik(#P#by56rdJh;-#Oz98k9SQMU(GS3=!0j;1e*qfS>mL2|zpC+6Ka+@y=UNRy9Bk;2psF87iCsZ;Q{Kz>O6^)ZNLA z$AbRw3Oq7*)I*!(uwDzCn9@3vun!z8);-{P)qzel$W_)FAk*^~+j}aph)f1mmAw7~sv1`@if0I4^9+Q*rYT57l4&|| c-qO + + + diff --git a/src/FeaturesPlugin/symmetry_widget.xml b/src/FeaturesPlugin/symmetry_widget.xml new file mode 100644 index 000000000..2d253500e --- /dev/null +++ b/src/FeaturesPlugin/symmetry_widget.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/GeomAPI/GeomAPI_Trsf.cpp b/src/GeomAPI/GeomAPI_Trsf.cpp index 322c14b90..21a972872 100644 --- a/src/GeomAPI/GeomAPI_Trsf.cpp +++ b/src/GeomAPI/GeomAPI_Trsf.cpp @@ -9,9 +9,11 @@ #include #include +#include #include -#include +#include +#include #define MY_TRSF implPtr() @@ -53,3 +55,21 @@ void GeomAPI_Trsf::setRotation(const std::shared_ptr theAxis, { MY_TRSF->SetRotation(theAxis->impl(), theAngle / 180.0 * M_PI); } + +//================================================================================================= +void GeomAPI_Trsf::setSymmetry(const std::shared_ptr thePoint) +{ + MY_TRSF->SetMirror(thePoint->impl()); +} + +//================================================================================================= +void GeomAPI_Trsf::setSymmetry(const std::shared_ptr theAxis) +{ + MY_TRSF->SetMirror(theAxis->impl()); +} + +//================================================================================================= +void GeomAPI_Trsf::setSymmetry(const std::shared_ptr thePlane) +{ + MY_TRSF->SetMirror(thePlane->impl()); +} diff --git a/src/GeomAPI/GeomAPI_Trsf.h b/src/GeomAPI/GeomAPI_Trsf.h index ed97f4beb..9f7a7f811 100644 --- a/src/GeomAPI/GeomAPI_Trsf.h +++ b/src/GeomAPI/GeomAPI_Trsf.h @@ -13,6 +13,7 @@ #include class GeomAPI_Ax1; +class GeomAPI_Ax2; class GeomAPI_Pnt; /**\class GeomAPI_Trsf @@ -57,6 +58,21 @@ class GeomAPI_Trsf : public GeomAPI_Interface */ GEOMAPI_EXPORT void setRotation(const std::shared_ptr theAxis, const double theAngle); + + /** \brief Sets a point symmetry transformation. + * \param[in] thePoint symmetry point. + */ + GEOMAPI_EXPORT void setSymmetry(const std::shared_ptr thePoint); + + /** \brief Sets an axis symmetry transformation. + * \param[in] theAxis symmetry axis. + */ + GEOMAPI_EXPORT void setSymmetry(const std::shared_ptr theAxis); + + /** \brief Sets a plane symmetry transformation. + * \param[in] thePlane symmetry plane. + */ + GEOMAPI_EXPORT void setSymmetry(const std::shared_ptr thePlane); }; #endif diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index d79ee1466..96ba617a9 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -47,6 +47,7 @@ SET(PROJECT_HEADERS GeomAlgoAPI_XAOImport.h GeomAlgoAPI_Copy.h GeomAlgoAPI_ConeSegment.h + GeomAlgoAPI_Symmetry.h ) SET(PROJECT_SOURCES @@ -89,6 +90,7 @@ SET(PROJECT_SOURCES GeomAlgoAPI_XAOImport.cpp GeomAlgoAPI_Copy.cpp GeomAlgoAPI_ConeSegment.cpp + GeomAlgoAPI_Symmetry.cpp ) SET(PROJECT_LIBRARIES @@ -155,5 +157,6 @@ INSTALL(FILES ${SWIG_SCRIPTS} DESTINATION ${SHAPER_INSTALL_SWIG}) ADD_UNIT_TESTS(TestAPI_Box.py TestAPI_GDMLConeSegment.py + TestAPI_Symmetry.py TestAPI_Translation.py) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI.i b/src/GeomAlgoAPI/GeomAlgoAPI.i index 3476e73f2..6ba7fc781 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI.i +++ b/src/GeomAlgoAPI/GeomAlgoAPI.i @@ -36,6 +36,7 @@ %shared_ptr(GeomAlgoAPI_Box) %shared_ptr(GeomAlgoAPI_ConeSegment) %shared_ptr(GeomAlgoAPI_Copy) +%shared_ptr(GeomAlgoAPI_Symmetry) // all supported interfaces %include "GeomAlgoAPI_MakeShape.h" @@ -72,6 +73,7 @@ %include "GeomAlgoAPI_Exception.h" %include "GeomAlgoAPI_ShapeAPI.h" %include "GeomAlgoAPI_Copy.h" +%include "GeomAlgoAPI_Symmetry.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_ShapeAPI.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp index d778964e8..185a2ca8b 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp @@ -9,13 +9,9 @@ #include #include #include +#include #include -#include -#include - -//#include - namespace GeomAlgoAPI_ShapeAPI { //======================================================================================= @@ -132,6 +128,72 @@ namespace GeomAlgoAPI_ShapeAPI return aTranslationAlgo.shape(); } + //========================================================================================================= + std::shared_ptr GeomAlgoAPI_ShapeAPI::makeSymmetry( + std::shared_ptr theSourceShape, + std::shared_ptr thePoint) throw (GeomAlgoAPI_Exception) + { + GeomAlgoAPI_Symmetry aSymmetryAlgo(theSourceShape, thePoint); + + if (!aSymmetryAlgo.check()) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + + aSymmetryAlgo.build(); + + if(!aSymmetryAlgo.isDone()) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + if (!aSymmetryAlgo.checkValid("Symmetry builder by a point")) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + return aSymmetryAlgo.shape(); + } + + //========================================================================================================= + std::shared_ptr GeomAlgoAPI_ShapeAPI::makeSymmetry( + std::shared_ptr theSourceShape, + std::shared_ptr theAxis) throw (GeomAlgoAPI_Exception) + { + GeomAlgoAPI_Symmetry aSymmetryAlgo(theSourceShape, theAxis); + + if (!aSymmetryAlgo.check()) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + + aSymmetryAlgo.build(); + + if(!aSymmetryAlgo.isDone()) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + if (!aSymmetryAlgo.checkValid("Symmetry builder by an axis")) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + return aSymmetryAlgo.shape(); + } + + //========================================================================================================= + std::shared_ptr GeomAlgoAPI_ShapeAPI::makeSymmetry( + std::shared_ptr theSourceShape, + std::shared_ptr thePlane) throw (GeomAlgoAPI_Exception) + { + GeomAlgoAPI_Symmetry aSymmetryAlgo(theSourceShape, thePlane); + + if (!aSymmetryAlgo.check()) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + + aSymmetryAlgo.build(); + + if(!aSymmetryAlgo.isDone()) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + if (!aSymmetryAlgo.checkValid("Symmetry builder by a plane")) { + throw GeomAlgoAPI_Exception(aSymmetryAlgo.getError()); + } + return aSymmetryAlgo.shape(); + } + //========================================================================================================= std::shared_ptr GeomAlgoAPI_ShapeAPI::makeConeSegment( const double theRMin1, const double theRMax1, diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.h b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.h index 92f057444..da69e20d4 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.h @@ -8,6 +8,7 @@ #define GEOMALGOAPI_SHAPEAPI_H #include +#include #include #include #include @@ -69,6 +70,21 @@ public: std::shared_ptr theSourceShape, std::shared_ptr theStartPoint, std::shared_ptr theEndPoint) throw (GeomAlgoAPI_Exception); + + /// Performs a symmetry by a point + static std::shared_ptr makeSymmetry( + std::shared_ptr theSourceShape, + std::shared_ptr thePoint) throw (GeomAlgoAPI_Exception); + + /// Performs a symmetry by an axis + static std::shared_ptr makeSymmetry( + std::shared_ptr theSourceShape, + std::shared_ptr theAxis) throw (GeomAlgoAPI_Exception); + + /// Performs a symmetry by a plane + static std::shared_ptr makeSymmetry( + std::shared_ptr theSourceShape, + std::shared_ptr thePlane) throw (GeomAlgoAPI_Exception); /// Creates a cone segment using standard GDML parameters /// \param theRMin1 Inner radius at base of cone diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.cpp new file mode 100644 index 000000000..e8f4db197 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.cpp @@ -0,0 +1,137 @@ +// Copyright (C) 2014-2016 CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Symmetry.cpp +// Created: 30 Nov 2016 +// Author: Clarisse Genrault (CEA) + +#include "GeomAlgoAPI_Symmetry.h" + +#include + +//================================================================================================= +GeomAlgoAPI_Symmetry::GeomAlgoAPI_Symmetry(std::shared_ptr theSourceShape, + std::shared_ptr thePoint) +{ + myMethodType = BY_POINT; + mySourceShape = theSourceShape; + myPoint = thePoint; +} + +//================================================================================================= +GeomAlgoAPI_Symmetry::GeomAlgoAPI_Symmetry(std::shared_ptr theSourceShape, + std::shared_ptr theAxis) +{ + myMethodType = BY_AXIS; + mySourceShape = theSourceShape; + myAxis = theAxis; +} + +//================================================================================================= +GeomAlgoAPI_Symmetry::GeomAlgoAPI_Symmetry(std::shared_ptr theSourceShape, + std::shared_ptr thePlane) +{ + myMethodType = BY_PLANE; + mySourceShape = theSourceShape; + myPlane = thePlane; +} + +//================================================================================================= +bool GeomAlgoAPI_Symmetry::check() +{ + switch (myMethodType) { + case BY_POINT: { + if (!myPoint) { + myError = "Mirror builder :: point is invalid."; + return false; + } + if (!mySourceShape) { + myError = "Mirror builder :: source shape is invalid."; + return false; + } + return true; + } + case BY_AXIS: { + if (!myAxis) { + myError = "Mirror builder :: axis is invalid."; + return false; + } + if (!mySourceShape) { + myError = "Mirror builder :: source shape is invalid."; + return false; + } + return true; + } + case BY_PLANE: { + if (!myPlane) { + myError = "Mirror builder :: plane is invalid."; + return false; + } + if (!mySourceShape) { + myError = "Translation builder :: source shape is invalid."; + return false; + } + return true; + } + default: { + myError = "Translation builder :: method not implemented."; + return false; + } + } +} + +//================================================================================================= +void GeomAlgoAPI_Symmetry::build() +{ + gp_Trsf* aTrsf = new gp_Trsf(); + + switch (myMethodType) { + case BY_POINT: { + const gp_Pnt& aPoint = myPoint->impl(); + aTrsf->SetMirror(aPoint); + break; + } + case BY_AXIS: { + const gp_Ax1& anAxis = myAxis->impl(); + aTrsf->SetMirror(anAxis); + break; + } + case BY_PLANE: { + const gp_Ax2& aPlane = myPlane->impl(); + aTrsf->SetMirror(aPlane); + break; + } + default: { + myError = "Mirror builder :: method not supported"; + return; + } + } + + const TopoDS_Shape& aSourceShape = mySourceShape->impl(); + + if(aSourceShape.IsNull()) { + myError = "Mirror builder :: source shape does not contain any actual shape."; + return; + } + + // Transform the shape while copying it. + BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, *aTrsf, true); + if(!aBuilder) { + myError = "Mirror builder :: source shape does not contain any actual shape."; + return; + } + + setImpl(aBuilder); + setBuilderType(OCCT_BRepBuilderAPI_MakeShape); + + if(!aBuilder->IsDone()) { + myError = "Mirror builder :: source shape does not contain any actual shape."; + return; + } + + TopoDS_Shape aResult = aBuilder->Shape(); + + std::shared_ptr aShape(new GeomAPI_Shape()); + aShape->setImpl(new TopoDS_Shape(aResult)); + setShape(aShape); + setDone(true); +} \ No newline at end of file diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.h b/src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.h new file mode 100644 index 000000000..955e06ad6 --- /dev/null +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Symmetry.h @@ -0,0 +1,66 @@ +// Copyright (C) 2014-2016 CEA/DEN, EDF R&D + +// File: GeomAlgoAPI_Symmetry.h +// Created: 30 Nov 2016 +// Author: Clarisse Genrault (CEA) + +#ifndef GEOMALGOAPI_SYMMETRY_H_ +#define GEOMALGOAPI_SYMMETRY_H_ + +#include +#include + +#include +#include +#include + +/// \class GeomAlgoAPI_Symmetry +/// \ingroup DataAlgo +/// \brief Creates a copy of the object by performing a symmetry operation by a point, +/// by an axis or by a plane. +class GeomAlgoAPI_Symmetry : public GeomAlgoAPI_MakeShape +{ +public: + /// Type of mirror operation + enum MethodType { + BY_POINT, ///< Mirror by point. + BY_AXIS, ///< Mirror by axis. + BY_PLANE ///< Mirror by plane. + }; + + /// \brief Creates an object which is obtained from current object by performing + /// a symmetry operation by a point. + /// \param[in] theSourceShape a shape to be moved. + /// \param[in] thePoint symmetry point. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Symmetry(std::shared_ptr theSourceShape, + std::shared_ptr thePoint); + + /// \brief Creates an object which is obtained from current object by performing + /// a symmetry operation by a point. + /// \param[in] theSourceShape a shape to be moved. + /// \param[in] theAxis symmetry axis. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Symmetry(std::shared_ptr theSourceShape, + std::shared_ptr theAxis); + + /// \brief Creates an object which is obtained from current object by performing + /// a symmetry operation by a point. + /// \param[in] theSourceShape a shape to be moved. + /// \param[in] thePlane symmetry plane. + GEOMALGOAPI_EXPORT GeomAlgoAPI_Symmetry(std::shared_ptr theSourceShape, + std::shared_ptr thePlane); + + /// Checks if data for the translation execution is OK. + GEOMALGOAPI_EXPORT bool check(); + + /// Execute the translation. + GEOMALGOAPI_EXPORT void build(); + +private: + MethodType myMethodType; /// Type of method used. + std::shared_ptr mySourceShape; /// Shape to be moved. + std::shared_ptr myPoint; /// Reflection point. + std::shared_ptr myAxis; /// Reflection axis. + std::shared_ptr myPlane; /// Reflection plane. +}; + +#endif // GEOMALGOAPI_SYMMETRY_H_ diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h index e39352b1e..b759eebd4 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_swig.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_swig.h @@ -47,6 +47,7 @@ #include "GeomAlgoAPI_Box.h" #include "GeomAlgoAPI_ConeSegment.h" #include "GeomAlgoAPI_Copy.h" + #include "GeomAlgoAPI_Symmetry.h" #include #include diff --git a/src/GeomAlgoAPI/Test/TestAPI_Symmetry.py b/src/GeomAlgoAPI/Test/TestAPI_Symmetry.py new file mode 100644 index 000000000..409d39863 --- /dev/null +++ b/src/GeomAlgoAPI/Test/TestAPI_Symmetry.py @@ -0,0 +1,48 @@ +# Copyright (C) 2014-2016 CEA/DEN, EDF R&D + +# File: TestAPI_Symmetry.py +# Created: 15 Nov 2016 +# Author: Clarisse Genrault (CEA) + +from GeomAlgoAPI import GeomAlgoAPI_ShapeAPI as shaperpy +from GeomAlgoAPI import GeomAlgoAPI_Exception as myExcept +from GeomAPI import GeomAPI_Ax1 as axis +from GeomAPI import GeomAPI_Ax2 as plane +from GeomAPI import GeomAPI_Pnt as pnt +from GeomAPI import GeomAPI_Dir as direction + +# Create a box +try : + box1 = shaperpy.makeBox(10.,10.,10.) + box2 = shaperpy.makeBox(10.,10.,10.) + box3 = shaperpy.makeBox(10.,10.,10.) + +except myExcept, ec: + print ec.what() + +# Perfom a symmetry by a point. +try : + origin = pnt(0.,0.,0.) + symmetry1 = shaperpy.makeSymmetry(box1,origin) + +except myExcept, ec: + print ec.what() + +# Perfom a symmetry by an axis. +try : + xDir = direction(1.,0.,0.) + xAxis = axis(origin, xDir) + translation2 = shaperpy.makeSymmetry(box2,xAxis) + +except myExcept, ec: + print ec.what() + +# Perfom a symmetry by a plane. +try : + pnt1 = pnt(0.,0.,10.) + pnt2 = pnt(10.,0.,10.) + aPlane = plane(origin, xDir) + translation3 = shaperpy.makeSymmetry(box3,aPlane) + +except myExcept, ec: + print ec.what() diff --git a/src/PythonAPI/model/features/__init__.py b/src/PythonAPI/model/features/__init__.py index 90c7d95fc..07471e912 100644 --- a/src/PythonAPI/model/features/__init__.py +++ b/src/PythonAPI/model/features/__init__.py @@ -1,7 +1,7 @@ """Package for Features plugin for the Parametric Geometry API of the Modeler. """ -from FeaturesAPI import addPlacement, addRotation, addTranslation +from FeaturesAPI import addPlacement, addRotation, addSymmetry, addTranslation from FeaturesAPI import addExtrusion, addExtrusionCut, addExtrusionFuse from FeaturesAPI import addRevolution, addRevolutionCut, addRevolutionFuse from FeaturesAPI import addPipe -- 2.39.2